This article will introduce the controller routing rule with a demo
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
1.Class definition
Controller is for MVC, ControllerBase is for web API controller
[ApiController]
用这个注解来提供一些默认行为,路径匹配,错误处理,参数获取等等
[Route("[controller]")]
controller就是当前的controller这个对象,可以是这个controller内定义的不同路径。
最后的路径就是base url加上在此controller定义的不同的路径
例如controller里面定义了一个weatherforecast的api,那么这个api完整的路径是https://localhost:{PORT}/weatherforecast
如果这里写的是:
[Route("api/[controller]")]
那这个api的完整路径就是:https://localhost:{PORT}/api/weatherforecast
每个路径的
2.Method definition
2.1 naming convention
[HttpGet(Name = "GetWeatherForecast")]
it’s a get, and the path is /weatherforecast
the default value for the name is: Get{ControllerName}, the controller name is the class name without the ‘controller’
add subfix to the router:
[HttpGet("suffix")]
2.2 Restfule Api example
Get by id
[HttpGet("{id}")]
Post
[HttpPost]
public IActionResult Create(Pizza pizza)
Put
[HttpPut("{id}")]
public IActionResult UpdatePizza(int id, Pizza pizza)
Delete
[HttpDelete("{id}")]
public IActionResult DeletePizza(int id)
2.3 Controller action return types
Specific type vs ActionResult and IActionResult
you can use the specific type in simple case.
but in some case, if you need to return multiple type as a return,you need the
IActionResult, because you can do the error handling and it can return both the specific type and badRequest/NotFound result
and also, if you know the specific type when you use the IActionResult, then you can use ActionResult<>, just use it as an generic
in this case it can simplify some setting because the framework already know the type:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
vs
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
3. Advance concept(which is not Support in Java)
Asynchronous action vs sunchronous action
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Product))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
if (!_repository.TryGetProduct(id, out var product))
{
return NotFound();
}
return Ok(product);
}
vs
[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync(Product product)
{
if (product.Description.Contains("XYZ Widget"))
{
return BadRequest();
}
await _repository.AddProductAsync(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
link:
https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-6.0