Controller Actions
Create web APIs with ASP.NET Core
Learn the basics of creating a web API in ASP.NET Core.

ControllerBase
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBaseWe 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
| Attribute | What it does | Typical use |
|---|---|---|
| [HttpGet] | Maps an action to HTTP GET | Read/list endpoints |
| [HttpPost] | Maps an action to HTTP POST | Create/command endpoints |
| [HttpPut] | Maps an action to HTTP PUT | Replace/update endpoints |
| [HttpPatch] | Maps an action to HTTP PATCH | Partial updates |
| [HttpDelete] | Maps an action to HTTP DELETE | Delete endpoints |
| [HttpHead] | Maps an action to HTTP HEAD | Headers-only checks |
| [HttpOptions] | Maps an action to HTTP OPTIONS | Capability/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
| Attribute | Binding source | Typical use |
|---|---|---|
| [FromBody] | Request body | JSON DTO payloads |
| [FromQuery] | Query string | Filtering, paging, flags |
| [FromRoute] | Route values | /{id} parameters |
| [FromHeader] | Headers | Correlation/idempotency keys |
| [FromForm] | Form body | Multipart + uploads |
| [FromServices] | DI container | Inject 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
| Attribute | What it declares | Why it’s useful |
|---|---|---|
| [Consumes(...)] | Accepted request content types | Helps enforce/document request formats (e.g. JSON vs XML) |
| [Produces(...)] | Response content types | Documents the response format |
| [ProducesResponseType(...)] | Possible status codes (and optional body type) | Makes Swagger/OpenAPI accurate |
| [ProducesDefaultResponseType] | Default response type | Useful 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
| Attribute | What it does | Typical use |
|---|---|---|
| [Route("...")] | Sets route template at controller/action level | Base routes like "automations" |
| [HttpGet("...")] etc. | Verb + route template in one | Most common pattern for actions |
| Route constraints (e.g. {id:guid}) | Restricts route matching | Avoid ambiguous routes |
[ApiController]
[Route("automations")]
public class AutomationsController : ControllerBase
{
[HttpGet("{id:guid}")]
public IActionResult Get(Guid id) => Ok(id);
}Auth and access control
| Attribute | What it does | Typical use |
|---|---|---|
| [Authorize] | Requires authenticated/authorized user | Protect APIs |
| [AllowAnonymous] | Allows unauthenticated access | Public 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
| Attribute | What it does | Typical use |
|---|---|---|
| [ServiceFilter] / [TypeFilter] | Adds an MVC filter with DI support | Logging, validation, transactions |
| [ResponseCache] | Controls response caching headers | Cache-friendly GET endpoints |
| [RequestSizeLimit] | Sets max request body size | Upload endpoints |
| [NonAction] | Marks method as not an endpoint | Helper methods inside controller |
[HttpGet]
[ResponseCache(Duration = 60)]
public IActionResult GetCached() => Ok(new { ts = DateTimeOffset.UtcNow });