Wir versuchen, Ninject innerhalb einer OWIN mit WebAPI-Pipeline zu verwenden. Wir haben alles nach this documentation eingerichtet, aber wir können InRequestScope() nicht zum Laufen bringen.Verwenden von Ninject mit Owin und InRequestScope
Hier ist der wesentliche Teil der startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
// Web API routes
config.MapHttpAttributeRoutes();
// Ninject Setup
app.UseNinjectMiddleware(NinjectConfig.CreateKernel);
app.UseNinjectWebApi(config);
}
}
NinjectConfig sieht ungefähr so aus:
public sealed class NinjectConfig
{
public static IKernel CreateKernel()
{
var kernel = new StandardKernel();
INinjectModule[] modules =
{
new ApplicationModule()
};
instance.Load(modules);
// Do we still need to do this wtih Owin?
instance.Bind<IHttpModule>().To<OnePerRequestHttpModule>();
}
}
Unser ApplicationModule wohnt in einem separaten Infrastrukturprojekt mit Zugang zu allen von unseren verschiedenen Schichten, zur Handhabung von DI & Kartierung:
public class ApplicationModule: NinjectModule
{
public override void Load()
{
// IUnitOfWork/EF Setups
Bind<ApplicationContext>().ToSelf().InRequestScope();
Bind<IUnitOfWork>().ToMethod(ctx => ctx.Kernel.Get<ApplicationContext>()});
Bind<ApplicationContext>().ToMethod(ctx => ctx.Kernel.Get<ChromLimsContext>()}).WhenInjectedInto<IDal>();
// other bindings for dals and business objects, etc.
}
}
Dann haben wir ein paar Schnittstellen:
public interface IUnitOfWork()
{
void SaveChanges();
Task SaveChangesAsync();
}
und
public interface IDal()
{
// Crud operations, Sync and Async
}
dann unsere tatsächlichen Klassen diese:
public class SomeBusinessObject
{
private IUnitOfWork _uow;
private IDal _someDal;
public SomeBusinessObject(IUnitOfWork uow, IDal someDal)
{
_uow = uow;
_someDal = someDal;
}
public Task<SomeResult> SaveSomething(Something something)
{
_someDal.Save(something);
_uow.SaveChanges();
}
}
Einiges Dal
public class SomeDal : IDal {
private ApplicationContext _applicationContext;
public SomeDal(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
public void Save(Something something)
{
_applicationContext.Somethings.Add(something);
}
}
Unsere EF DbContext
public class ApplicationContext : DbContext, IUnitOfWork
{
// EF DBSet Definitions
public void SaveChanges()
{
base.SaveChanges();
}
}
Die Erwartung ist, dass für jede Anforderung eine einzelne Instanz Application erstellt und in die Business-Objekte als IUnitOfWork Implementierung und in die IDals als Application injiziert wird.
Stattdessen wird eine neue Instanz von ApplicationContext für jede einzelne Klasse erstellt, die sie verwendet. Wenn ich den Bereich von InRequestScope auf InSingletonScope umschalte, wird (wie erwartet) genau eine Instanz für die gesamte Anwendung erstellt und ordnungsgemäß in die angegebenen Klassen eingefügt. Da dies funktioniert, gehe ich davon aus, dass dies kein bindendes Problem ist, sondern ein Problem mit der InRequestScope-Erweiterung.
Das einzige Problem, das ich ähnlich finden könnte, was ich erfahre, ist this one, aber leider hat die Lösung nicht funktioniert. Ich verweise bereits auf alle Pakete, die er in den Projekten WebApi und Infrastructure angegeben hat, und ich überprüfe, ob sie in das Erstellungsverzeichnis kopiert werden.
Was mache ich falsch?
Bearbeiten: Einige zusätzliche Informationen. Betrachtet man den Ninject-Quellcode sowohl in Ninject.Web.WebApi.OwinHost als auch in Ninject.Web.Common.OwinHost, so scheint es, als ob Owin Middleware den OwinWebApiRequestScopeProvider als IWebApiRequestScopeProvider hinzufügt. Dieser Provider wird dann in der Erweiterungsmethode InRequestScope() verwendet, um einen benannten Bereich namens "Ninject_WebApiScope" zurückzugeben. Dies wird bis zur Zielklasse vorhanden sein, die in Switches injiziert wird. Der benannte Bereich verschwindet dann und ein neuer Bereich wird erstellt. Ich denke, das ist möglicherweise, worauf sich @BatteryBackupUnit in ihrem Kommentar bezieht, aber ich weiß nicht, wie ich es korrigieren soll.
Meine Vermutung wäre, dass Ihre zweite 'Bind()' dies verursacht. Sie setzen es nicht auf "InRequestScope()" –
LukeP
Leider hat das nicht funktioniert. Ich habe auch versucht, nur den ApplicationContext an InRequestScope zu binden und dann nur IUnitOfWork ToMethod (ctx => ctx.Kernel.Get()) zu binden. InRequestScope() –
aasukisuki
Funktioniert '.InRequestScope()' für * any * verbindlich? Es gibt ein "bekanntes" Problem im Zusammenhang mit der ninjet-nugget-Paketinstallation/-aktualisierung, bei der es nicht korrekt eingerichtet ist und das Request-Scope-spezifische ninject-Zeug nicht korrekt registriert ist. '.InRequestScope()' hat keine Wirkung - leider keine Ausnahme. – BatteryBackupUnit