CRUD (Create, Read, Update, Delete) operations are fundamental in web applications. This guide provides a detailed overview of implementing CRUD operations in ASP.NET Core 8 Web API using best practices, including setup, controllers, services, repositories, and detailed examples.
CRUD operations form the backbone of most web applications, enabling users to create, read, update, and delete data. In ASP.NET Core, these operations can be efficiently implemented using the MVC pattern and Entity Framework Core (EF Core).
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
}
var builder = WebApplication.CreateBuilder(args);
// Add services to the container
builder.Services.AddControllers();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); //ms sql server
var app = builder.Build();
app.MapControllers();
app.Run();
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDatabase;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public decimal Price { get; set; }
}
public interface IProductRepository
{
Task<IEnumerable<Product>> GetAllAsync();
Task<Product> GetByIdAsync(int id);
Task AddAsync(Product product);
Task UpdateAsync(Product product);
Task DeleteAsync(int id);
}
public class ProductRepository : IProductRepository
{
private readonly ApplicationDbContext _context;
public ProductRepository(ApplicationDbContext context)
{
_context = context;
}
public async Task<IEnumerable<Product>> GetAllAsync()
{
return await _context.Products.ToListAsync();
}
public async Task<Product> GetByIdAsync(int id)
{
return await _context.Products.FindAsync(id);
}
public async Task AddAsync(Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
}
public async Task UpdateAsync(Product product)
{
_context.Products.Update(product);
await _context.SaveChangesAsync();
}
public async Task DeleteAsync(int id)
{
var product = await _context.Products.FindAsync(id);
if (product != null)
{
_context.Products.Remove(product);
await _context.SaveChangesAsync();
}
}
}
builder.Services.AddScoped<IProductRepository, ProductRepository>();
public interface IProductService
{
Task<IEnumerable<Product>> GetAllProductsAsync();
Task<Product> GetProductByIdAsync(int id);
Task AddProductAsync(Product product);
Task UpdateProductAsync(Product product);
Task DeleteProductAsync(int id);
}
public class ProductService : IProductService
{
private readonly IProductRepository _productRepository;
public ProductService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
public async Task<IEnumerable<Product>> GetAllProductsAsync()
{
return await _productRepository.GetAllAsync();
}
public async Task<Product> GetProductByIdAsync(int id)
{
return await _productRepository.GetByIdAsync(id);
}
public async Task AddProductAsync(Product product)
{
await _productRepository.AddAsync(product);
}
public async Task UpdateProductAsync(Product product)
{
await _productRepository.UpdateAsync(product);
}
public async Task DeleteProductAsync(int id)
{
await _productRepository.DeleteAsync(id);
}
}
builder.Services.AddScoped<IProductService, ProductService>();
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
var products = await _productService.GetAllProductsAsync();
return Ok(products);
}
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProduct(int id)
{
var product = await _productService.GetProductByIdAsync(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct(Product product)
{
await _productService.AddProductAsync(product);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
await _productService.UpdateProductAsync(product);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
await _productService.DeleteProductAsync(id);
return NoContent();
}
}
public class Product
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Range(0.01, 1000.00)]
public decimal Price { get; set; }
}
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception has occurred.");
await HandleExceptionAsync(context, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var response = new { message = "An unexpected error occurred.", detail = exception.Message };
var jsonResponse = JsonSerializer.Serialize(response);
return context.Response.WriteAsync(jsonResponse);
}
}
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseMiddleware<ExceptionHandlingMiddleware>();
app.MapControllers();
app.Run();
Implementing CRUD operations in ASP.NET Core 8 Web API involves creating models, repositories, services, and controllers. Following best practices such as using repository and service layers, asynchronous methods, model validation, and global exception handling ensures that your application is robust, maintainable, and scalable. This comprehensive guide provides the foundation for building effective CRUD operations in ASP.NET Core 8 Web API.