2012-06-18 3 views
36

В том же решении есть приложение ASP.NET MVC4 Slick.App и библиотека классов Awesome.Mvc.Lib. Awesome.Mvc.Lib содержит один класс контроллера.Контроллер в отдельной сборке и маршрутизации

public class ShinnyController : Controller 
{ 
    [HttpGet] 
    public string Index() 
    { 
     return "Hello, from Awesome.Mvc.Lib"; 
    } 
} 

Если я просто добавить ссылку из Slick.App в Awesome.Mvc.Lib, запустить приложение и точка Брауэр в /shinny, я на самом деле увидеть ответ «Привет из Awesome.Mvc.Lib».

Это то, чего я не ожидаю вообще. Все время я думал, что ASP.NET MVC уважает пространства имен, в которые помещаются контроллеры. Таким образом, контроллеры из других пространств имен не отображаются, по крайней мере, до того, как я не просил.

Я попытался изменить учетную запись по умолчанию, чтобы использовать параметр namespaces.

routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
     namespaces: new [] { "Slick.App.Controllers" } 
    ); 

Тем не менее, маршрут ShinnyController по-прежнему соответствует «/ shinny».

У меня проблемы, это правильное поведение по умолчанию. Мой вопрос в том, как явным образом сказать, какие контроллеры выставлены, и предотвратить использование маршрута по умолчанию для соответствия контроллерам в отдельной библиотеке классов?

ответ

30

Список имен на маршруте только дает приоритет к определенным пространствам имен над другими, которые не перечислены:

new [] {"Namespace1", "Namespace2"} 

не дает более высокий приоритет Namespace1 как можно было бы ожидать, но только дает приоритет обоим пространствам имен над другими.

Это означает, что пространства имен в списке сначала ищут контроллеры, а затем, если совпадение не найдено, используются остальные доступные контроллеры с этим именем.

Вы можете подавить использование не приоритизированных контроллеров, делая это:

var myRoute = routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
     namespaces: new [] { "Slick.App.Controllers" } 
    ); 

myRoute.DataTokens["UseNamespaceFallback"] = false; 
3

Вы можете наследовать от DefaultControllerFactory так:

public class CustomControllerFactory : DefaultControllerFactory 
{ 
    protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) 
    { 
     var type = base.GetControllerType(requestContext, controllerName); 

     if (type != null && IsIngored(type)) 
     { 
      return null; 
     } 

     return type; 
    } 

    public static bool IsIngored(Type type) 
    { 
     return type.Assembly.GetCustomAttributes(typeof(IgnoreAssemblyAttribute), false).Any() 
      || type.GetCustomAttributes(typeof(IgnoreControllerAttribute), false).Any(); 
    } 
} 

Тогда некоторые изменения global.asax

protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 

     ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory()); 
    } 

И вот вы! Любой тип, отмеченный знаком IgnoreControllerAttribute, не будет виден. Вы можете даже скрыть всю сборку.

Если вам нужно некоторое поведение конфигурации на основе, это не большое дело, чтобы сделать все необходимые изменения;)

+1

Unfortunatelly, это не совсем то, что моя проблема. Моя проблема в том, что у меня нет доступа к хост-приложению, поэтому создание фабрики настраиваемых контроллеров для меня не сработает. –

+0

@alexanderb: Нет, вы можете сделать это, используя это: [сборка: System.Web.PreApplicationStartMethod (typeof (MvcTools.Hooks.PreApplicationStartCode), «Пуск»)], см. Эту ссылку: http: //blog.davidebbo. com/2011/02/register-your-http-modules-at-runtime.html В начале вы делаете это: System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory (YOUR_ControllerFactory)); Все, что вам нужно сделать, это заставить приложение-хост загружать вашу DLL, чего вы можете достичь с помощью записи web.config;) –

Смежные вопросы