Controller Actions

Create web APIs with ASP.NET Core
Learn the basics of creating a web API in ASP.NET Core.
https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-10.0

ControllerBase

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase?view=aspnetcore-10.0

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

We inherit from ControllerBase for APIs; which offers many properties and methods for handling HTTP requests.

Note: this is not Controller which inherits from ControllerBase; since this includes additional features to support for views and web pages.

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

The action result specifies the response aka NotFound or Created

Attributes

Attributes are used to configure the behaviour of a controller, aka what its route is and what code it might respond with.

HTTP action attributes

AttributeWhat it doesTypical use
[HttpGet]Maps an action to HTTP GETRead/list endpoints
[HttpPost]Maps an action to HTTP POSTCreate/command endpoints
[HttpPut]Maps an action to HTTP PUTReplace/update endpoints
[HttpPatch]Maps an action to HTTP PATCHPartial updates
[HttpDelete]Maps an action to HTTP DELETEDelete endpoints
[HttpHead]Maps an action to HTTP HEADHeaders-only checks
[HttpOptions]Maps an action to HTTP OPTIONSCapability/CORS preflight
[ApiController]
[Route("widgets")]
public class WidgetsController : ControllerBase
{
    [HttpGet("{id:guid}")]
    public ActionResult<string> Get(Guid id) => Ok($"widget {id}");

    [HttpPost]
    public IActionResult Create([FromBody] object dto) => Created("widgets/...", dto);
}

Binding source attributes

AttributeBinding sourceTypical use
[FromBody]Request bodyJSON DTO payloads
[FromQuery]Query stringFiltering, paging, flags
[FromRoute]Route values/{id} parameters
[FromHeader]HeadersCorrelation/idempotency keys
[FromForm]Form bodyMultipart + uploads
[FromServices]DI containerInject per-action dependency
[HttpGet("{id:guid}")]
public IActionResult Get(
    [FromRoute] Guid id,
    [FromQuery] bool includeDetails = false,
    [FromHeader(Name = "X-Correlation-Id")] string? correlationId = null)
{
    return Ok(new { id, includeDetails, correlationId });
}

Content negotiation and response metadata

AttributeWhat it declaresWhy it’s useful
[Consumes(...)]Accepted request content typesHelps enforce/document request formats (e.g. JSON vs XML)
[Produces(...)]Response content typesDocuments the response format
[ProducesResponseType(...)]Possible status codes (and optional body type)Makes Swagger/OpenAPI accurate
[ProducesDefaultResponseType]Default response typeUseful for standard error payloads
[HttpPost]
[Consumes("application/json")]
[Produces("application/json")]
[ProducesResponseType(typeof(MyResponseDto), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<MyResponseDto> Create([FromBody] MyRequestDto dto)
{
    return Created("...", new MyResponseDto());
}

Routing attributes

AttributeWhat it doesTypical use
[Route("...")]Sets route template at controller/action levelBase routes like "automations"
[HttpGet("...")] etc.Verb + route template in oneMost common pattern for actions
Route constraints (e.g. {id:guid})Restricts route matchingAvoid ambiguous routes
[ApiController]
[Route("automations")]
public class AutomationsController : ControllerBase
{
    [HttpGet("{id:guid}")]
    public IActionResult Get(Guid id) => Ok(id);
}

Auth and access control

AttributeWhat it doesTypical use
[Authorize]Requires authenticated/authorized userProtect APIs
[AllowAnonymous]Allows unauthenticated accessPublic endpoints (health/auth)
[ApiController]
[Route("secure")]
[Authorize]
public class SecureController : ControllerBase
{
    [HttpGet("ping")]
    public IActionResult Ping() => Ok("ok");

    [AllowAnonymous]
    [HttpGet("public")]
    public IActionResult Public() => Ok("public ok");
}

Cross-cutting filters and behavior

AttributeWhat it doesTypical use
[ServiceFilter] / [TypeFilter]Adds an MVC filter with DI supportLogging, validation, transactions
[ResponseCache]Controls response caching headersCache-friendly GET endpoints
[RequestSizeLimit]Sets max request body sizeUpload endpoints
[NonAction]Marks method as not an endpointHelper methods inside controller
[HttpGet]
[ResponseCache(Duration = 60)]
public IActionResult GetCached() => Ok(new { ts = DateTimeOffset.UtcNow });