DotNet Core WebAPI C# CRUD Part2

Amir Hoss
3 min readJul 31, 2023

--

Part I [Read] | Part II ( Create, Update, and Delete)

Adding an item with POST

// Controllers/ProductsController.cs


[HttpPost]
public async Task<ActionResult> CreateProduct(Product product)
{
// if (!ModelState.IsValid)
// {
// return BadRequest();
// }
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

Model validation

// Models/Product.cs
using System.ComponentModel.DataAnnotations;

namespace Cousrse01.API.Models;

public class Product
{
[Required]
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? Sku { get; set; }
public decimal Price { get; set; }
public string? Description { get; set; }
//is available
public bool IsAvailable { get; set; }

// Category Id
[Required]
public int CategoryId { get; set; }

public virtual Category? Category { get; set; } = null!;

}

Enable SuppressModelStateInvalidFilter instead of check ModelState.IsValid

// Using this code in Program.cs
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});

// Instead of check validation in ProductsController
if (!ModelState.IsValid)
{
return BadRequest();
}
// Program.cs

using Cousrse01.API.Models;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddDbContext<ShopContext>(options =>
{
options.UseInMemoryDatabase("Shop");
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Updating an item with PUT

// Controllers/ProductsController.cs

[HttpPut("{id}")]
public async Task<ActionResult> UpdateProduct(int id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
_context.Entry(product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Products.Any(p => p.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}

Deleting an item with DELETE

// Controllers/ProductsController.cs

[HttpDelete("{id}")]
public async Task<ActionResult> DeleteProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound();
}
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return NoContent();
}

Challenge: Deleting several items

// Controllers/ProductsController.cs

// Deleting several items
[HttpDelete]
public async Task<ActionResult> DeleteProducts([FromQuery] int[] ids)
{
var products = await _context.Products.Where(p => ids.Contains(p.Id)).ToArrayAsync();
if (products.Length == 0)
{
return NotFound();
}
_context.Products.RemoveRange(products);
await _context.SaveChangesAsync();
return NoContent();
}
// Controllers/ProductsController.cs

using Cousrse01.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace Cousrse01.Controllers;

[ApiController]
[Route("[controller]")]

public class ProductsController : ControllerBase
{
private readonly ShopContext _context;

public ProductsController(ShopContext context)
{
_context = context;
_context.Database.EnsureCreated();
}

[HttpGet]
public async Task<ActionResult> AllProducts()
{
Console.WriteLine("Get Products");
//return "Get Products";
return Ok(await _context.Products.ToArrayAsync());
}

[HttpGet("{id}")]
public async Task<ActionResult> GetProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}

[HttpPost]
public async Task<ActionResult> CreateProduct(Product product)
{
// if (!ModelState.IsValid)
// {
// return BadRequest();
// }
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}

[HttpPut("{id}")]
public async Task<ActionResult> UpdateProduct(int id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
_context.Entry(product).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!_context.Products.Any(p => p.Id == id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}

[HttpDelete("{id}")]
public async Task<ActionResult> DeleteProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
{
return NotFound();
}
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return NoContent();
}

// Deleting several items
[HttpDelete]
public async Task<ActionResult> DeleteProducts([FromQuery] int[] ids)
{
var products = await _context.Products.Where(p => ids.Contains(p.Id)).ToArrayAsync();
if (products.Length == 0)
{
return NotFound();
}
_context.Products.RemoveRange(products);
await _context.SaveChangesAsync();
return NoContent();
}
}

Run and Test

dotnet run
# The port is sample
http://localhost:5027/swagger/index.html

<< Part I [Read]

--

--

Amir Hoss

✔Senior PHP Developer✔Mobile Developer✔MySQL Administrator [myWebsite:https://amirhome.com]