У меня есть веб-приложение ASP. NET (. NET Framework 4.8), в котором я настроил NInject, но все службы, которые я установил с помощью InRequestScope
, проходят, как если бы переходная область (т.е. новые экземпляры создаются для каждой сущности, которая зависит от нее - в рамках одного и того же веб-запроса).
Я использую следующие пакеты NuGet (последние):
- Ninject v3.3.4
- Ninject.Web.Common v.3.32 («Загрузчик для веб-проектов»)
App_Start\Ninject.Web.Common.cs
присутствует и является правильным и выглядит следующим образом:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(ScormWebService.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(ScormWebService.App_Start.NinjectWebCommon), "Stop")]
namespace ScormWebService.App_Start
{
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
using Services;
using System;
using System.Web;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static IKernel Kernel { get; private set; }
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
kernel.Bind<IDumpConfigService>().To<DumpConfigService>().InSingletonScope();
// These objects are created fresh for each request
kernel.Bind<ILogService>().To<LogService>().InRequestScope();
kernel.Bind<IDumpService>().To<DumpService>().InRequestScope();
kernel.Bind<ISaveDataRequestReader>().To<SaveDataRequestReaderXml>().InRequestScope();
kernel.Bind<ISaveDataResponseWriter>().To<SaveDataResponseWriterXml>().InRequestScope();
kernel.Bind<IHttpContextAccessor>().To<HttpContextAccessor>().InRequestScope();
Kernel = kernel;
}
}
}
Входящий запрос на самом деле является реализацией IHttpHandler
(т.е. файл ashx, а не aspx). Однако это по-прежнему запрос страницы с текущим запросом и HttpContext.Current.
Вот как я настраиваю объекты для запроса страницы
public class SaveDataHandler : IHttpHandler, IRequiresSessionState
{
/// <summary>
/// A new handler is required for each and every incoming request
/// </summary>
public bool IsReusable => false;
public SaveDataHandler()
{
var kernel = App_Start.NinjectWebCommon.Kernel;
LogService = (ILogService)kernel.GetService(typeof(ILogService));
Reader = (ISaveDataRequestReader)kernel.GetService(typeof(ISaveDataRequestReader));
Writer = (ISaveDataResponseWriter)kernel.GetService(typeof(ISaveDataResponseWriter));
DumpService = (IDumpService)kernel.GetService(typeof(IDumpService));
}
}
Так, например, в конструкторе SaveDataHandler
для каждого запроса создаются три экземпляра ILogService
вместо одного: SaveDataHandler
сам запрашивает его (см. выше), как и class DumpService : IDumpService
и class SaveDataRequestReaderXml : ISaveDataRequestReader
.
Может ли кто-нибудь дать представление Что касается того, почему InRequestScope
действует как переходный осциллограф? Я подозреваю, что причина в использовании страницы IHttpHandler
(ashx) вместо страницы веб-формы (aspx), но я не понимаю, почему это не сработает, поскольку HttpContext.Current
одинаков во всем запросе, и это то, что NInject.Web.Common
используется в качестве идентификатора области запроса. Я создал страницу WebForm.aspx, но такая же проблема возникает и для нее, поэтому она не указывает c на ashx / IHttpHandler
запросы:
namespace ScormWebService
{
public partial class WebForm1 : Page
{
protected void Page_Init(object sender, EventArgs e)
{
var kernel = App_Start.NinjectWebCommon.Kernel;
var LogService = (ILogService)kernel.GetService(typeof(ILogService));
var Reader = (ISaveDataRequestReader)kernel.GetService(typeof(ISaveDataRequestReader));
var Writer = (ISaveDataResponseWriter)kernel.GetService(typeof(ISaveDataResponseWriter));
var DumpService = (IDumpService)kernel.GetService(typeof(IDumpService));
// At this point, three instances of LogService have been created.
}
}
}
Изменить: я создал fre sh минимальный ASP. NET проект веб-форм, который воспроизводит проблему, которую вы можете скачать здесь , но все основные элементы уже описаны в код выше.
Спасибо.