.NET Core 3.1 Web API CRUD

This article will explain how to perform CRUD (Create, Read, Update and Delete) operations in Asp.Net Core 3.1 Web API using Entity Framework Core. We will see step-by-step instructions about CRUD operations in Asp.Net Core Web API. We will use the Database First Approach where our database will be ready before creating an actual code.

Before we start, Let's understand the objective of this demonstration which tells what exactly will be covered in this article.

  • Create the Database and Tables
  • Create Asp.Net Core Web API Project
  • Install Nuget Packages for Entity Framework
  • Generates Model Classes
  • Setup Dependency Injection
  • Enable CORS
  • Use Swagger
  • Create Repository and implement CRUD operations
  • Create a Controller and Create API call

So, Let's get started.

Create the Database and Tables

CREATE TABLE [dbo].[Employee](
	[EmployeeID] [int] IDENTITY(1,1) NOT NULL,
	[EmployeeName] [varchar](500) NULL,
	[Department] [varchar](100) NULL,
	[EmailId] [nvarchar](500) NULL,
	[DOJ] [date] NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
(
	[EmployeeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Department](
	[DepartmentID] [int] IDENTITY(1,1) NOT NULL,
	[DepartmentName] [varchar](50) NULL,
 CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED 
(
	[DepartmentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

Create Asp.Net Core Web API Project

Open Visual studio -> New Project -> ASP.NET Core Web API.

Create Project

Project Name

Select Target framework & click Create

Install Nuget Packages for Entity Framework

  • Microsoft.EntityFrameworkCore.
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.AspNetCore.Mvc.NewtonsoftJson
  • Swashbuckle.AspNetCore
  • Microsoft.OpenApi

 Nuget Packages 

Now Add Database connection the in appsettings.json file

appsettings.json

Generates Model Classes

Now, Create Model Entities 

Department

[Table("Department")]

    public class Department
    {
        [Key]
        public int DepartmentId { get; set; }

        public string DepartmentName { get; set; }
    }

 Employee

[Table("Employee")]
    public class EmployeeAngular
    {
        [Key]
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string Department { get; set; }
        public string EmailId { get; set; }
        public DateTime DOJ { get; set; }
    }

Now, once we have added our table entities, now we will create APIDbContext Class which will inhert from DbContext class

public class APIDbContext: DbContext {
    public APIDbContext(DbContextOptions < APIDbContext > options): base(options) {}
    public DbSet < Department > Departments {
        get;
        set;
    }
    public DbSet < Employee > Employees {
        get;
        set;
    }
}

Create Repository and implement CRUD operations

Now Create Folder as Repository in which we will write Repository logic which will communicate with database.

Inside Repository folder Create Interface IDepartmentRepository and DepartmentRepository class.

IDepartmentRepository

public interface IDepartmentRepository {
    Task < IEnumerable < Department >> GetDepartment();
    Task < Department > GetDepartmentByID(int ID);
    Task < Department > InsertDepartment(Department objDepartment);
    Task < Department > UpdateDepartment(Department objDepartment);
    bool DeleteDepartment(int ID);
}

 DepartmentRepository

public class DepartmentRepository: IDepartmentRepository {
    private readonly APIDbContext _appDBContext;
    public DepartmentRepository(APIDbContext context) {
        _appDBContext = context ??
            throw new ArgumentNullException(nameof(context));
    }
    public async Task < IEnumerable < Department >> GetDepartment() {
        return await _appDBContext.Departments.ToListAsync();
    }
    public async Task < Department > GetDepartmentByID(int ID) {
        return await _appDBContext.Departments.FindAsync(ID);
    }
    public async Task < Department > InsertDepartment(Department objDepartment) {
        _appDBContext.Departments.Add(objDepartment);
        await _appDBContext.SaveChangesAsync();
        return objDepartment;
    }
    public async Task < Department > UpdateDepartment(Department objDepartment) {
        _appDBContext.Entry(objDepartment).State = EntityState.Modified;
        await _appDBContext.SaveChangesAsync();
        return objDepartment;
    }
    public bool DeleteDepartment(int ID) {
        bool result = false;
        var department = _appDBContext.Departments.Find(ID);
        if (department != null) {
            _appDBContext.Entry(department).State = EntityState.Deleted;
            _appDBContext.SaveChanges();
            result = true;
        } else {
            result = false;
        }
        return result;
    }
}

Same goes for Employee Create Interface IEmployeeRepository and EmployeeRepository class

IEmployeeRepository

public interface IEmployeeRepository {
    Task < IEnumerable < Employee >> GetEmployees();
    Task < Employee > GetEmployeeByID(int ID);
    Task < Employee > InsertEmployee(Employee objEmployee);
    Task < Employee > UpdateEmployee(Employee objEmployee);
    bool DeleteEmployee(int ID);
}

EmployeeRepository

public class EmployeeRepository: IEmployeeRepository {
    private readonly APIDbContext _appDBContext;
    public EmployeeRepository(APIDbContext context) {
        _appDBContext = context ??
            throw new ArgumentNullException(nameof(context));
    }
    public async Task < IEnumerable < Employee >> GetEmployees() {
        return await _appDBContext.Employees.ToListAsync();
    }
    public async Task < Employee > GetEmployeeByID(int ID) {
        return await _appDBContext.Employees.FindAsync(ID);
    }
    public async Task < Employee > InsertEmployee(Employee objEmployee) {
        _appDBContext.Employees.Add(objEmployee);
        await _appDBContext.SaveChangesAsync();
        return objEmployee;
    }
    public async Task < Employee > UpdateEmployee(Employee objEmployee) {
        _appDBContext.Entry(objEmployee).State = EntityState.Modified;
        await _appDBContext.SaveChangesAsync();
        return objEmployee;
    }
    public bool DeleteEmployee(int ID) {
        bool result = false;
        var department = _appDBContext.Employees.Find(ID);
        if (department != null) {
            _appDBContext.Entry(department).State = EntityState.Deleted;
            _appDBContext.SaveChanges();
            result = true;
        } else {
            result = false;
        }
        return result;
    }
}

Now, Once we are ready with Repository, now lets Setup Dependency Injection

Setup Dependency Injection

Open Startup.cs class file.

 services.AddScoped<IDepartmentRepository, DepartmentRepository>();
 services.AddScoped<IEmployeeRepository, EmployeeRepository>();

 services.AddDbContext<APIDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("EmployeeAppCon")));

Enable CORS

//Enable CORS
services.AddCors(c =>
 {
    c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod()
      .AllowAnyHeader());
 });
 app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

Swagger

services.AddSwaggerGen(options => {
    options.SwaggerDoc("v1", new OpenApiInfo {
        Title = "WEB API",
            Version = "v1"
    });
});
app.UseSwagger();
app.UseSwaggerUI(c => {
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "WEB API");
    c.DocumentTitle = "WEB API";
    c.DocExpansion(DocExpansion.List);
});

Complete Startup.cs class file code.

public class Startup {
    public Startup(IConfiguration configuration) {
        Configuration = configuration;
    }
    public IConfiguration Configuration {
        get;
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services) {
        services.AddScoped < IDepartmentRepository, DepartmentRepository > ();
        services.AddScoped < IEmployeeRepository, EmployeeRepository > ();
        services.AddDbContext < APIDbContext > (options => options.UseSqlServer(Configuration.GetConnectionString("EmployeeAppCon")));
        services.AddSwaggerGen(options => {
            options.SwaggerDoc("v1", new OpenApiInfo {
                Title = "WEB API",
                    Version = "v1"
            });
        });
        //Enable CORS
        services.AddCors(c => {
            c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        });
        //JSON Serializer
        services.AddControllersWithViews().AddNewtonsoftJson(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore).AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
        services.AddControllers();
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        if (env.IsDevelopment()) {
            app.UseDeveloperExceptionPage();
        }
        app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints => {
            endpoints.MapControllers();
        });
        app.UseSwagger();
        app.UseSwaggerUI(c => {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "WEB API");
            c.DocumentTitle = "WEB API";
            c.DocExpansion(DocExpansion.List);
        });
        app.UseStaticFiles(new StaticFileOptions {
            FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Photos")),
                RequestPath = "/Photos"
        });
    }
}

Note: In Startup.cs class, We have added Dependency Injection, Swagger, and CORS. Also, I have added StaticFiles for the file upload path.

Now let's start creating a Controller

Create a Controller and Create an API call

Department Controller.

[Route("api/[controller]")]
[ApiController]
public class DepartmentController: ControllerBase {
    private readonly IDepartmentRepository _department;
    public DepartmentController(IDepartmentRepository department) {
            _department = department ??
                throw new ArgumentNullException(nameof(department));
        }
        [HttpGet]
        [Route("GetDepartment")]
    public async Task < IActionResult > Get() {
            return Ok(await _department.GetDepartment());
        }
        [HttpGet]
        [Route("GetDepartmentByID/{Id}")]
    public async Task < IActionResult > GetDeptById(int Id) {
            return Ok(await _department.GetDepartmentByID(Id));
        }
        [HttpPost]
        [Route("AddDepartment")]
    public async Task < IActionResult > Post(Department dep) {
            var result = await _department.InsertDepartment(dep);
            if (result.DepartmentId == 0) {
                return StatusCode(StatusCodes.Status500InternalServerError, "Something Went Wrong");
            }
            return Ok("Added Successfully");
        }
        [HttpPut]
        [Route("UpdateDepartment")]
    public async Task < IActionResult > Put(Department dep) {
            await _department.UpdateDepartment(dep);
            return Ok("Updated Successfully");
        }
        [HttpDelete]
    //[HttpDelete("{id}")]
    [Route("DeleteDepartment")]
    public JsonResult Delete(int id) {
        _department.DeleteDepartment(id);
        return new JsonResult("Deleted Successfully");
    }
}

Employee Controller

[Route("api/[controller]")]
[ApiController]
public class EmployeeController: ControllerBase {
    private readonly IEmployeeRepository _employee;
    private readonly IDepartmentRepository _department;
    public EmployeeController(IEmployeeRepository employee, IDepartmentRepository department) {
            _employee = employee ??
                throw new ArgumentNullException(nameof(employee));
            _department = department ??
                throw new ArgumentNullException(nameof(department));
        }
        [HttpGet]
        [Route("GetEmployee")]
    public async Task < IActionResult > Get() {
            return Ok(await _employee.GetEmployees());
        }
        [HttpGet]
        [Route("GetEmployeeByID/{Id}")]
    public async Task < IActionResult > GetEmpByID(int Id) {
            return Ok(await _employee.GetEmployeeByID(Id));
        }
        [HttpPost]
        [Route("AddEmployee")]
    public async Task < IActionResult > Post(Employee emp) {
            var result = await _employee.InsertEmployee(emp);
            if (result.EmployeeID == 0) {
                return StatusCode(StatusCodes.Status500InternalServerError, "Something Went Wrong");
            }
            return Ok("Added Successfully");
        }
        [HttpPut]
        [Route("UpdateEmployee")]
    public async Task < IActionResult > Put(Employee emp) {
            await _employee.UpdateEmployee(emp);
            return Ok("Updated Successfully");
        }
        [HttpDelete]
        [Route("DeleteEmployee")]
    //[HttpDelete("{id}")]
    public JsonResult Delete(int id) {
            var result = _employee.DeleteEmployee(id);
            return new JsonResult("Deleted Successfully");
        }

        [Route("SaveFile")]
        [HttpPost]
        public JsonResult SaveFile()
        {
            try
            {
                var httpRequest = Request.Form;
                var postedFile = httpRequest.Files[0];
                string filename = postedFile.FileName;
                var physicalPath = _env.ContentRootPath + "/Photos/" + filename;

                using (var stream = new FileStream(physicalPath, FileMode.Create))
                {
                    stream.CopyTo(stream);
                }

                return new JsonResult(filename);
            }
            catch (Exception)
            {
                return new JsonResult("anonymous.png");
            }
        }

        [HttpGet]
        [Route("GetDepartment")]
    public async Task < IActionResult > GetAllDepartmentNames() {
        return Ok(await _department.GetDepartment());
    }
}

Now Run the Project using F5

API Running 

Get All Department

Get All Department

Get Department By Id

Department By Id

Add Department

Add Department

In Database

Add in DB

Update Department

Update Department

In Database 

Update Department DB

Delete Department

Delete

In Database

After Delete

Now, the Same we can try for Employee. 

I have added the full code as an attachment.

Note: We can use this web API for angular and react js curd demo.