How to Create .Net Core Web API – CRUD Operation

In this Article we will learn How to Create .Net Core 6.0 Web API – CRUD (Create, Read, Update and Delete) Operation in Asp.net Core with Entity Framework Core. We will use the Code First Approach.

Prerequisites

  • Download and install .Net Core 6.0 SDK from here
  • Download and Install Microsoft Visual Studio 2022 from here
  • SQL Server

Previous Article Also check Generate Report in PDF Format

Create ASP.Net Core Web API

  • Open visual studio and click the Create New Project Option
  • Select the Template
Asp.Net Web API
  • Enter the name of the Project

Select Frame Work Click on Create

Install NuGet Packages

  • Microsoft Entity Framework Core Sql Server.
  • Microsoft Entity Framework Core Tools
  • Microsoft Entity Framework Core
  • AutoMapper

Now Add the Database connection in the appsettigns.json

Configure appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "sqlconnection": "Server=(local)\\MSSQL;Database=Inventory;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "AllowedHosts": "*"
}

ASP.Net Core Web API Project Structure

  • Controller – It is a class that handles requests to specific endpoints and returns HTTP response in the form of JSON or XML.  Each action method in a controller class should handle a specific HTTP request verb (GET, POST, PUT, DELETE) and a specific route.
  • Entities – It represent the application data the stored in the database. Entity Framework Core maps relational data from the database to instances of entity objects to be used within the application for data management and CRUD operations.
  • Models –  it represent request and response models for controller method , request model define parameters for incoming requests and response model define custom data returned in responses when required
  • Services – it contain validation , Business logic and database code
  • Helper – It contains DbContext class , AppException custom Exception and Middleware Error Handler

Create Entities

Employee.cs

using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;

namespace Web_API_Tutorials.Entities
{
    public class Employee
    {
        [Key]

        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string designation { get; set; }
        public string Title { get; set; }
        public string Email { get; set; }

        [Required]
        [EnumDataType(typeof(Role))]
        public string  Role { get; set; }

        [JsonIgnore]
        public string Password { get; set; }

    }
}

Role.cs

namespace Web_API_Tutorials.Entities
{
    public enum Role
    {
         Admin,
         SuperAdmin,
         User,
    }
}

Helpers

Helper Folder Contains DbContext , AppException, Middleware Error Handler

DbContext Class

DbContext Class. The DbContext is used for accessing application data through Entity Framework Core and is configured to connect to a SQL Server database. It inherits from the Entity Framework Core DbContext class.

using Microsoft.EntityFrameworkCore;
using Web_API_Tutorials.Entities;

namespace Web_API_Tutorials.Helpers
{
    public class DbContextData : DbContext 
    {
        public DbContextData(DbContextOptions<DbContextData> option):base(option)
        {

        }

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

    }
}

AppException

App Exceptions – The app exception is a custom exception class used in the .NET API to differentiate between handled and unhandled exception. Unhandled exceptions are generated by the .NET framework or caused by bugs in application code , where handled exception are generated by application code and used to return friendly error message or user define error, such as business logic or validation exception caused by invalid request parameters

using System.Globalization;

namespace Web_API_Tutorials.Helpers
{
    public class AppException :Exception
    {
        public AppException() { }
        public AppException(string message):base(message) {  }

        public AppException(string message,params object[] args) 
        : base(String.Format(CultureInfo.CurrentCulture,message ,args)) 
        {
        }
    }
}

Middleware Error Handler

Error Handler Is used to catch all error and remove the need for duplicated error handling code throughout the .Net 6.o API. It’s configured as middleware in the program.cs file.

using System.Net;
using System.Text.Json;

namespace Web_API_Tutorials.Helpers
{
    public class MiddlewareErrorHandler
    {

        private readonly ILogger _logger;
        private readonly RequestDelegate _errorHandler;

        public MiddlewareErrorHandler(ILogger<MiddlewareErrorHandler> logger, RequestDelegate errorHandler)
        {
            _logger = logger;
            _errorHandler = errorHandler;
        }

        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _errorHandler(context);
            }
            catch (Exception Err)
            {
                var resp = context.Response;
                resp.ContentType= "application/json";

                switch (Err)
                {

                    case AppException e:
                        resp.StatusCode = (int)HttpStatusCode.BadRequest; 
                        break;
                    case KeyNotFoundException e:
                        resp.StatusCode = (int)HttpStatusCode.NotFound;
                        break;
                    default:
                        _logger.LogError(Err, Err.Message);
                        resp.StatusCode = (int)(HttpStatusCode.InternalServerError);
                        break;
                }

                var outresult = JsonSerializer.Serialize(new { Message = Err?.Message });
                await resp.WriteAsync(outresult);
            }

        }
    }
}

Models

AutoMapper

using System.Runtime;
using AutoMapper;
using Web_API_Tutorials.Entities;

namespace Web_API_Tutorials.Models
{
    public class AutoMapper :Profile 
    {
        public AutoMapper()
        {
            CreateMap<CreateEmpRequest, Employee>();
            CreateMap<UpdateEmpRequest, Employee>();

        }
    }
}

Create Request

The Create Employee Request Model define the parameters for incoming POST requests to the route.

using System.ComponentModel.DataAnnotations;
using Web_API_Tutorials.Entities;

namespace Web_API_Tutorials.Models
{
    public class CreateEmpRequest
    {
        [Required]
        public string Title { get; set; }

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

        [Required]
        public string LastName { get; set; }
        [Required]
        public string designation { get; set; }
        public string Email { get; set; }
        [Required]
        public Role Role { get; set; }
        [Required]
        [MinLength(8)]
        public string password { get; set; }

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

Update Request

The Update Employee Request Model define the parameters for incoming PUT requests to the route.

using System.ComponentModel.DataAnnotations;
using Web_API_Tutorials.Entities;

namespace Web_API_Tutorials.Models
{
    public class UpdateEmpRequest
    {

        
        public string Title { get; set; } 
        public string FirstName { get; set; }       
        public string LastName { get; set; }
        public string designation { get; set; }

        [EmailAddress]
        public string Email { get; set; }

        [EnumDataType(typeof(Role))]
        public string Role { get; set; }

        private string _password;
                    
        [MinLength(8)]

        public string password
        {
            get => _password; set => _password = replacewithNull(value);
        }

        private string _confirmpassword;

        [Compare("password")]
      
        public string confirmpassword
        {
            get => _confirmpassword;
            set => _confirmpassword = replacewithNull(value);
        }

        private string replacewithNull(string value)
        {
            return string.IsNullOrEmpty(value) ? null : value;
        }

    }
}

Services

It contain validation , Business logic and database code

Create Interface

using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Models;

namespace Web_API_Tutorials.Services
{
    public interface IEmployee
    {
        void Employeecreate(CreateEmpRequest empRequest);
        void Employeeupdate(int id, UpdateEmpRequest empRequest);
        void Employeedelete(int id);
        IEnumerable<Employee> GetAll();
        Employee EmployeeGetById(int id);
    }
}

Create Concrete Class

using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Web_API_Tutorials.Entities;
using Web_API_Tutorials.Helpers;
using Web_API_Tutorials.Models;
 

namespace Web_API_Tutorials.Services
{
    public class EmployeeService : IEmployee
    {
        private  DbContextData  _dbContext;
        private readonly IMapper _mapper;

        public EmployeeService(DbContextData dbContext,IMapper mapper)
        {
            _dbContext = dbContext;
            _mapper = mapper;
        }

        public void Employeecreate(CreateEmpRequest empRequest)
        {

            var Emailexist = _dbContext.Employee.Any(e=>e.Email== empRequest.Email); 
            if (Emailexist == true)
            {
                throw new  AppException("Employee Email ID : '" + empRequest.Email + "' Already Exist");
            }

            var emp = _mapper.Map<Employee>(empRequest);

            _dbContext.Add(emp);
            _dbContext.SaveChanges();

             
        }

        public void Employeedelete(int id)
        {
            var emp = _dbContext.Employee.Find(id);
            if (emp == null) { throw new AppException("Employee Not Found"); }
            _dbContext.Remove(emp);
            _dbContext.SaveChanges();
             
        }

        public Employee EmployeeGetById(int id)
        {
            var emp = _dbContext.Employee.Find(id);
            if (emp==null) { throw new AppException("Employee Not Found"); }
            return emp;
        }

      
        public void Employeeupdate(int id, UpdateEmpRequest empRequest)
        {
            var emp = EmployeeGetById(id); 
            if (emp.Email==empRequest.Email)
            {
                throw new AppException("Employee Email ID : '" + empRequest.Email + "' Already Exist");
            }
            _mapper.Map(empRequest,emp);
            _dbContext.Employee.Update(emp);
            _dbContext.SaveChanges();
        }
        public  IEnumerable<Employee> GetAll()
        {
            return  _dbContext.Employee; 
        }        
    }
}

Program.cs

using Microsoft.EntityFrameworkCore;
using System.Text.Json.Serialization;
using Web_API_Tutorials.Helpers;
using Web_API_Tutorials.Services;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers().AddJsonOptions(json=> {
    json.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
    json.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});
 

builder.Services.AddDbContext<DbContextData>(con => con.UseSqlServer(builder.Configuration.GetConnectionString("connection")));
builder.Services.AddScoped<IEmployee, EmployeeService>();

builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthorization();

app.UseMiddleware<MiddlewareErrorHandler>();

app.MapControllers();

app.Run();

Migration

Add-Migration 'Initial-Create'
Update-Database

Controller

Controller is a class that handles requests to specific endpoints and returns HTTP response in the form of JSON or XML.Β 

using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Web_API_Tutorials.Models;
using Web_API_Tutorials.Services;

namespace Web_API_Tutorials.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeRegController : ControllerBase
    {
        private readonly IEmployee _employee;
        private readonly IMapper _mapper;

        public EmployeeRegController(IEmployee employee, IMapper mapper)
        {
            _employee = employee;
            _mapper = mapper;
        }
        // GET: api/<EmployeeRegController>
        [HttpGet]
        public IActionResult Get()
        {
            var emp = _employee.GetAll();
            return Ok(emp);
        }

        // GET api/<EmployeeRegController>/5
        [HttpGet("{id}")]
        public IActionResult Get(int id)
        {
            var emp = _employee.EmployeeGetById(id);
            return Ok(emp);
        }

        // POST api/<EmployeeRegController>
        [HttpPost]
        public IActionResult Post(CreateEmpRequest createEmpmodel)
        {
            _employee.Employeecreate(createEmpmodel);

            return Ok(new { Message = "Employee Created" });
        }

        // PUT api/<EmployeeRegController>/5
        [HttpPut("{id}")]
        public IActionResult Put(int id, UpdateEmpRequest updateEmp)
        {

            _employee.Employeeupdate(id, updateEmp);
            return Ok(new { Message = "Employee Updated" });
        }

        // DELETE api/<EmployeeRegController>/5
        [HttpDelete("{id}")]
        public IActionResult Delete(int id)
        {
            _employee.Employeedelete(id);
            return Ok(new { Message = "Employee Deleted" });
        }
    }
}

Test the ASP.Net Core Web API Using Postman

  • Create a New Employee
  • Retrieve a list of all Employee
  • Update the Employee
  • Delete the Employee
  • Retrieve a Employee by id

Create a New Employee

Retrieve a list of all Employee

Update the Employee

Delete the Employee

Retrieve a Employee by id

Leave a Reply

Your email address will not be published. Required fields are marked *