Select Page
Entity Framework Core in ASP.NET Core 3.1

Entity Framework Core in ASP.NET Core 3.1

This article will be covering in detail the implementation of Entity Framework Core in ASP.NET Core Web API. We will learn about entity framework core in details i.e. what, how & why and see how to use it in ASP.NET Core Web API to implement CRUD operations. Though here we will be using entity framework in ASP.NET Core this can be implemented even in .NET Framework for your data persistence. I hope you will join me on this and go through step by step demonstration on implementing entity framework core in ASP.NET Core Web API.

Introduction to Entity Framework Core

ASP.NET Core Entity Framework

Entity Framework has been around since 2008 which has improved over the years. Entity framework core was introduced for .NET Core based applications. It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft. Entity framework core has been rewritten from scratch to make it lightweight, flexible & achieve better performance.

In the absence of an ORM typically lots of code have to be written to perform CRUD operations with the database. using an ORM like entity framework can reduce the number of lines of code to be written for database interactions. Typical ORM will work on classes & database tables of similar structure but entity framework core implements mappings which makes it a lot more flexible i.e. in case table & class does not match then mappings can be exercised to get from objects to tables.

Entity framework core can work with wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third party providers some commercial and some from community.

How does entity framework core works?

How Entity Framework Works
  1. Define domain classes & configure entity framework DbContext API along with mappings to let entity framework work how this class maps to the database schema.
  2. Write LINQ to objects to fetch data from the database.
  3. Based on mappings & database provider configured entity framework will translate queries into SQL that’s understood by the database.
  4. The query is executed and the object is populated with data.
  5. Data in objects can be modified, deleted or new records can be added to the list & once done call DbContext.saveChanges from EF API to save data back to the database.
  6. The entity framework will generate the required SQL statements to save data back to the database.

Should we use Entity Framework Core?

Entity framework can increase developer productivity but still many developers don’t prefer using it due to the complexity it adds to data access layer.

Use entity framework when

  • There is a one-to-one mapping between fields on-screen and columns in the database tables.
  • You need to implement CRUD operation for the screen and business logic is not so complex.
  • There are no bulk database operations to be implemented.
  • There is no need to bother about the SQL generated for the operation i.e. no SQL tweaking are required for the performance

Code First v/s Database First Approach

Entity Framework Database First vs Code First Approach

Entity framework provides two approaches for development

  1. Database First Approach: This is used when you already have a database ready or you have a team of DBAs and take the approach that you will be designing the database first and then the application. Entity framework will create Entities for you from the database. Manual changes to the database can be done and the model can be updated from the database.
  2. Code First Approach: This is used when there is a team of developers who need full control over the code. The entity framework will generate database tables for you based on the domain classes. Here database is just storage with no business logic in the database layer. Any manual changes to the database will be lost.

Implement Entity Framework Core in ASP.NET Core Web API

Demonstration video

Create a project for demonstration

For demonstration purposes, we will be creating a default ASP.NET Core 3.1 API Project using Visual Studio 2019 Community Edition. We will be using the code-first approach for the demonstration.

ASP.NET Core 3.1 API Project Creation

Create the data model

Create an Employee entity class. Here Id will become the primary key column for the database table that will be created for this class. Entity framework interprets property named as Id or ID as the primary key

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Designation { get; set; }
    public double Salary { get; set; }
}

Install Entity Framework Core Packages

We need to install the required entity framework packages. You run the below mentioned commands in Package Manager or install required Nuget packages from Nuget Package Manager.

Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.Tools
Install Entity Framework Core

Adding database context class

This is the main class that co-ordinates entity framework functionality for a given model class. You need to derive the class from entity framework DbContext class and specify the entities included in the data model. This class creates a DbSet property for the Employee entity set. An entity set typically represents a database table and an entity represents a row in the table.

Database table will have the same name as DbSet property name.

public interface IApplicationDbContext
{
    DbSet<Employee> Employees { get; set; }
    Task<int> SaveChanges();
}
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public DbSet<Employee> Employees { get; set; }

    public new async Task<int> SaveChanges()
    {
        return await base.SaveChangesAsync();
    }
}

Connect application to the database

Specify the SQL Server connection string in appsettings.json file. We are using localdb database which is light-weight version of the SQL Server Express database engine.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=EFCoreDb;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Register database context for dependency injection in Startup class

You need to configure the database context as service in configureservices in the startup.cs file so that you pass this service to the controller through the constructor parameter.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection"),
        ef => ef.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
    services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

    services.AddControllers();
}
//Remaining code has been removed

For more details on Dependency Injection, you can read my another article – https://procodeguide.com/programming/dependency-injection-in-asp-net-core-3/

Add Migrations

To automate the migrations from our entity framework class the database we need to run the command add-migration in the package manager console.

add-migration FirstMigration

This will add migration folder & required migration files to the solution as shown below. These files will be on the basis entities we configured.

Entity Framework Migrations

To create database from the migration created above we need to command update-database in the package manager console

update-database

The database as shown below will be created based on entities configured. Here it has created an Employee table based on the Employee model configured.

Entity Framework Core - Code First Database

Add CRUD operations in Repository for Employee

Repository is a component that encapsulated the objects related to data store and operations performed over them. You can even write a generic repository but for demonstration purpose I have added a repository specific to Employee entity. Interface will contain the operations that are possible (based on requirements) on the entity i.e. CRUD operations. DbContext is passed as parameter in constructor using dependency injection. Here we have added following operations.

  • Create – to add a new employee
  • GetAll – to get a list of all employees
  • GetById – to get particular employee by Id
  • Update – to modify existing employee
  • Delete – to delete existing employee
public interface IEmployeeRepository
{
    Task<int> Create(Employee employee);
    Task<List<Employee>> GetAll();
    Task<Employee> GetById(int id);
    Task<string> Update(int id, Employee employee);
    Task<string> Delete(int id);
}
public class EmployeeRepository : IEmployeeRepository
{
    private IApplicationDbContext _dbcontext;
    public EmployeeRepository(IApplicationDbContext dbcontext)
    {
        _dbcontext = dbcontext;
    }

    public async Task<int> Create(Employee employee)
    {
        _dbcontext.Employees.Add(employee);
        await _dbcontext.SaveChanges();
        return employee.Id;
    }

    public async Task<List<Employee>> GetAll()
    {
        var employees = await _dbcontext.Employees.ToListAsync<Employee>();
        return employees;
    }

    public async Task<Employee> GetById(int id)
    {
        var employee = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync();
        return employee;
    }

    public async Task<string> Update(int id, Employee employee)
    {
        var employeeupt = await _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefaultAsync();
        if (employeeupt == null) return "Employee does not exists";

        employeeupt.Designation = employee.Designation;
        employeeupt.Salary = employee.Salary;

        await _dbcontext.SaveChanges();
        return "Employee details successfully modified";
    }

    public async Task<string> Delete(int id)
    {
        var employeedel = _dbcontext.Employees.Where(empid => empid.Id == id).FirstOrDefault();
        if (employeedel == null) return "Employee does not exists";

        _dbcontext.Employees.Remove(employeedel);
        await _dbcontext.SaveChanges();
        return "Employee details deleted modified";
    }
}

As shown below register Employee repository as a service in the ConfigureServices method of Startup class

services.AddTransient<IEmployeeRepository, EmployeeRepository>();

Repository helps in better testing of the code. Since repository is passed as service till database is ready we can create a dummy repository service for simulation of CRUD operations. Also we can pass different repository implementation based of environments. If you want to read more about how to handle multiple environment you can read my article on Configuring multiple ASP.NET Core hosting environment

Add Employee controller

Here is the code for the Employee controller which has been added to expose the CRUD operations for the Employee entity as a API. Employee Repository has been passed as constructor parameter using dependency injection. Implementation have been added by calling the methods in repository class. I have not covered validations here but before calling repository method input should be validated.

[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
    private IEmployeeRepository _employeerepository;
    public EmployeeController(IEmployeeRepository employeerepository)
    {
        _employeerepository = employeerepository;
    }

    [HttpPost]
    [Route("Create")]
    public async Task<ActionResult> create([FromBody] Employee employee)
    {
        int empid = await _employeerepository.Create(employee);
        return Ok(empid);
    }

    [HttpGet]
    [Route("GetAll")]
    public async Task<ActionResult> GetAll()
    {
        var employees = await _employeerepository.GetAll();
        return Ok(employees);
    }

    [HttpGet]
    [Route("GetById/{id}")]
    public async Task<ActionResult> GetById(int id)
    {
        var employee = await _employeerepository.GetById(id);
        return Ok(employee);
    }

    [HttpPut]
    [Route("Update/{id}")]
    public async Task<IActionResult> Update(int id, Employee employee)
    {
        string resp = await _employeerepository.Update(id, employee);
        return Ok(resp);
    }

    [HttpDelete]
    [Route("Delete/{id}")]
    public async Task<IActionResult> Delete(int id)
    {
        var resp = await _employeerepository.Delete(id);
        return Ok(resp);
    }
}

Let’s run & test the code

Will be using postman to test the code.

Create – request & response. Here we can see that we are sending a post HTTP request for creating along with Employee object in the body in JSON format & in response we get employee Id

EF Core - Create Request

GetAll – request & response. Here we are sending a get HTTP request without any parameters & in response we get all the employees present in database.

EF Core - GetAll Request

Entity Framework Conventions

We saw that we just added the entity class for Employee and the table was created for this entity without specifying any metadata for the database or table. This is due to the fact that the entity framework does this based on the default conventions or assumptions it follows.

  • DbSet property name is used for table name.
  • Entity class property name is used for column name.
  • Entity class properties with name ID or classnameID are assumed as primary key.

You can override these conventions by specifying your own details for the table name, column name, primary key, and foreign key details.

Modifying the database with Annotations

Entity class can be modified to specify the metadata for the table being created for entity i.e. it will override the default conventions used for migrations. Data Annotations Attributed available in namespace “System.ComponentModel.DataAnnotations” to specify the column properties for table.

public class Employee
{
    public int Id { get; set; }
        
    [Required]
    [StringLength(60)]
    public string FirstName { get; set; }

    [StringLength(60)]
    public string MiddleName { get; set; }

    [StringLength(60)]
    public string LastName { get; set; }

    [Required]
    public string Designation { get; set; }

    [Required]
    public double Salary { get; set; }
}
EF Core - Modified Database

Entity Framework Fluent API can also be used to configure DbContext classes to override conventions.

Summary

We covered how to implement Entity Framework Core in ASP.NET Web API with the code-first approach. I have even posted a video of the implementation.

One thing to keep in mind is that the entity framework doesn’t fit in all the scenarios so please do your research well before deciding to implement it in your project.

Referenceshttps://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-3.1

Source code download

  1. What is entity framework core?

    It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft.W

  2. Which databases are supported with Entity framework?

    Entity framework core can work with wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third party providers some commercial and some from community.

  3. Is entity framework code asynchronous ?

    Asynchronous programming is the default mode for ASP.NET Core and Entity Framework Core.

Implement Automapper in ASP.NET Core 3.1

In every application, there will be a need to map the object of one type to object of another type. Automapper is used to map these objects of dissimilar types without the need to write boring code to map each data member. Automapper in ASP.NET core comes handy when mapping objects between Model & DTO.

What is automapper & when to use it?

Automapper

Automapper is a popular small library for an object to object mapping used to map objects of different classes.

Let’s say you have two different classes EmployeeDTO & EmployeeModel with the same data members and you need to copy data from one object to another. Now you cannot set an instance of one object to another object as though data member match but objects are of different classes. You will have to use the traditional approach i.e. copy data from one object to another field by field.

To simply this job of mapping data from one object to objects Auto Mapper can be used. Auto Mapper is an open-source library and It maps the properties of two different objects.

Implement automapper in ASP.NET Core

Setup project for demonstration

Create new ASP.NET Core API Project

For implementation purpose, I have created a default ASP.NET Core 3.1 API Project using Visual Studio 2019

ASP.NET Core 3.1 API Project Creation

Install automapper NuGet package

Install package AutoMapper.Extensions.Microsft.DependencyInjection & this package depends on the AutoMapper package which will also get installed with this package.

NuGet Extension

Create sample EmployeeDTO & EmployeeModel classes

public class EmployeeDTO
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
}
public class EmployeeModel
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
}

Configure automapper in startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
}
//Remaining code has been removed

Create an automapper mapping profile as EmployeeProfile.cs

Creating Mapping profiles is a better way to organize your object mappings. This profile tells automapper about which object links to which another object, which property of one object links to which property of other object and even let’s configure conditional mappings.

Create a mapping profile class that inherits from AutoMapper.Profile and add the configuration in the constructor of that mapping profile class

public class EmployeeProfile : Profile
{
    public EmployeeProfile()
    {
        CreateMap<EmployeeDTO, EmployeeModel>();
    }
}

Do note that with above CreateMap you can map from EmployeeDTO to EmployeeModel but reverse mapping will not be supported. Reverse Maps will have to be used for bidirectional mapping.

Using employee mapping in Employee controller

Create an Employee controller as shown below. Automapper service will have to be injected into controller using constructor dependency injection (Refer here for more details on Dependency Injection). Here Employee controller’s post method takes an object of type EmployeeDTO and using automapper maps it to EmployeeModel & return the same as JSON.

[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
    private readonly IMapper _mapper;

    public EmployeeController(IMapper mapper)
    {
        _mapper = mapper;
    }

    // POST api/<EmployeeController>
    [HttpPost]
    public IActionResult Post([FromBody] EmployeeDTO _employeeDTO)
    {
        var employeeModel = _mapper.Map<EmployeeModel>(_employeeDTO);
        return Ok(employeeModel);
    }
}

After executing the above project and calling Employee controller post-action using postman we got the following result

mapper in ASP.NET Core

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Mapping objects having different property names

To demonstrate how to map objects using automapper having different property names. We have modified class EmployeeModel property name for Name to FullName.

public class EmployeeDTO
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
}
public class EmployeeModel
{
    public long Id { get; set; }
    public string FullName { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
}

Below is the code for Employee Mapping Profile class in which we have added mapping for properties having different name i..e. EmployeeDTO=>Name to EmployeeModel=>FullName. Here we have used method ForMember to specify the mapping

public class EmployeeProfile : Profile
{
    public EmployeeProfile()
    {
        CreateMap<EmployeeDTO, EmployeeModel>()
            .ForMember(empmodel => empmodel.FullName, empdto => empdto.MapFrom(empdto => empdto.Name));
    }
}

After executing the above project and calling Employee controller post-action using postman we got the following result.

automapper conditional mapping

Mapping objects with conditional mapping

Here is the how to implement conditional mapping for objects in Employee Mapping Profile class

public class EmployeeProfile : Profile
{
    public EmployeeProfile()
    {
        CreateMap<EmployeeDTO, EmployeeModel>()
            .ForMember(empmodel => empmodel.FullName, empdto => empdto.MapFrom(empdto => empdto.Name))
            .ForMember(empmodel => empmodel.Salary, empdto => empdto.MapFrom(empdto => empdto.Age > 55 ? empdto.Salary * 10 : empdto.Salary));
    }
}

Mapping objects with Null Subsitution

This allows you to set an default or alternate value for the destination data member in case the source data member is null

public EmployeeProfile()
{
    CreateMap<EmployeeDTO, EmployeeModel>()
        .ForMember(empmodel => empmodel.Telephone, empdto => empdto.NullSubstitute("Not Available"));
}

Mapping objects with Reverse Map

Do note that with CreateMap you can map from source (EmployeeDTO) to destination (EmployeeModel) but reverse mapping will not be supported. Reverse Maps will have to be used for bidirectional mapping.

public class EmployeeProfile : Profile
{
    public EmployeeProfile()
    {
        CreateMap<EmployeeDTO, EmployeeModel>()
            .ForMember(empmodel => empmodel.FullName, empdto => empdto.MapFrom(empdto => empdto.Name))
            .ForMember(empmodel => empmodel.Salary, empdto => empdto.MapFrom(empdto => empdto.Age > 55 ? empdto.Salary * 10 : empdto.Salary))
            .ReverseMap();
    }
}

Mapping Objects of Complex Types

EmployeeDTO & EmployeeModel classes have been modified to add a new property which is of a type of custom class as shown below

public class TelephoneNumberDTO
{
    //1 - Home, 2 - Office, 3 - Mobile
    public int PhoneType { get; set; }
    public string PhoneNumber { get; set; }
}
public class TelephoneNumberModel
{
    //1 - Home, 2 - Office, 3 - Mobile
    public int PhoneType { get; set; }
    public string PhoneNumber { get; set; }
}
public class EmployeeDTO
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
    public TelephoneNumberDTO Telephone { get; set; }
}
public class EmployeeModel
{
    public long Id { get; set; }
    public string FullName { get; set; }
    public int Age { get; set; }
    public double Salary { get; set; }
    public TelephoneNumberModel Telephone { get; set; }
}

Here is the how to map complex objects in Employee Mapping Profile class

public class EmployeeProfile : Profile
{
    public EmployeeProfile()
    {
        CreateMap<EmployeeDTO, EmployeeModel>()
            .ForMember(empmodel => empmodel.FullName, empdto => empdto.MapFrom(empdto => empdto.Name))
            .ForMember(empmodel => empmodel.Salary, empdto => empdto.MapFrom(empdto => empdto.Age > 55 ? empdto.Salary * 10 : empdto.Salary))
            .ReverseMap();
        CreateMap<TelephoneNumberDTO, TelephoneNumberModel>()
            .ReverseMap();
    }
}

Advantages of automapper

  • No need to write boring code so saves time
EmployeeDTO.Name = EmployeeModel.Name
EmployeeDTO.Id = EmployeeModel.Id
  • Handles conditional mapping
  • Handles complex objects

Summary

Automapper is used to map objects of dissimilar types without the need to write boring code to map each data member.

We used automapper in ASP.NET Core to map objects of dissimilar types. It was easy to map objects having the same property names with minimal coding. Though different property names required some mapping to map properties within classes.

Automapper on GitHub

You can also check my other article on Top 12 ASP.NET Core libraries for developers – https://procodeguide.com/programming/top-12-essential-asp-net-core-libraries

Complete source code for Automapper in ASP.NET Core is available on my GitHub for download

Automapper.Sample
https://github.com/procodeguide/Automapper.Sample
0 forks.
0 stars.
0 open issues.
Recent commits:

  1. What is Automapper?

    Automapper is a popular small library for an object to object mapping used to map objects of different classes.

  2. When to use Automapper?

    Use it to simply job like you have two different classes EmployeeDTO & EmployeeModel with the same data members and you need to copy data from one object to another

  3. What are advantages of Automapper?

    No need to write boring code so saves time, handles complex objects, conditional mapping, etc.

Web API Versioning in ASP.NET Core 3.1

Web API versioning though being one of the important features mostly goes ignored when building a Web API application. Web API versioning in ASP.NET Core is simple and easy to implement. In this article, we will look at what is Web API versioning along with why it is needed and how to achieve Web API versioning in ASP.NET Core.

Web API Versioning – What & Why?

Web API Versioning in ASP.NET Core

When we start a new Web API project at that time it is all fine as we develop an initial version get it tested with all the clients and push it to production. Now after going to production there are some changes in existing Web API which is a mandatory change for one of the client but it will not be possible for other clients to go live with new changes at the same time. Also, it is not recommended to change existing working clients by implementing new Web API features which they don’t need. So now if you change the existing Web API on production with breaking changes and if any of the clients don’t implement new changes it will start failing. So now there is a need to support the old version as well as the newer version of Web API so that all existing clients can function without failing.

Web API versioning is a feature using which we can implement multiple versions of the same API so that different clients can work with the required version of API.

Implement Web API versioning in ASP.NET Core

There are many ways to implement versioning in Web API. Here I will be covering methods to version Web API using Nuget Package Microsoft.AspNetCore.Mvc.Versioning

We can achieve Web API versioning using following approaches

  1. Query String
  2. HTTP Header
  3. URL

Here for demonstration purposes, I have created an ASP.NET Core 3.1 Web API project. I will be using the default generated WeatherForecast Controller for configuring Web API Versioning. By default, there is no versioning support added as shown below.

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    [HttpGet]
    public string Get()
    {
        return "This is from WeatherForecast - Sunny Day";
    }
}

As shown below Install the Nuget package and enable the support for Web API versioning in ConfigureServices method in the startup.cs file.

Web API Versioning in ASP.NET Core 3
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddApiVersioning(apiVerConfig =>
        {
            apiVerConfig.AssumeDefaultVersionWhenUnspecified = true;
            apiVerConfig.DefaultApiVersion = new ApiVersion(new DateTime(2020, 6, 6));
        });

        services.AddControllers();
    }
    //Remaining code has been removed
}

Web API Versioning using Querystring Parameter

Here you need to define the same controller twice with different values for ApiVersion attribute in different namespaces as shown below.

namespace WebAPIVersioning.Controllers.V1
{
    [ApiVersion("1.0")]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V1 - Sunny Day";
        }
    }
}

namespace WebAPIVersioning.Controllers.V2
{
    [ApiVersion("2.0")]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V2 - Rainy Day";
        }
    }
}

After defining multiple versions of the same controller as shown above you can invoke these using version number in querystring i.e. http://server:port/api/weatherforecast?api-version=1.0 or 2.0.

Below is the output screen from both version of API

Versioning Using Querystring

Web API Versioning using HTTP Header

For version to be part of HTTP header and enable controllers to read version number form header you need to first configure this in ConfigureServices method in startup.cs file as hows below

public void ConfigureServices(IServiceCollection services)
{
    services.AddApiVersioning(apiVerConfig =>
    {
        apiVerConfig.AssumeDefaultVersionWhenUnspecified = true;
        apiVerConfig.DefaultApiVersion = new ApiVersion(1,0);
        apiVerConfig.ReportApiVersions = true;
        apiVerConfig.ApiVersionReader = new HeaderApiVersionReader("api-version");
    });

    services.AddControllers();
}

Then you need to define the same controller twice with different values for ApiVersion attribute in different namespaces as shown below.

namespace WebAPIVersioning.Controllers.V1
{
    [ApiVersion("1.0")]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V1 - Sunny Day";
        }
    }
}

namespace WebAPIVersioning.Controllers.V2
{
    [ApiVersion("2.0")]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V2 - Rainy Day";
        }
    }
}

After defining multiple versions of the same controller as shown above you can invoke these using version number in HTTP header as “api-version: 1.0” or “api-version: 2.0”

Below is the output screen from both version of API

Versioning Using HTTP Header

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Web API Versioning using URL

Here you need to define the same controller twice with different values for ApiVersion attribute in different namespaces as shown below. Also, you need to add parameter v{version:apiVersion} in route attribute like Route(“api/v{version:apiVersion}/[controller]”) so that API version becomes part of URL.

namespace WebAPIVersioning.Controllers.V1
{
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V1 - Sunny Day";
        }
    }
}

namespace WebAPIVersioning.Controllers.V2
{
    [ApiVersion("2.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V2 - Rainy Day";
        }
    }
}

After defining multiple versions of the same controller as shown above you can invoke these using version number in HTTP URL i.e. http://server:port/api/v1/weatherforecast or http://server:port/api/v2/weatherforecast

Below is the output screen from both version of API

Versioning in ASP.NET Core using HTTP URL

Supported & Deprecated API Version

In startup.cs file while configuring API version since we have enabled parameter ReportApiVersions so any API call will return supported versions for that API in response header as shown below.

Supported API Versions

Now if you want to pass on the information that older version of API will be removed then you can add deprecate flag to the version of API which will be not supported in future.

namespace WebAPIVersioning.Controllers.V1
{
    [ApiVersion("1.0",Deprecated = true)]
    [Route("api/[controller]")]
    [ApiController]
    public class WeatherForecastController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "This is from WeatherForecast V1 - Sunny Day";
        }
    }
}
deprecated API versions

Summary

API versioning is useful when you need to enhance an existing API that is being consumed by multiple clients. Versioning in ASP.NET Core Web API is easy and simple to implement. We can make use of the NuGet package Microsoft.AspNetCore.Mvc.Versioning to achieve the same.

Though there are a number of ways to achieve API versioning I personally prefer URL based versioning as that avoids extra api-version parameter in querystring and HTTP header both.

You can also check my other article on Top 12 ASP.NET Core libraries for developers: https://procodeguide.com/programming/top-12-essential-asp-net-core-libraries/

Dependency Injection in ASP.NET Core 3.1

ASP.NET Core is designed from the ground up to support the dependency injection design pattern. Dependency injection in ASP.NET Core provides a technique to create applications that are loosely coupled. ASP.NET Core allows us to injects dependent objects either through constructor or methods. Based on the environment in which application is running different objects can be injected.

What is Dependency Injection?

Dependency Injection in ASP.NET Core

Dependency injection is used to achieve loose coupling in application between client objects and their dependencies. Instead of directly instantiating objects of classes and using them rather Interfaces are used and objects are provided to class in some way either through constructor or through some method.

Class will depend on an interface rather than concrete implementation of dependencies. This makes our code loosely coupled as we can inject any concrete object as far as it implements the required interface.

ASP.NET Core comes with a built-in container (IServiceProvider) that supports constructor injection by default and the framework itself provides some services through dependency injection.

Here is a great article by Martin Fowler on Dependency Injection

Why Dependency Injection

  • Improves code readability by keeping it clean so easier to maintain it.
  • Application is loosely coupled which improves flexibility
  • Increases code testing ability with different mock implementations of services.
  • Supports extendable class structure

Implementation of Dependency Injection in ASP.NET Core

There are two types of services in ASP.NET Core

  1. Framework provided services – These services are part of ASP.NET Core framework
  2. Custom Services – These are add-on services created by developers

Registering framework provided services

Below code shows how to register a framework defined service (Memory Caching Service) in ConfigureServices() method of startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddMemoryCache();
    }
    //Remaining code was removed
}

Registering your own services

You can even register your own service and make it available for dependency injection into controllers, middlewares & views

First you need to define the service using an interface as shown below

public interface ILogger
{
    void Log(string message);
    void Log(string message, Exception ex);
}

public class LogToFile : ILogger
{
    public void Log(string message)
    {
        //Log Message to File
    }

    public void Log(string message, Exception ex)
    {
        //Log Message & Exception to File
    }
}

public class LogToDB : ILogger
{
    public void Log(string message)
    {
        //Log Message to Database
    }

    public void Log(string message, Exception ex)
    {
        //Log Message & Exception to Database
    }
}

Service Lifetime

Before we talk about how to register your service in the startup.cs file we need to understand the significance of Service Lifetime while registering a service. Lifetime decides whether the instance of a service being injected is a new instance to that component or it same signal instance which is being used everywhere in the application. While registering service you need to choose the lifetime for each service.

Transient – Each time a new object is created for dependency injection i.e. each component will have its unique instance. This is the option used for lightweight & stateless services.

services.AddTransient<ILogger, LogToFile>();

Scoped – This means that it is created once for each request i.e. a new object will be created for each new request.

services.AddScoped<ILogger, LogToFile>();

Singleton – One single component will be created for the lifetime of the application. This single instance is shared across all components and all requests.

services.AddSingleton<ILogger, LogToFile>();

Registering Services in startup.cs

You need to register required services in ConfigureServices() methif of startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddMemoryCache();

        services.AddTransient<ILogger, LogToDB>();
    }
     //Remaining code has been removed
}

Once service is registered it can be injected into other components

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Injecting services (framework/custom) into Middleware

Below is the code sample for the injection of service into middleware. Either it can be injected through the constructor and or through the invoke method.

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;
    private readonly IMemoryCache _cache;

    public ExceptionMiddleware(RequestDelegate next, ILogger logger, IMemoryCache cache)
    {
        _next = next;
        _logger = logger;
        _cache = cache;
    }

    public Task Invoke(HttpContext httpContext, ILogger logger, IMemoryCache cache)
    {
        return _next(httpContext);
    }
}

Injecting services (framework/custom) into Controller

Below is the code sample for the injection of service into the controller. Either it can be injected through the constructor and or through the action method.

public class HomeController : Controller
{
    private readonly ILogger _logger;
    private readonly IMemoryCache _cache;

    public HomeController(ILogger logger, IMemoryCache cache)
    {
        _logger = logger;
        _cache = cache;
    }

    public IActionResult Index([FromServices] ILogger logger, [FromServices] IMemoryCache cache)
    {
        return View();
    }
}

Request Services Manually

Instead of using dependency injection to inject services, components can even manually request services. Below code shows how to manually request a service using HttpContext object.

var services = this.HttpContext.RequestServices;
var log = (ILogger)services.GetService(typeof(ILogger));

Summary

Dependency injection allows us to develop loosely coupled applications. Dependency injection in ASP.NET Core is supported and also it is simple and easy to implement. Framework provided services or your own custom services can be used for dependency injection.

You can inject components using dependency injection into middlewares, controllers, view, etc. Service lifetime can be used to control the scope of the service.

References: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

You can also check my another Article on Microsoft Azure Storage – https://procodeguide.com/programming/azure-storage/

ASP.NET Core Hosting on IIS on Windows

This article will provide details about how to deploy ASP.NET Core web application or Web API on IIS. .NET Core 2.2 onwards there were significant changes in the hosting model to IIS. Prior to .NET Core 2.2 only option available was to use IIS as a reverse proxy to ASP.NET Core Kestrel web server.

With .NET Core 2.2 option was added for direct in-process hosting to IIS which can improve the performance significantly. The old approach with IIS as a reverse proxy is also available as an out-of-process hosting model. ASP.NET Core hosting on IIS supports two models for hosting on the IIS i.e. In-process hosting model & out-of-process hosting model.

ASP.NET Core Hosting on IIS is different as compared to ASP.NET Webforms or ASP.NET MVC.

Supported operating systems

  • Windows 7 or later
  • Windows server 2012 R2 or later

Apps published for 32 bit (x86) and 64 bit (x64) are supported. Application pools under should be configured accordingly for 32-bit & 64-bit apps.

Type of Hosting Models

ASP.NET Core Hosting on IIS
In-process hosting model

As the name suggests ASP.NET Core application runs in the same process as IIS (w3wp.exe) and it does not use the Kestrel web server. This hosting model uses IISHttpServer that is hosted directly inside the application pool. This hosting model provides a significant performance improvement over the other out-of-process model as it does not have to forward requests to Kestrel for processing. IIS handles process management in the traditional way with the help of windows process activation service (WAS).

Request flow details:

  • Request arrives from web at HTTP.sys
  • HTTP.sys routes the request to IIS
  • ASP.NET Core module receives the request and passes it to IIS HTTP Server.
  • IISHTTPServer passes the request to ASP.NET Core middleware pipeline.
  • ASP.NET Core application handles the request and returns response
Out-of-process hosting model

Again as the name suggests here ASP.NET Core application runs in a separate process from the IIS worker process. This is similar to what was available in ASP.NET Core versions prior to 2.2. ASP.NET Core module handles process management, this module is responsible for starting the ASP.NET Core App when the first request arrives & also restarts if it shuts down or crashes.

Here IIS acts as a reverse proxy to Kestrel web server where ASP.NET Core application is running. For application to be configured as an out-of-process model it needs to specify UseIISIntegration as part of WebHostBuilder code in the program.cs file. ASP.NET Core module doesn’t support HTTPS forwarding.

Steps for ASP.NET Core hosting on IIS

  • Publish your application
  • Install/Enable IIS Server on windows
  • Install the .NET Core Hosting Bundle
  • Create a new application pool & website for your application
Publish your Application

Right click on project in Solution Explorer and select Publish option. This should being up the screen to publish your code. Select Folder option to publish all the files to a folder. This folder will be configured in IIS as website folder.

IIS Configuration

Use the Add Roles & Features wizard to Enable IIS on Windows server operating system.

IIS Installation

Select following services under web server on Select role services screen

IIS Installation Select Services

For windows desktop operating system select Control Panel ==> Program ==> Program & Features ==> Turn windows features on or off and select following features for installations

IIS Installation on Windows Desktop

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Install .NET Hosting Bundle

You can download the required version of the hosting bundle from here. The hosting bundle installs the .NET Core Runtime, .NET Core Library, and the ASP.NET Core Module.

If the Hosting Bundle is installed before IIS, the bundle installation must be repaired. Run the Hosting Bundle installer again after installing IIS.

Create IIS Site

Open IIS Manager & expand server node in connections panel on left hand side. Right click site folder and select “Add Website…” from the context menu. Provide Site name, Physical path (where code was published), binding configuration details & click on ok.

IIS Create Website

Finally browse and check your website.

Summary

ASP.NET Core hosting on IIS supports two models for hosting on the IIS i.e. In-process hosting model & out-of-process hosting model. .NET Core 2.2 onward there were significant changes in the hosting model to IIS.

In-process hosting model provides a significant performance improvement over the other out-of-process model as it does not have to forward requests to Kestrel for processing

References: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1

You can also check my other Article on Configuring multiple ASP.NET Core hosting environment: https://procodeguide.com/programming/asp-net-core-hosting-environment/