seesharper / LightInject

An ultra lightweight IoC container
http://www.lightinject.net
MIT License
624 stars 120 forks source link

Retrieving dependencies in Application_Start when using LightInject.Mvc #174

Open ghost opened 9 years ago

ghost commented 9 years ago

I'm using LightInject.MVC in an MVC 4 Application. The first block of my Application_Start method creates and intializes my ServiceContainer with a set of service registrations. It also sets the scope manager to PerRequestScope.

    var container = new ServiceContainer();
    container.EnablePerWebRequestScope();
    container.EnableAnnotatedConstructorInjection();

    container
        .ScanAndLoadAllCompositionRoots()  //Registrations are performed here
                         container.RegisterControllers(Assembly.GetCallingAssembly(),Assembly.GetExecutingAssembly());
            container.EnableMvc();

When I try to resolve one of my services later on in the Application_Start method as so: var authorizationPermissionManager = container.GetInstance<IAuthorizationPermissionManager>();

I get the following exception:

"Unable to locate a scope manager for the current HttpRequest. Ensure that the LightInjectHttpModule has been added."

I understand that the scope manager isn't associated with the HttpRequest until after Application_Start is executed, so I'm confused on how I'm supposed to retrieve my dependency.

seesharper commented 9 years ago

If the service require a scope, you could start the scope manually.

container.BeginScope()

You might need to do this before enabling the perwebrequestscope. Put the statement in a using block to ensure that the scope is disposed.

On Friday, March 27, 2015, Adam Greene notifications@github.com wrote:

I'm using LightInject.MVC in an MVC 4 Application. The first block of my Application_Start method creates and intializes my ServiceContainer with a set of service registrations. It also sets the scope manager to PerRequestScope.

var container = new ServiceContainer();
container.EnablePerWebRequestScope();
container.EnableAnnotatedConstructorInjection();

container
    .ScanAndLoadAllCompositionRoots()  //Registrations are performed here
                     container.RegisterControllers(Assembly.GetCallingAssembly(),Assembly.GetExecutingAssembly());
        container.EnableMvc();

When I try to resolve one of my services later on in the Application_Start method as so:

var authorizationPermissionManager = container.GetInstance();

I get the following exception:

"Unable to locate a scope manager for the current HttpRequest. Ensure that the LightInjectHttpModule has been added."

I understand that the scope manager isn't associated with the HttpRequest until after Application_Start is executed, so I'm confused on how I'm supposed to retrieve my dependency.

— Reply to this email directly or view it on GitHub https://github.com/seesharper/LightInject/issues/174.

ghost commented 9 years ago

I get the same error message even when I wrap the call to resolve the service in the using block as follows:

using (container.BeginScope())
{
    var authorizationPermissionManager =    container.GetInstance<IAuthorizationPermissionManager>();
}

Is it possible that the Scope hasn't been added to the request because the LightInjectHttpModule hasn't been executed yet for this request?

seesharper commented 9 years ago

That is very plausible. That is why you might want to do this before enabling the perwebrequestscope.

kgoyal1 commented 7 years ago

Hi I am still not able to figure it out. PLease help out.

1down votefavorite I have integrated Light Inject in web api project. I am able to register service successfully in application_start in global.asax. I am using filter which needs to be registered as well in application_start in global.asax. Filter constructor have reference to the services registered however I am not able to get the service instance. Samplee code: service registration is as below:container.Register<ILogger, EPPSLogger>(GetLifetime()); filter registration needs instance of ILogger. Using below code:config.Filters.Add(new EPPSAuthenticationFilter( config.DependencyResolver.GetService(), config.DependencyResolver.GetService())); gets the error when try to getService that lightinject module is not injected/registered. I cant upgrade to .net framework 4.5 or so.Any help is highly appreciated. Thanks
seesharper commented 7 years ago

I’ll help you out. Put up a simple repro here on github and we will PR a solution into that repo

kgoyal1 commented 7 years ago

Thanks. I am able to resolve atleast above issue by using the code below: using (container.BeginScope()) { var authorizationPermissionManager = container.GetInstance(); }

However I am running into another issues for getting current httpmessage. I am using the code below: public class HttpRequestMessageHandler : DelegatingHandler { protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { CurrentMessage = request; return base.SendAsync(request, cancellationToken);
}

    public static HttpRequestMessage CurrentMessage
    {
        get { return (HttpRequestMessage)CallContext.LogicalGetData("RequestMessage"); }
        private set { CallContext.LogicalSetData("RequestMessage", value); }
    }
}    

and retrieves the current http message as below: public HttpRequestMessage CurrentMessage { get { return HttpRequestMessageHandler.CurrentMessage; } } I am not getting current http message. Am I missing anything here? Thanks in advance.

kgoyal1 commented 7 years ago

Another thing is for percontainerlifetime, if I initialize any class level variable in the constructor, I am not able to retrieve the value of those variable when actual method call is made. what is the recommended way of handling this? Thanks again

seesharper commented 7 years ago

If you put thus into a simple repro, we can have a look at it. Also see #386 for more information around logical call context.

kgoyal1 commented 7 years ago

HI THe Repo is kgoyal1/lightinject1.

  1. webapiconfig is used for service registration. the below line in this file is not returning instance: serviceContainer.Register<IProvider, CorrelationProvider>(new PerContainerLifetime());
  2. httprequestmessagehandler is used for getting current http request message. The issue here is current request message doesnt have .net principal etc. 3.eppsauthenticationfilter is used for token authentication. The issue here is class variable initialized in the constructor dont persisit the value when actual request invokes the filter.

Thanks for help

kgoyal1 commented 7 years ago

Added another one which returns properties but I am not getting anything.

kgoyal1 commented 7 years ago

HI I have added another code for filter UserIdReplacementFilter which returns me recipientid as null.

seesharper commented 7 years ago

Hi again. Took a look at your repo and it looks like it only contains parts of the original application.

"If you put thus into a simple repro, we can have a look at it."

What I meant by this is a minimal and runnable application that contains no more than the code needed to demonstrate the problem. A small reproduction that we can fork and hit F5 to see the problem.

This might seem like nitpicking to some people, but otherwise it would take to much time to try to figure out the context and the surrounding parts of you applications.