MVC 2 Beta DefaultControllerFactory с областями

Почему фабрика по умолчанию НЕ возвращает полное имя контроллеров (с пространствами имен)? Я использую Service Locator и автофак.

using System.Web.Mvc;

using Microsoft.Practices.ServiceLocation;

namespace Application.Core.MVC
{

        public override IController CreateController(System.Web.Routing.RequestContext requestContext, string **controllerName**)
        {
            return ServiceLocator.Current.GetInstance<IController>(controllerName);
        }
}

У меня было два домашних контроллера (один под областью Блог)

HTTP: // локальный / Home

HTTP: // локальный / Блог / Главная

controllerName возвращает только "Home" без полного имени для обоих в приведенном выше коде. Это создает проблему, когда я пытаюсь зарегистрировать имена контроллеров для внедрения зависимостей. Вот как я сейчас регистрирую контроллеры в соответствии с этой ситуацией. Даже это поднимает страницы без исключения. Но когда я получаю доступ к http://localhost/Home, оба контроллера запускаются независимо.

   foreach (var tp in currentAssemblyControllersTypes)
                    builder.Register(tp).FactoryScoped().Named(tp.Name.Replace("Controller", ""));

Кто-нибудь может помочь? Спасибо.

2 ответа

Решение

Метод DefaultControllerFactory.CreateController() отвечает за возврат контроллера для данного запроса. Параметр controllerName является просто частью {controller} маршрута. Задача CreateController (), а не вызывающего, - определить правильный тип с учетом имени контроллера, указанного в URL.

Чтобы сделать это проще, DefaultControllerFactory.CreateController() делегирует два других метода: GetControllerType() и GetControllerInstance(). Если вы хотите использовать исходную логику разрешения контроллера (например, поиск типов), но просто изменить способ создания экземпляров типов, оставьте методы CreateController () и GetControllerType () как есть и просто переопределите GetControllerInstance(). Это уже заботится о логике поиска пространства имен, которую вы дублируете, и сделает ваш код намного проще.

[Обновление в соответствии с ответом Леви]

1. Зарегистрируйте каждый контроллер на полное имя в явном виде:

 foreach (var tp in currentAssemblyControllersTypes)
                builder.Register(tp).FactoryScoped().Named(tp.FullName)

//Application.Controllers.HomeController
//Application.Areas.Blog.Controllers.HomeController

2. Укажите пространство имен в MapRoute() для Application.Controllers.HomeController в Global.ascx.cs в соответствии с демонстрацией PDC09.

    routes.MapRoute(
                    "Default",                                              // Route name
                    "{controller}/{action}/{id}",                           // URL with parameters
                    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults

                    ,new string [] { "Application.Controllers"}  //Specify namespace

      );

        }

3. Переопределить метод GetControllerInstance(). IoCControllerFactory.cs

Protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType)
 {
  return (controllerType == null)? base.GetControllerInstance(requestContext,controllerType):ServiceLocator.Current.GetInstance<IController>(controllerType.FullName);
 }
Другие вопросы по тегам