ASP.NET Core Web API

Getting Started with Web API

ASP.NET Core Web API is a framework for building HTTP services that can be accessed by a broad range of clients, including browsers and mobile devices. It's built on top of ASP.NET Core, offering high performance, flexibility, and a modern development experience.

To create a new Web API project, you can use the .NET CLI:

dotnet new webapi -n MyWebApiProject

This command will create a new directory named MyWebApiProject containing the basic structure of a Web API application. The project includes a sample controller, `WeatherForecastController.cs`, which you can examine to understand the fundamental concepts.

Key components of a Web API include:

  • Controllers: Classes that handle incoming HTTP requests.
  • Routing: Mechanism for mapping URLs to controller actions.
  • Model Binding: Process of creating .NET objects from incoming HTTP request data.
  • Serialization: Converting .NET objects into formats like JSON or XML for transmission.

Controllers

Controllers are the heart of your Web API. They are regular C# classes that inherit from ControllerBase or Controller (if you need view support, which is less common for pure APIs).

Here's a simple example of a controller:

Sample Controller (ProductsController.cs)


using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private static List _products = new List
    {
        new Product { Id = 1, Name = "Laptop", Price = 1200.00m },
        new Product { Id = 2, Name = "Keyboard", Price = 75.50m },
        new Product { Id = 3, Name = "Mouse", Price = 25.00m }
    };

    [HttpGet]
    public ActionResult> GetProducts()
    {
        return Ok(_products);
    }

    [HttpGet("{id}")]
    public ActionResult GetProduct(int id)
    {
        var product = _products.FirstOrDefault(p => p.Id == id);
        if (product == null)
        {
            return NotFound();
        }
        return Ok(product);
    }

    [HttpPost]
    public ActionResult CreateProduct(Product product)
    {
        product.Id = _products.Max(p => p.Id) + 1;
        _products.Add(product);
        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
                    

The [ApiController] attribute enables API-specific behaviors, and [Route("api/[controller]")] defines the base route for the controller (e.g., /api/products).

HTTP verbs are mapped using attributes like [HttpGet], [HttpPost], [HttpPut], [HttpDelete], etc.

Routing

Routing determines how incoming requests are mapped to specific controller actions. ASP.NET Core Web API uses a convention-based routing system, often defined by route templates.

Route templates can include literal values and parameters. For example, [Route("api/products/{id}")] defines a route with an id parameter.

You can also define routes directly on action methods:


[HttpGet("details/{productId}")]
public IActionResult GetProductDetails(int productId)
{
    // ...
}
                

This would map to a URL like /api/products/details/123.

Model Binding

Model binding is the process of taking incoming HTTP request data (from the URL, query string, request body, headers, etc.) and creating .NET objects that can be used in your controller actions.

By default, parameters are bound from:

  • The request body for complex types (like objects sent in POST/PUT requests).
  • The query string for simple types (like integers, strings) if not specified otherwise.
  • The route data for parameters matching route template segments.

You can explicitly specify the source of binding using attributes like [FromBody], [FromQuery], [FromRoute], and [FromHeader].

Model Binding Example


[HttpPost]
public IActionResult PostData([FromBody] MyDataModel data)
{
    // 'data' is bound from the request body
    return Ok(data);
}

[HttpGet]
public IActionResult GetData([FromQuery] string searchParam, int pageNumber)
{
    // 'searchParam' is from query string (?searchParam=value)
    // 'pageNumber' is also from query string
    return Ok($"Searching for: {searchParam}, Page: {pageNumber}");
}
                    

Serialization

Web APIs communicate by sending and receiving data in formats like JSON and XML. ASP.NET Core Web API uses System.Text.Json (by default) or Newtonsoft.Json for serialization and deserialization.

You can configure serialization options globally or per-request.

JSON is the de facto standard for Web APIs.

The [ApiController] attribute automatically enables JSON formatting for responses where a return type is specified.

Authentication & Authorization

Securing your Web API is crucial. ASP.NET Core provides robust mechanisms for both authentication (verifying who the user is) and authorization (determining what the user can do).

Authentication

Common authentication schemes include:

  • JWT Bearer Tokens: Widely used for stateless authentication in APIs.
  • Cookies: Typically used for browser-based applications.
  • OAuth/OpenID Connect: For delegated authorization and federated identity.

You configure authentication in your Program.cs (or Startup.cs in older versions).

Authorization

Once authenticated, you need to authorize access to resources. This can be done using:

  • Role-based authorization: [Authorize(Roles = "Admin")]
  • Policy-based authorization: For more complex rules.
  • User claims: Checking specific attributes associated with the user.

Authorization Example


[HttpGet("admin-only")]
[Authorize(Roles = "Administrator")]
public IActionResult GetAdminData()
{
    return Ok("This is sensitive admin data.");
}
                    

Testing Web APIs

Comprehensive testing is essential for building reliable APIs. ASP.NET Core provides excellent support for unit and integration testing.

Unit Testing

Focuses on testing individual components (like controller actions or business logic) in isolation. Mocking dependencies is common here.

Integration Testing

Tests the entire application pipeline, including routing, model binding, controllers, and actual HTTP requests and responses. The WebApplicationFactory class is invaluable for this.

You can use testing frameworks like xUnit, NUnit, or MSTest.

Integration Test Snippet (using xUnit)


using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
using System.Net.Http;
using System.Threading.Tasks;

public class ProductsControllerIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly WebApplicationFactory<Program> _factory;

    public ProductsControllerIntegrationTests(WebApplicationFactory<Program> factory)
    {
        _factory = factory;
    }

    [Fact]
    public async Task Get_Products_ReturnsOk()
    {
        var client = _factory.CreateClient();
        var response = await client.GetAsync("/api/products");
        response.EnsureSuccessStatusCode(); // Status Code 200-299
        Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString());
    }
}