CRUD Operations Using .NET 5.0 Web API

In this article, we will learn about how we can perform CRUD (Create, Read, Update, Delete) operations using .NET 5.0 Web API.

Prerequisites

Let’s first open Visual Studio 2019 and create a .NET 5.0 application by clicking ‘Create a new project‘.

Choose ASP.NET Core Web API.

Now, set the Project name and Location, and then click on the Next button.

Now, set the Target Framework as .NET 5.0, and then click on the Create button.

.NET 5.0 application is created. So now let’s delete WeatherForecast.cs and WeatherForecastController.cs from it.

Now, we will install two NuGet packages Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Tools, which are required for Code First migration.

Now create an Entities folder and inside that folder create a Book.cs model class of record type and BookDbContext.cs class that will inherit to DbContext class, then add the following code to it.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CRUD_.NET_5.Entities
{
    public record Book
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; init; }
        public string Name { get; init; }
        [Column(TypeName = "decimal(18,2)")]
        public decimal Price { get; init; }
        public DateTime CreatedDate { get; init; }
    }
}
using Microsoft.EntityFrameworkCore;

namespace CRUD_.NET_5.Entities
{
    public class BookDbContext : DbContext
    {
        public BookDbContext(DbContextOptions options) : base(options)
        {

        }
        public DbSet<Book> Books { get; set; }
    }
}

Open the appsettings.json file and add the code to it.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "SqlConnection": "Server=DESKTOP-78L71550; database=BookDemoDB; User Id=sa; Password=thecodehubs;"
  }
}

Open the Startup.cs file and add the code to it.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using CRUD_.NET_5.Entities;
using Microsoft.EntityFrameworkCore;
using CRUD_.NET_5.Repositories;
using CRUD_.NET_5.Repositories.Interfaces;

namespace CRUD_.NET_5
{
    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.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "CRUD_.NET_5", Version = "v1" });
            });
            services.AddDbContext<BookDbContext>(item => item.UseSqlServer(Configuration.GetConnectionString("SqlConnection")));
            services.AddScoped<IBooksRepository, BooksRepository>();
        }

        // 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.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "CRUD_.NET_5 v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Now create a Repositories folder and inside that folder create an IBooksRepository.cs interface and BooksRepository.cs class, then add the following code to it.

using CRUD_.NET_5.Entities;
using System.Collections.Generic;

namespace CRUD_.NET_5.Repositories.Interfaces
{
    public interface IBooksRepository
    {
        Book GetBook(int id);
        IEnumerable<Book> GetBooks();
        void AddBook(Book book);
        void UpdateBook(Book book);
        void DeleteBook(Book book);
    }
}
using CRUD_.NET_5.Entities;
using CRUD_.NET_5.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;

namespace CRUD_.NET_5.Repositories
{
    public class BooksRepository : IBooksRepository
    {
        protected BookDbContext Context;

        public BooksRepository(BookDbContext context)
        {
            Context = context;
        }
        public IEnumerable<Book> GetBooks()
        {
            return Context.Books.AsNoTracking().ToList();
        }
        public Book GetBook(int id)
        {
            return Context.Books.AsNoTracking().FirstOrDefault(b => b.Id == id);
        }
        public void AddBook(Book book)
        {
            Context.Books.Add(book);
            Context.SaveChanges();
        }
        public void UpdateBook(Book book)
        {
            Context.Entry(book).State = EntityState.Modified;
            Context.SaveChanges();
        }
        public void DeleteBook(Book book)
        {
            Context.Remove(book);
            Context.SaveChanges();
        }
    }
}

Now create a DTOs folder and create three model classes (AddBookDTO.cs, BookDTO.cs, UpdateBookDTO.cs) in it.

using System;
using System.ComponentModel.DataAnnotations;

namespace CRUD_.NET_5.DTOs
{
    public record AddBookDTO
    {
        [Required]
        public string Name { get; init; }
        [Required]
        [Range(10, 500)]
        public decimal Price { get; init; }
    }
}
using System;

namespace CRUD_.NET_5.DTOs
{
    public record BookDTO
    {
        public int Id { get; init; }
        public string Name { get; init; }
        public decimal Price { get; init; }
        public DateTime CreatedDate { get; init; }
    }
}
using System;
using System.ComponentModel.DataAnnotations;

namespace CRUD_.NET_5.DTOs
{
    public record UpdateBookDTO
    {
        [Required]
        public string Name { get; init; }
        [Required]
        [Range(10, 500)]
        public decimal Price { get; init; }
    }
}

Now, open the package manager console to fire the commands.

  • Add-Migration MigrationName
Add-Migration Initial
  • Update-Database
Update-Database

BookDemoDB database with Books table is created.


Now create and open the BooksController.cs file and add the code to it.

using CRUD_.NET_5.DTOs;
using CRUD_.NET_5.Entities;
using CRUD_.NET_5.Repositories.Interfaces;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CRUD_.NET_5.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BooksController : ControllerBase
    {
        private readonly IBooksRepository _booksRepository;

        public BooksController(IBooksRepository booksRepository)
        {
            _booksRepository = booksRepository;
        }

        //GET /books
        [HttpGet]
        public IEnumerable<BookDTO> GetBooks()
        {
            return _booksRepository.GetBooks().Select(b => new BookDTO
            {
                Id = b.Id,
                Name = b.Name,
                Price = b.Price,
                CreatedDate = b.CreatedDate
            });
        }

        //GET /books/{id}
        [HttpGet("{id}")]
        public ActionResult<BookDTO> GetBook(int id)
        {
            Book book = _booksRepository.GetBook(id);
            if (book is null) return NotFound();
            return new BookDTO
            {
                Id = book.Id,
                Name = book.Name,
                Price = book.Price,
                CreatedDate = book.CreatedDate
            };
        }

        //POST /AddBook
        [HttpPost("[action]")]
        public ActionResult<BookDTO> AddBook(AddBookDTO addBookDTO)
        {
            Book book = new()
            {
                Name = addBookDTO.Name,
                Price = addBookDTO.Price,
                CreatedDate = DateTime.Now
            };
            _booksRepository.AddBook(book);
            return CreatedAtAction(nameof(GetBook), new { id = book.Id }, new BookDTO
            {
                Id = book.Id,
                Name = book.Name,
                Price = book.Price,
                CreatedDate = book.CreatedDate
            });
        }

        //PUT /UpdateBook/{id}
        [HttpPut("[action]/{id}")]
        public ActionResult UpdateBook(int id, UpdateBookDTO updateBookDTO)
        {
            Book book = _booksRepository.GetBook(id);
            if (book is null) return NotFound();
            Book updatedBook = book with
            {
                Name = updateBookDTO.Name,
                Price = updateBookDTO.Price
            };
            _booksRepository.UpdateBook(updatedBook);
            return Ok();
        }

        //DELETE /DeleteBook/{id}
        [HttpDelete("[action]/{id}")]
        public ActionResult DeleteBook(int id)
        {
            Book book = _booksRepository.GetBook(id);
            if (book is null) return NotFound();
            _booksRepository.DeleteBook(book);
            return Ok();
        }
    }
}

Output:

Please give your valuable feedback and if you have any questions or issues about this article, please let me know.

Also, check AddTransient VS AddScoped VS AddSingleton In .NET Core

Submit a Comment

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

Subscribe

Select Categories