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: // локальный / Блог / Главная
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);
}