{"id":26466065,"url":"https://github.com/urfnet/urf.core.sample.v3","last_synced_at":"2026-04-16T13:36:23.258Z","repository":{"id":56136232,"uuid":"206605837","full_name":"urfnet/URF.Core.Sample.v3","owner":"urfnet","description":"Sample using Unit of Work and Repository Framework (URF) with ASP.NET Core 3.0","archived":false,"fork":false,"pushed_at":"2020-11-24T22:56:46.000Z","size":25,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-04-16T01:07:35.202Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/urfnet.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-09-05T16:09:35.000Z","updated_at":"2024-04-16T01:07:35.203Z","dependencies_parsed_at":"2022-08-15T13:20:56.877Z","dependency_job_id":null,"html_url":"https://github.com/urfnet/URF.Core.Sample.v3","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfnet%2FURF.Core.Sample.v3","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfnet%2FURF.Core.Sample.v3/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfnet%2FURF.Core.Sample.v3/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urfnet%2FURF.Core.Sample.v3/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/urfnet","download_url":"https://codeload.github.com/urfnet/URF.Core.Sample.v3/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244413483,"owners_count":20448711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-19T11:18:22.077Z","updated_at":"2026-04-16T13:36:23.211Z","avatar_url":"https://github.com/urfnet.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# URF Core 3.x Demo\n\nSample using Unit of Work and Repository Framework (URF) with ASP.NET Core 3.x\n\n## Prerequisites\n\n- .NET Core SDK (https://dotnet.microsoft.com/download/dotnet-core)\n- EF Core CLI (specify current version)\n    ```\n    dotnet tool uninstall --global dotnet-ef\n    dotnet tool install --global dotnet-ef\n    ```\n\n## EF Core Code First\n\n1. Create `Models` .NET Standard 2.1 class library.\n\n2. Add `Product` class.\n    ```csharp\n    public class Product\n    {\n        public int Id { get; set; }\n        public string ProductName { get; set; }\n        public decimal UnitPrice { get; set; }\n    }\n    ```\n\n3. Create `EF` .NET Core class library.\n   - Reference the Models project.\n   - Add NuGet packages:\n     - URF.Core.EF\n     - Microsoft.EntityFrameworkCore.SqlServer\n     - Microsoft.EntityFrameworkCore.Design\n\n4. Add `UrfSampleContext` class that extends `DbContext`\n   - Add Contexts folder.\n  \n    ```csharp\n    public class UrfSampleContext : DbContext\n    {\n        public UrfSampleContext(DbContextOptions\u003cUrfSampleContext\u003e options) : base(options) { }\n\n        public DbSet\u003cProduct\u003e Products { get; set; }\n    }\n    ```\n\n5. Add `UrfSampleContextFactory` class that implements `IDesignTimeDbContextFactory\u003cUrfSampleContext\u003e`\n\n    ```csharp\n    public class UrfSampleContextFactory : IDesignTimeDbContextFactory\u003cUrfSampleContext\u003e\n    {\n        public UrfSampleContext CreateDbContext(string[] args)\n        {\n            var optionsBuilder = new DbContextOptionsBuilder\u003cUrfSampleContext\u003e();\n            optionsBuilder.UseSqlServer(@\"Data Source=(localdb)\\MSSQLLocalDB;initial catalog=UrfSample;Integrated Security=True; MultipleActiveResultSets=True\");\n            return new UrfSampleContext(optionsBuilder.Options);\n        }\n    }\n    ```\n\n6. Add code to `UrfSampleContext` to seed data the database.\n\n    ```csharp\n    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        modelBuilder.Entity\u003cProduct\u003e().HasData(\n            new Product { Id = 1, ProductName = \"Chai\", UnitPrice = 1 },\n            new Product { Id = 2, ProductName = \"Chang\", UnitPrice = 2},\n            new Product { Id = 3, ProductName = \"Cappuccino\", UnitPrice = 3 }\n        );\n    }\n    ```\n\n7. Open command prompt at EF project directory and add an EF migration.\n\n    ```\n    dotnet ef migrations add initial\n    ```\n\n8.  Apply the EF migration to the database\n\n    ```\n    dotnet ef database update\n    ```\n\n## URF.Core Unit of Work\n\n1. Create `Abstractions` .NET Standard 2.1 class library.\n   - Reference the Models project.\n   - Add URF.Core.Abstractions package.\n   - Add `IUrfSampleUnitOfWork` interface that extends `IUnitOfWork` and adds `ProductsRepository` property.\n    ```csharp\n    public interface IUrfSampleUnitOfWork : IUnitOfWork\n    {\n        public IRepository\u003cProduct\u003e ProductsRepository { get; }\n    }\n    ```\n\n2. In the `EF` project add a reference to the `Abstractions` project.\n   - Add `UnitsOfWork` folder.\n   - Create a `UrfSampleUnitOfWork` class that extends `UnitOfWork` and implements `IUrfSampleUnitOfWork`.\n\n    ```csharp\n    public class UrfSampleUnitOfWork : UnitOfWork, IUrfSampleUnitOfWork\n    {\n        public UrfSampleUnitOfWork(DbContext context, IRepository\u003cProduct\u003e productsRepository) : base(context)\n        {\n            ProductsRepository = productsRepository;\n        }\n\n        public IRepository\u003cProduct\u003e ProductsRepository { get; }\n    }\n    ```\n\n## Web API with URF.Core\n\n1. Add a new ASP.NET Core Web API project\n   - Remove `WeatherForecast` and `WeatherForecastController` classes.\n   - Add NuGet packages:\n     - Microsoft.EntityFrameworkCore.SqlServer\n     - URF.Core.EF\n   - Reference Models, Abstractions and EF projects.\n\n2. Add a connection string to appsettings.json.\n\n    ```json\n    \"ConnectionStrings\": {\n    \"UrfSampleContext\": \"Data Source=(localdb)\\\\MSSQLLocalDB;initial catalog=UrfSample;Integrated Security=True; MultipleActiveResultSets=True\"\n    }\n    ```\n\n3. Register services in `Startup.ConfigureServices`.\n\n    ```csharp\n    public void ConfigureServices(IServiceCollection services)\n    {\n        services.AddControllers();\n        var connectionString = Configuration.GetConnectionString(nameof(UrfSampleContext));\n        services.AddDbContext\u003cUrfSampleContext\u003e(options =\u003e options.UseSqlServer(connectionString));\n        services.AddScoped\u003cDbContext, UrfSampleContext\u003e();\n        services.AddScoped\u003cIUrfSampleUnitOfWork, UrfSampleUnitOfWork\u003e();\n        services.AddScoped\u003cIRepository\u003cProduct\u003e, Repository\u003cProduct\u003e\u003e();\n    }\n    ```\n\n4. Add a `ProductController` controller.\n\n    ```csharp\n    [Route(\"api/[controller]\")]\n    [ApiController]\n    public class ProductController : ControllerBase\n    {\n        public IUrfSampleUnitOfWork UnitOfWork { get; }\n\n        public ProductController(IUrfSampleUnitOfWork unitOfWork)\n        {\n            UnitOfWork = unitOfWork;\n        }\n\n        // GET: api/Product\n        [HttpGet]\n        public async Task\u003cActionResult\u003cIEnumerable\u003cProduct\u003e\u003e\u003e GetProduct()\n        {\n            var products = await UnitOfWork.ProductsRepository.Queryable().ToListAsync();\n            return Ok(products);\n        }\n\n        // GET: api/Produc/5\n        [HttpGet(\"{id}\")]\n        public async Task\u003cActionResult\u003cProduct\u003e\u003e GetProduct(int id)\n        {\n            var product = await UnitOfWork.ProductsRepository.FindAsync(id);\n            if (product == null)\n                return NotFound();\n            return product;\n        }\n\n        // PUT: api/Produc/5\n        [HttpPut(\"{id}\")]\n        public async Task\u003cIActionResult\u003e PutProduct(int id, Product product)\n        {\n            if (id != product.Id)\n                return BadRequest();\n\n            UnitOfWork.ProductsRepository.Update(product);\n\n            try\n            {\n                await UnitOfWork.SaveChangesAsync();\n            }\n            catch (DbUpdateConcurrencyException)\n            {\n                if (!await ProductExists(id))\n                    return NotFound();\n                else\n                    throw;\n            }\n            return Ok(product);\n        }\n\n        // POST: api/Product\n        [HttpPost]\n        public async Task\u003cActionResult\u003cProduct\u003e\u003e PostProduct(Product product)\n        {\n            UnitOfWork.ProductsRepository.Insert(product);\n            await UnitOfWork.SaveChangesAsync();\n            return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);\n        }\n\n        // DELETE: api/Product/5\n        [HttpDelete(\"{id}\")]\n        public async Task\u003cActionResult\u003e DeleteProduct(int id)\n        {\n            var result = await UnitOfWork.ProductsRepository.DeleteAsync(id);\n            if (!result)\n                return NotFound();\n            await UnitOfWork.SaveChangesAsync();\n            return NoContent();\n        }\n\n        private async Task\u003cbool\u003e ProductExists(int id)\n        {\n            return await UnitOfWork.ProductsRepository.ExistsAsync(id);\n        }\n    }\n    ```\n\n5. Update `launchSettings.json` in the Properties folder.\n   - Replace `weatherforecast` with `api/product`.\n   - Set the `Api` project as the startup project.\n   - Select `URF.Core.Sample.v3.Api` for debugging and press F5.\n\n6. Start the Web API project and test with Postman.\n   - Turn off 'SSL certificate verification' in Settings \u003e General\n\n    ```\n    GET: https://localhost:5001/api/product\n    GET: https://localhost:5001/api/product/1\n    ```\n    ```\n    POST: https://localhost:5001/api/product\n    ```\n    ```json\n    {\n        \"productName\": \"Chocolato\",\n        \"unitPrice\": 4.00\n    }\n    ```\n    - Should return 201 Created with correct Location response header.\n    ```\n    PUT: https://localhost:5001/api/product/4\n    ```\n    ```json\n    {\n        \"id\": 4,\n        \"productName\": \"Chocolato\",\n        \"unitPrice\": 5.00\n    }\n    ```\n    ```\n    DELETE: https://localhost:5001/api/product/4\n    ```\n    ```\n    GET: https://localhost:5001/api/product/4\n    ```\n    - Should return 404 Not Found.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furfnet%2Furf.core.sample.v3","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Furfnet%2Furf.core.sample.v3","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furfnet%2Furf.core.sample.v3/lists"}