12

In the following code (from https://github.com/JasonGT/NorthwindTraders/blob/master/Src/WebUI/Controllers/BaseController.cs), it's a base control inherited by all controllers.

[ApiController]
[Route("api/[controller]/[action]")]
public abstract class BaseController : ControllerBase
{
    private IMediator _mediator;

    protected IMediator Mediator => _mediator ??= HttpContext.RequestServices.GetService<IMediator>();
}

The sub-class controllers then just use the property of Mediator.

How it differs from just adding services.AddScope<Mediator>(); in Startup.cs and then inject mediator.

// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    // services.AddSingleton<Mediator>(); 
    services.AddScope<Mediator>();
Julian
  • 33,915
  • 22
  • 119
  • 174
ca9163d9
  • 27,283
  • 64
  • 210
  • 413
  • 1
    In the `BaseController`, nothing is getting injected for it has no ctor. `IMediator` needs to get initialized when it is null, so what is done there is Service Locator pattern instead of injecting. You would still need `services.AddScope();` for it to work tho. – JohanP Nov 25 '19 at 23:27
  • just wanted to know if we are are not using constructor injection how can we unit test the controller inheriting the base controller , if @ca9163dn has any idea do let me know – Rahul Sharma Aug 20 '20 at 21:58

1 Answers1

19

The difference is that you don't need to inject IMediator to the constructor of BaseController and to all sub classes of BaseController.

So it's saves some boilerplate, but also makes the dependency less explicit.

Side note, Microsoft recommends to prefer the injection over RequestServices

The services available within an ASP.NET Core request from HttpContext are exposed through the HttpContext.RequestServices collection.

Request Services represent the services configured and requested as part of the app. When the objects specify dependencies, these are satisfied by the types found in RequestServices, not ApplicationServices.

Generally, the app shouldn't use these properties directly. Instead, request the types that classes require via class constructors and allow the framework inject the dependencies. This yields classes that are easier to test.

Note

Prefer requesting dependencies as constructor parameters to accessing the RequestServices collection.

See Microsoft docs

Julian
  • 33,915
  • 22
  • 119
  • 174