Brad M
Brad M

Reputation: 7898

Ninject Owin Request Scope Silently Fails

The problem - Ninject kernel is always returning new instances even if they are scoped to the request.

-I'm using OWIN with the SystemWeb host package to allow me to use IIS.

-The project depends on an API app that has all the necessary Ninject/owin libraries installed.

app.UseNinjectMiddleware(CreateKernel).UseNinjectWebApi(config);

-Everything worked as intended prior to converting to OWIN.

-Only a single Kernel instance is created.

-Some global filters are registered which set certain properties on a request scoped object.

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var accountService = Startup.Kernel.Get<IAccountService>();
            // some changes to accountService etc.

-When other filters down the pipeline then attempt to get an instance of IAccountService, they always return a new instance.

Based on my own research efforts, it appears this a known issue. Any ideas would be appreciated. Thanks.

Upvotes: 4

Views: 1304

Answers (2)

DennisVM-D2i
DennisVM-D2i

Reputation: 490

Just to add to the answer; you might find that in addition (for 'IDisosable' objects) the 'Dispose()' not getting called, the binding's deactivation handler (- if present -) also does not get invoked (but the activation handler still will), e.g.:

            Bind<IThingSvc>().To<ThingSvc>()
                .InRequestScope()
                .OnActivation((ctx, x) => Debug.WriteLine($"Ninject:Activation - '{x.GetType()}' (- '{ctx.GetScope()?.GetType()}')"))
                .OnDeactivation((ctx, x) => Debug.WriteLine($"Ninject:Deactivation - '{x.GetType()}' (- '{ctx.GetScope()?.GetType()}')"));

It looks like 'Ninject.Extensions.ContextPreservation' is referenced by the 'NamedScope' extension - 'NamedScopeExtensionMethods.cs: IsCurrentResolveRoot()'.

You might find all the OWIN-Host overrides are not working/loaded - e.g. the "OwinWebApiModule" module is not loaded (if you query the Kernel), maybe even an error message like the following (- referring to the OWIN named-scope - 'Ninject_WebApiScope'/"internal const string WebApiScopeName = "Ninject_WebApiScope";"):

[16:29:10] Exception: E0434F4D.Ninject.Extensions.NamedScope.UnknownScopeException ("Error activating ApplicationUserManager The scope Ninject_WebApiScope is not known in the current context. No matching scopes are available, and the type is declared InNamedScope(Ninject_WebApiScope).

Upvotes: 1

jlvaquero
jlvaquero

Reputation: 8785

I've seen a similar problem and maybe this is your case.

InRequestScope does not work if:

Web API with OWIN in a separate assembly. That assembly has Ninject and Web API and OWIN installed it in.

Empty ASP.Net web project which just references the previous assembly. The ASP.Net Web project does not have Web API or Ninject installed, it just has the package to allow OWIN to be hosted on top of ASP.Net.

In that setup, Ninject appears to work just fine; except that InRequestScope is ignored and always resolve different instances of the object.

The problem is that VS does not copy all the required assemblies to the result directory because they are not referenced directly by the application and not used by your OWIN assembly but just dynamically loaded by Ninject.

To resolve the issue just NuGet Ninject.Extensions.ContextPreservation in your ASP.Net web project.

Maybe this is just your problem or it is similar. Take a look at Ninject Extensions and try to identify wich extensions you need thas was not added to the result directory.

Upvotes: 3

Related Questions