ASP.NET Core Web API and RESTful Principles
1. Understanding Web API
ASP.NET Core Web API allows developers to create HTTP services that can be consumed by a variety of clients, including browsers, mobile applications, and other services. Web APIs are lightweight, stateless, and can be consumed by any device capable of making HTTP requests.
Key Concepts:
- Stateless Communication: Each request from a client must contain all the information needed for the server to process the request.
- JSON/XML Format: ASP.NET Core Web API primarily communicates using JSON, but it can also support other formats like XML.
2. RESTful Architecture
REST (Representational State Transfer) is an architectural style that defines constraints and principles to create web services.
RESTful Principles:
- Client-Server Architecture: Separation of concerns between the client and server.
- Statelessness: Every interaction between the client and server is independent.
- Cacheability: Responses must explicitly indicate whether caching is allowed.
- Uniform Interface: All requests are made to a single, well-defined interface using standard HTTP methods.
- Resource Identification: Resources (data) are identified using URIs.
3. RESTful Constraints in Web API
Resources and URIs:
GET /api/products/12345HTTP Methods in REST:
- GET: Retrieve data.
- POST: Create a new resource.
- PUT: Update an existing resource.
- DELETE: Remove a resource.
4. Implementing a Simple Web API with REST Principles
Step 1: Create a New ASP.NET Core Web API Project
dotnet new webapi -n ProductApiStep 2: Define the Product Model
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
}Step 3: Create a ProductsController
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
private static List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 999.99m, Description = "A high-performance laptop" },
new Product { Id = 2, Name = "Smartphone", Price = 499.99m, Description = "A flagship smartphone" },
};
// GET: api/products
[HttpGet]
public ActionResult<IEnumerable<Product>> GetProducts()
{
return products;
}
// GET: api/products/1
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(int id)
{
var product = products.FirstOrDefault(p => p.Id == id);
if (product == null)
return NotFound();
return product;
}
// POST: api/products
[HttpPost]
public ActionResult<Product> CreateProduct(Product newProduct)
{
newProduct.Id = products.Max(p => p.Id) + 1;
products.Add(newProduct);
return CreatedAtAction(nameof(GetProduct), new { id = newProduct.Id }, newProduct);
}
// PUT: api/products/1
[HttpPut("{id}")]
public IActionResult UpdateProduct(int id, Product updatedProduct)
{
var product = products.FirstOrDefault(p => p.Id == id);
if (product == null)
return NotFound();
product.Name = updatedProduct.Name;
product.Price = updatedProduct.Price;
product.Description = updatedProduct.Description;
return NoContent(); // 204 No Content
}
// DELETE: api/products/1
[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
var product = products.FirstOrDefault(p => p.Id == id);
if (product == null)
return NotFound();
products.Remove(product);
return NoContent();
}
}5. HTTP Status Codes
| Status Code | Meaning |
|---|---|
| 200 OK | The request was successful |
| 201 Created | A resource was successfully created |
| 204 No Content | Successful, but no content to return |
| 400 Bad Request | The request was malformed or invalid |
| 404 Not Found | The resource was not found |
Web API Controllers
In ASP.NET Core, Web API Controllers serve as the backbone for handling HTTP requests.
1. What is a Web API Controller?
A Web API controller is a class that handles HTTP requests and generates appropriate HTTP responses. It inherits from ControllerBase and uses attributes to define routing, HTTP methods, and input/output handling.
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
// Example action methods
}[ApiController]: Makes it easier to build a Web API by handling automatic model state validation.[Route]: Defines the URI path for the controller.
2. Action Methods in Web API Controllers
Attribute Routing:
[HttpGet("search/{name}")]
public ActionResult<IEnumerable<Product>> SearchProducts(string name)
{
var matchedProducts = products.Where(p => p.Name.Contains(name, StringComparison.OrdinalIgnoreCase)).ToList();
if (!matchedProducts.Any())
return NotFound();
return Ok(matchedProducts);
}3. Binding Data to Controllers
ASP.NET Core provides several ways to bind incoming HTTP data:
- From Route: Bind data from route parameters.
- From Query: Bind data from query strings.
- From Body: Bind data from the request body (usually JSON).
[HttpGet("{id}")]
public ActionResult<Product> GetProduct(int id, [FromQuery] string search)
{
// logic...
}4. Validation in Web API Controllers
public class Product
{
public int Id { get; set; }
[Required(ErrorMessage = "Name is required.")]
[MaxLength(50)]
public string Name { get; set; }
[Range(0.01, 9999.99, ErrorMessage = "Price must be between 0.01 and 9999.99.")]
public decimal Price { get; set; }
[StringLength(200)]
public string Description { get; set; }
}5. Dependency Injection in Web API Controllers
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public ActionResult<IEnumerable<Product>> GetProducts()
{
return Ok(_productService.GetProducts());
}
}API Controllers vs. MVC Controllers
1. Overview
| Feature | API Controllers | MVC Controllers |
|---|---|---|
| Base Class | ControllerBase | Controller (inherits ControllerBase) |
| Return Types | JSON/XML data | HTML views |
| View Support | No | Yes (Razor views) |
[ApiController] | Yes | No |
| Purpose | RESTful services | Traditional web apps |
2. ControllerBase vs. Controller
ControllerBase: For API controllers. Focused on returning data (JSON, XML). No view support.Controller: For MVC controllers. Inherits allControllerBasefeatures plus view methods.
3. Return Types
In API Controllers:
[HttpGet]
public ActionResult<IEnumerable<Product>> GetProducts()
{
return Ok(new List<Product>());
}In MVC Controllers:
public IActionResult Index()
{
return View(); // Returns an HTML view
}4. Automatic Model Validation
In API controllers with [ApiController], model validation is automatic. In MVC controllers, you manually check ModelState.IsValid.
Entity Framework Core with Web API
1. Setting Up DbContext
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Product> Products { get; set; }
}2. Configure Connection String
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=ecommerce_db;Trusted_Connection=True;"
}
}3. Register DbContext in Program.cs
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));4. CRUD Operations
Create (POST):
[HttpPost]
public async Task<ActionResult<Product>> CreateProduct([FromBody] Product product)
{
_context.Products.Add(product);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetProductById), new { id = product.Id }, product);
}Read (GET) All:
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetProducts()
{
var products = await _context.Products.ToListAsync();
return Ok(products);
}Read (GET) by ID:
[HttpGet("{id}")]
public async Task<ActionResult<Product>> GetProductById(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
return NotFound();
return Ok(product);
}Update (PUT):
[HttpPut("{id}")]
public async Task<IActionResult> UpdateProduct(int id, [FromBody] Product product)
{
if (id != product.Id)
return BadRequest();
_context.Entry(product).State = EntityState.Modified;
await _context.SaveChangesAsync();
return NoContent();
}Delete (DELETE):
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)
{
var product = await _context.Products.FindAsync(id);
if (product == null)
return NotFound();
_context.Products.Remove(product);
await _context.SaveChangesAsync();
return NoContent();
}5. Migration: Creating the Database
dotnet ef migrations add InitialCreate
dotnet ef database updateDifferent Return Types of Web API Action Methods
| Return Type | Description | Use Case |
|---|---|---|
| Void | Returns nothing | Rare in Web APIs |
Primitive Types (int, string, bool) | Basic data | Simple ID, message |
| IEnumerable<T> / List<T> | Collections | Lists of items |
| Object (T) | Single entity | Single resource |
| Task / Task<T> | Async operations | I/O-bound tasks |
| ActionResult<T> | Data + status codes | Flexible responses |
| IActionResult | Full control over response | Any HTTP response |
| FileResult | File downloads | PDFs, images, CSVs |
| Custom Response Wrappers | Consistent response format | Structured API responses |
ControllerBase
ControllerBase is a foundational class in ASP.NET Core MVC and Web API applications.
Key Features:
- Action methods for handling HTTP requests
- Response types for returning various HTTP responses
- Dependency injection support
- Model binding and validation
Key Methods:
Ok(): Returns 200 OK with optional content.CreatedAtAction(): Returns 201 Created.NotFound(): Returns 404 Not Found.BadRequest(): Returns 400 Bad Request.NoContent(): Returns 204 No Content.
Key Points to Remember
- RESTful Principles: Focus on resource-based URIs, stateless communication, and uniform interfaces.
- Web API Controllers: Inherit from
ControllerBase, handle HTTP requests, return data responses. - API vs MVC Controllers: API controllers handle data without views; MVC controllers manage views.
- Entity Framework Core: ORM for database operations with CRUD support.
- Return Types:
IActionResultprovides flexibility;ActionResult<T>combines data and status codes. - ControllerBase: Core class for Web API controllers, focusing on HTTP request handling.