Подтвердить что ты не робот

Контроллер в отдельной сборке и маршрутизации

В том же решении есть приложение 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, запустите приложение и пункт brower на /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".

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

4b9b3361

Ответ 1

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

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;

Ответ 2

Вы можете наследовать от 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, не будет виден. Вы можете даже скрыть всю сборку.

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