-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Owin + WebApi - Ninject 'Provider' does not work honor request scope #17
Comments
Is there any news on this issue? It's not only related to providers. Request scope doesn't work at all when you're using Owin. 1.) Create a Ninject web application as per: https://github.com/ninject/Ninject.Web.Common/wiki/Setting-up-a-OWIN-WebApi-application 2.) Create some custom type that you can bind, e.g. public class TestService : ITestService { }
public interface ITestService { } 3.) Add request scope binding, e.g. private static StandardKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<ITestService>().To<TestService>().InRequestScope();
return kernel;
} 4.) Test. For example: app.Use((context, next) =>
{
Debug.WriteLine(
webApiConfiguration.DependencyResolver.GetService(typeof(ITestService)) ==
webApiConfiguration.DependencyResolver.GetService(typeof(ITestService)));
return next();
}); Output is "False", should be "True". That's a show-stopper for us at the moment. |
It seems that this project is dead. |
We have subsequently changed to using Autofac and haven't looked back. |
Maybe you should have left the issue open so others exploring Ninject and its options can find it more easily. I've always liked Ninject and did some investigation into what needs to be done to fix this, but in the end we also moved on to a different framework. Can't say I miss the NuGet package mess, introduction of breaking changes in bug fix releases and similar things. |
Good point :) On Thu, Nov 26, 2015 at 5:38 AM, Peter notifications@github.com wrote:
|
You need to use IResolutionRoot if you want create objects in the scope. Don't use the kernel directly in this case. Also make sure that you have installed the context preservation module. |
As you can see in my example, I wasn't using the kernel but the built-in dependency resolver which is also used by the runtime itself for i.e. constructor injection. The actual use of the kernel in this case is not under the control of the code in question but hidden behind at least the provided adapter and potentially more layers of code. The context preservation module in this sample is installed automatically as one of the NuGet dependencies, but unfortunately it's still not working. Side note: With all due respect, I think that these exactly are the problems with Ninject nowadays. Even the simple sample above requires 7(!) Ninject NuGet packages to be installed, and after closely following provided instructions or samples you are still confronted with how to specifically handle details that in my opinion should be internal to the framework itself. A developer's intention is quite clear: have DI for typical web application scenarios. Ninject however seems to get more and more lost in layer after layer of generic and abstracted logic, carefully balanced (read: fragile) interaction of multiple independent modules, and some implicit behind-the-scenes magic. If you hit a road block with all that, good luck, because now you're forced to understand all of that magic the framework is supposed to hide from you, to figure out what you might have missed or used in a way that was not intended. Just read, for example, through the wiki documentation of the context preservation module you were referring to. There is simply no way anyone without deeper knowledge of the inner workings of the framework could make any sense of this highly abstracted information in the context of a problem like "request scoping isn't working as expected". Don't get me wrong, I highly appreciate the work people put into these projects, and I have benefited from Ninject quite a lot in the past. I am thankful for that. It just feels like that at some point the project took a turn for the worse. The fact that an issue like this one, of fundamental nature and reproducible by just a few simple steps, is not only unaddressed but also passed without comment for months, does not really help with that impression. |
I'm gonna have to agree with @MisterGoodcat. If before Owin the scope was set to the Http context, people were naturally expecting that the Owin context took its place, which is not the case. That's what InRequestScope should mean, right? Doesn't matter whether I'm inside the Owin middleware pipeline, in a filter or inside a controller. An InRequestScope resolved service should remain the same! I did take a look at the implementation of this extension, and it's pure and simple wrong. I explained a bit more in #22. The fix is not trivial. |
The workaround is to remove this module altogether from the project and set up Ninject's classic HTTP scope handler instead. Obviously this would only work on web server hosted apps. Alternatively, if this is an option at this stage, use a different DI framework. |
This is what I'm testing out and it seems to work. Instead of calling .InRequestScope() I'm now calling InCustomRequestScope. This seems entirely too easy. Anyone see a problem here? And if you don't have HttpContext.Current.Request you could just throw an if block into GetRequestScope and return the correct "scope managing object." public static IBindingNamedWithOrOnSyntax InCustomRequestScope(this IBindingInSyntax syntax) |
I just hit this issue. I was using context.Kernel.Get in a ToMethod binding and was very surprised to find that the services I produce this way are not in request scope but transient. Ended up using this code (thanks to @ItWorksOnMyMachine ) to create my own scope. I hope I did not break something
|
2017 and the issue is still there. Switched to autofac |
|
I found (as a replacement for the above / in my case) that this variant seems to be working for me - as 'HttpContext.Current.Handler' always seemed to be set to 'null' (- so using 'HttpContext.Current' or 'HttpContext.Current.Request' instead);: public static class CustomRequestScope
{
public static Ninject.Syntax.IBindingNamedWithOrOnSyntax<T> InCustomRequestScope<T>(this Ninject.Syntax.IBindingInSyntax<T> syntax)
{
return syntax.InScope(ctx => HttpContext.Current != null ? HttpContext.Current.Request : null);
}
} But I do wonder if the use of 'HttpContext.Current.Request' should actually be replaced by 'HttpContext.Current' instead, inline with it's use in the 'OnePerRequestHttpModule' & 'DefaultWebApiRequestScopeProvider' classes (/files): ...\Ninject\Ninject.Web.Common-3.3.0\src\Ninject.Web.Common.WebHost\OnePerRequestHttpModule.cs ...\Ninject\Ninject.Web.WebApi-3.3.0\src\Ninject.Web.WebApi\DefaultWebApiRequestScopeProvider.cs |
Based upon my comment (/discovery) above, I wonder if you should be using 'HttpContext.Current' instead of 'HttpContext.Current.Request' (?). |
I'm considering using |
Just be careful that you're not inadvertently hiding/running way from the problem that I seemed to encounter, whereby the switch between OWIN & ASP.NET (contexts) seemed to cause 2 different request scopes to be used - one per context, in other words the request scope was not been shared. |
Thanks for the suggestion. I've closed the IActivationBlock PR and created #29. It will always use HttpContext.Current if it's available. https://github.com/ninject/Ninject.Web.WebApi/tree/Re-implement-IDependencyScope |
Try Ninject.Web.WebApi 3.3.1 please. |
Unfortunately, it doesn't help. |
@ISkomorokh What’s the symptom? Would you mind sharing your package list and some code snippets? |
@scott-xu sure.
<package id="Ninject" version="3.3.4" targetFramework="net46" />
<package id="Ninject.Web.Common" version="3.3.2" targetFramework="net46" />
<package id="Ninject.Web.Common.WebHost" version="3.3.2" targetFramework="net46" />
<package id="Ninject.Web.WebApi" version="3.3.1" targetFramework="net46" />
<package id="Ninject.Web.WebApi.WebHost" version="3.3.1" targetFramework="net46" /> I've a internal sealed class StateContextProviderFactory : IStateContextProviderFactory {
public static IStateContextProviderFactory Instance => (IStateContextProviderFactory)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(StateContextProviderFactory));
} I know, that it is a Service Locator anti-pattern, but still, I need it in order to simplify the instantiation in the legacy part of the app until it gets refactored. This blog post has a very useful passage:
Unfortunately, my code flow doesn't deal with HttpRequestMessage. Hope this helps. |
@ISkomorokh Try |
Fixed in Ninject.Web.WebApi 3.3.1 |
When using a Ninject
Provider<T>
(factory) to create a dependency, the dependencies resolved from theIContext
passed to the Provider will not honor any 'Per Request' scoping.When in Owin/WebApi world, ninject creates a named scope per request which is automatically bound to a context but it seems that the context passed to the
CreateInstance
method is somehow not aware of any global named scope.To reproduce, create a provider which relies on some per request object:
Registration:
Now you would need a WebApi controller hosted in Owin to rely on an IFoo.
The text was updated successfully, but these errors were encountered: