Plaga
Plaga

Reputation: 83

Accessing dependency injected services in MVC 6

I'm using mvc6 with vs2015 rc. After reading Using IConfiguration globally in mvc6, my code now looks like this:

startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    ...
    IConfiguration configuration = new Configuration().AddJsonFile("config.json");
    services.Configure<Settings>(configuration);
}

my controller:

private Settings options;
public MyController(IOptions<Settings> config)
{
    options = config.Options;
}

this works great for controllers.

But how can I access my Settings object from somewhere else in the code, like for example from inside my Formatters (implementing IInputFormatter and thus, with fixed signatures) or any other random class?

Upvotes: 3

Views: 1955

Answers (1)

Kiran
Kiran

Reputation: 57949

In general where ever you have access to HttpContext, you can use the property called RequestServices to get access to the services in DI. For example, to get access to the ILogger service from within ObjectResult.

public override async Task ExecuteResultAsync(ActionContext context)
{
    var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ObjectResult>>();

The above usage is a bit different than what you mentioned in the controller example above because controllers in MVC are type activated...that is the responsibility of constructing the controller is managed through DI which will look at the parameters of the constructor and populate them from registered services in DI...this is also called constructor injection...

To see how DI type activation works in general (DI is independent of MVC and can used even in a console app), take a look at the following snippet of code (taken from http://docs.asp.net/en/latest/security/data-protection/using-data-protection.html)

using System;
using Microsoft.AspNet.DataProtection;
using Microsoft.Framework.DependencyInjection;

public class Program
{
    public static void Main(string[] args)
    {
        // add data protection services
        var serviceCollection = new ServiceCollection();
        serviceCollection.AddDataProtection();
        var services = serviceCollection.BuildServiceProvider();

        // create an instance of MyClass using the service provider
        var instance = ActivatorUtilities.CreateInstance<MyClass>(services);
        instance.RunSample();
    }

    public class MyClass
    {
        IDataProtector _protector;

        // the 'provider' parameter is provided by DI
        public MyClass(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("Contoso.MyClass.v1");
        }

        public void RunSample()
        {
            Console.Write("Enter input: ");
            string input = Console.ReadLine();

            // protect the payload
            string protectedPayload = _protector.Protect(input);
            Console.WriteLine($"Protect returned: {protectedPayload}");

            // unprotect the payload
            string unprotectedPayload = _protector.Unprotect(protectedPayload);
            Console.WriteLine($"Unprotect returned: {unprotectedPayload}");
        }
    }
}

In the above example, the type MyClass was type activated.

And regarding your specific example about InputFormatter, they are not type activated and hence you cannot use constructor injection with it, but you would have access to the HttpContext and so you can do as mentioned earlier in this post.

Also take a look at this article: http://blogs.msdn.com/b/webdev/archive/2014/06/17/dependency-injection-in-asp-net-vnext.aspx

Upvotes: 3

Related Questions