One feature in ASP.NET Core that I was surprised by is the ability to inject a service into a specific action of a controller. Normally you inject into a constructor of a controller and keep the dependencies as local variables. So imagine a controller like this:
[Route(api/[controller])]
[ApiController]
public class PersonController : ControllerBase
{
private readonly IPersonDataService personDataService;
public PersonController(IPersonDataService personDataService)
{
this.personDataService = personDataService;
}
[HttpGet]
public async Task<ActionResult> Get(string name)
{
//Do something
return Ok(personDataService.Get(name));
}
[HttpPost]
public async Task<ActionResult> Post([FromBody] PersonViewModel person)
{
//Do something
return Ok();
}
}
This is pretty standard and there is nothing special with the service registration to achieve this. The one issue with this approach is that even if the Post is called, all the dependencies need to be loaded regardless. The IPersonDataService could be a transient service that is quite expensive to load. It would be better in some cases if you only load the dependency on the calls that need it. You can do this with Action injection.
To change to Action injection you can change the above code to:
[Route(api/[controller])]
[ApiController]
public class PersonController : ControllerBase
{
public PersonController()
{
}
[HttpGet]
public async Task<ActionResult> Get([FromServices]IPersonDataService personDataService, string name)
{
//Do something
return Ok(personDataService.Get(name));
}
[HttpPost]
public async Task<ActionResult> Post([FromBody] PersonViewModel person)
{
//Do something
return Ok();
}
}
One could argue that a more maintainable route would be to create a separate controller that has dependencies in the constructor that are needed by all actions but at least the action injection gives you another option.