Контроллер StructureMap factory и экземпляр нулевого контроллера в MVC

Я все еще пытаюсь разобраться с StructureMap, и одна из проблем, с которыми я столкнулся, - это класс, который запускается класс Controller Factory, когда ему присваивается тип нулевого контроллера. Это происходит только тогда, когда приложение создается впервые, после чего каждая последующая сборка работает нормально. Даже когда я завершаю Visual Studio и снова открываю проект (я не запускаю его в IIS). Это почти похоже на то, что происходит какое-то кеширование. Это класс контроллера выглядит следующим образом:

public class IocControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            return (Controller)ObjectFactory.GetInstance(controllerType);
        }
        catch (StructureMapException)
        {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}

Что может быть неправильным? Нужно ли регистрировать каждый контроллер? Спасибо.

Ответ 1

Я столкнулся с той же проблемой с контроллером factory, созданным вокруг ninject.

Кажется, MVC передаст вам null для типа контроллера, когда он не сможет разрешить маршрут из таблицы маршрутизации или когда маршрут указывает ни одного существующего контроллера. Я сделал две вещи, чтобы решить эту проблему. Вы можете проверить свою таблицу маршрутов и добавить общий маршрут, который показывает страницу ошибки 404, как описано здесь .NET MVC Routing Catchall не работает

Вы также можете проверить с помощью отладчика маршрутизации, что пойдет не так. http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

Ответ 2

Большинство браузеров ищут favicon.ico, когда вы загружаете сайт, и, вероятно, какое-то кэширование связано с этим поведением, это может объяснить нечетную вещь "Только сбой первой сборки", которую вы упомянули.

В моем случае это вызывало проблему типа нулевого контроллера в контроллере factory.

Добавление routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); в global.asax заставляет проблему уйти, запрос должен провалиться в файловую систему без MVC, ища в вашем коде контроллер favico.ico.

Вот ссылка на Сообщение Gunnar Peipman об этом

Я узнал, переопределив GetControllerType (string controllerName) в моем классе пользовательского контроллера factory и проверив, какое значение имя контроллера было для каждого запроса.

Ответ 3

У меня была аналогичная проблема. Я считаю, что это HTTP-запросы на несуществующие изображения, файлы CSS и т.д.

Мы знаем, что маршрутизация MVC сначала ищет, чтобы физически существовал запрошенный файл. Если это не так, URL-адрес тестируется против настроенных Маршрутов. Я думаю, что запрос на изображение, которое физически не существовало, было передано движку маршрутизации и не соответствовало никаким маршрутам, поэтому использовался NULL.

Чтобы исправить это, используйте FireBug или что-то, что нужно для просмотра и исправления, разбитых HTTP-запросов. Во время разработки я использовал такой маршрут, чтобы временно обойти эти проблемы (все папки ресурсов начинаются с подчеркивания типа _Images, _Styles и т.д.):

routes.IgnoreRoute("_*");  // TODO: Remove before launch

Надеюсь, это поможет!

Ответ 4

Я думаю, что вам нужно сделать то же самое, что и стандартный MVC-контроллер factory для метода GetControllerInstance. Если вы посмотрите на исходный код Microsoft для DefaultControllerFactory в http://aspnetwebstack.codeplex.com/, вы увидите, что DefaultControllerFactory выдает исключение 404, если тип контроллера равен NULL. Вот как мы делаем это на основе этой информации:

 public class StructureMapControllerFactory : DefaultControllerFactory
 {
      protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
      {
           if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
           var controller = ObjectFactory.GetInstance(controllerType);
           return (IController)controller;
      }
 }

В основном это гарантирует, что когда пользователь вводит неверный маршрут, приложение обрабатывает его как ошибку 404.