Поставщик InRequestScope (для пользовательского ViewEngine) вызывается только один раз при запуске приложения

#asp.net-mvc-3 #ninject #viewengine

#asp.net-mvc-3 #ninject #viewengine

Вопрос:

Я хочу внедрить пользовательский ViewEngine на мой веб-сайт MVC. Это то, что я делаю:

 private static IKernel CreateKernel()
{
   kernel.Bind<IViewEngine>().ToProvider(new RazorViewEngineProvider()).InRequestScope();
}
 

Это мой провайдер:

 public class RazorViewEngineProvider : Provider<RazorViewEngine>
{
    protected override RazorViewEngine CreateInstance(IContext context)
    {
        return new RazorViewEngine();
    }
}
 

Проблема в том, что мой провайдер вызывается только один раз, когда я захожу на веб-сайт в первый раз. В следующий раз мой провайдер каким-то образом все еще находится в кэше. И это не то, чего я хочу.

Я хочу, чтобы поставщик выполнялся при каждом запросе. Я думал, что смогу это сделать.InRequestScope(), но это не имеет никакого значения. Кто-нибудь знает, что происходит?

Ответ №1:

В этом случае механизм просмотра не кэшируется Ninject. Сам MVC не запрашивает его каждый раз из IDependencyResolver. Но я думаю, что это правильное поведение. Таким образом, он сводит к минимуму накладные расходы на создание механизма просмотра путем его повторного использования.

У вас не должно быть зависимой от запроса зависимости в вашем механизме просмотра. Этот вид зависимости должен быть извлечен из модели представления и должен быть назначен контроллером.

И вы должны удалить InRequestScope. В противном случае он будет удален Ninject после первого запроса, но MVC все равно попытается его повторно использовать.

Комментарии:

1. Я пытаюсь кое-что сделать для многопользовательского веб-сайта. Я хочу иметь разные темы. Таким образом, у каждого тенанта есть свой собственный css и masterpage. Я подумал, что было бы неплохо обнаруживать теннант при каждом запросе и создавать viewengine с его помощью.

Ответ №2:

Вместо того, чтобы вводить пользовательский механизм просмотра, не могли бы вы попробовать использовать Application_Start() вместо этого:

 protected void Application_Start()
{
   ViewEngines.Engines.Clear();
   ViewEngines.Engines.Add(new RazorViewEngineProvider());
   RegisterRoutes(RouteTable.Routes);
}
 

Что происходит, когда вы выполняете регистрацию таким образом? Работает ли это?

Комментарии:

1. Да, такая регистрация работает. Но это не совсем то, что я хочу. Я хочу обновлять ViewEngine при каждом запросе. Я рассмотрел методы global_asax, из которых BeginRequest выглядит наиболее актуальным. Но я хотел бы использовать зависимость от Ninject, и я не могу получить доступ к ядру Ninject из global_asax.

2. Я повторил вашу проблему, действительно, CreateInstance метод вызывается только один раз и для меня. Боюсь, я не уверен в этом.