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

Ограничить маршрут до пространства имен контроллера в ядре ASP.NET

Я пытаюсь ограничить контроллеры моих основных маршрутов ASP.NET определенным пространством имен.

В предыдущих версиях ASP.NET MVC произошла перегрузка, которая предоставляла параметр string[] namespaces при добавлении маршрутов. Это отсутствует в ASP.NET MVC 6. Итак, после некоторых поисковых запросов я попытался сыграть с чем-то вроде

app.UseMvc(routes => {
    var dataTokens = new RouteValueDictionary {
        {
            "Namespaces", new[] {"ProjectA.SomeNamespace.Controllers"}
        }
    };

    routes.MapRoute(
         name: "default",
         template: "{controller=Home}/{action=Index}/{id?}",
         defaults: null,
         constraints: null,
         dataTokens: dataTokens
    );
});

но он, похоже, не делает того, что я хочу. Есть ли способ ограничить механизм маршрутизации определенным пространством имен?

Обновление

Я просто понял, что, возможно, что-то нужно сделать с тем фактом, что я использую маршрутизацию атрибутов на каждом отдельном контроллере? Распределяет ли маршрутизация атрибутов маршруты, определенные app.UseMvc()?

Обновление 2

Подробнее:

У меня есть два полностью независимых проекта Web API. Кстати, несколько маршрутов одинаковы в обоих (т.е. ~/api/ping). Эти проекты независимы в Production, одна из них - конечная точка для пользователей, одна из которых является конечной точкой для администраторов.

У меня также есть модульные тесты, используя Microsoft.AspNet.TestHost. Некоторые из этих модульных тестов требуют функциональности обоих этих проектов Web API (т.е. Требуется конечная точка "admin" для полной установки тестового примера для "пользователя" ). Но когда я ссылаюсь на оба проекта API, TestHost запутывается из-за одинаковых маршрутов и жалуется на "несколько маршрутов соответствия":

Microsoft.AspNet.Diagnostics.DeveloperExceptionPageMiddleware: Error: An unhandled exception has occurred while executing the request
Microsoft.AspNet.Mvc.Infrastructure.AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
    ProjectA.SomeNamespace.Controllers.PingController.Ping
    ProjectB.SomeNamespace.Controllers.PingController.Ping
at Microsoft.AspNet.Mvc.Infrastructure.DefaultActionSelector.SelectAsync(RouteContext context)
at Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.<RouteAsync>d__6.MoveNext()
4b9b3361

Ответ 1

Update:

Я нашел решение с помощью ActionConstraint. Вы должны добавить собственный атрибут Action Constraint о повторяющихся действиях.

Пример с дублирующими методами индекса.

Первый HomeController

namespace WebApplication.Controllers
{
    public class HomeController : Controller
    {
        [NamespaceConstraint]
        public IActionResult Index()
        {
            return View();
        }
    }
}

Второй HomeController

namespace WebApplication
{
    public class HomeController : Controller
    {
        [NamespaceConstraint]
        public IActionResult Index()
        {
            return View();
        }
    }
}

Настройка маршрутизации

app.UseMvc(cR =>
   cR.MapRoute("default", "{controller}/{action}", null, null, 
   new { Namespace = "WebApplication.Controllers.HomeController" }));

Ограничение действия

namespace WebApplication
{
    public class NamespaceConstraint : ActionMethodSelectorAttribute
    {
        public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action)
        {
            var dataTokenNamespace = (string)routeContext.RouteData.DataTokens.FirstOrDefault(dt => dt.Key == "Namespace").Value;
            var actionNamespace = ((ControllerActionDescriptor)action).MethodInfo.DeclaringType.FullName;

            return dataTokenNamespace == actionNamespace;
        }
    }
}

Первый ответ:

Проводит ли маршрутизация атрибутов маршрутов, определенных приложением app.UseMvc()?

Маршрутизация атрибутов и маршрутизация на основе конференций (routes.MapRoute(...) работают независимо. А маршруты атрибутов имеют преимущество над маршрутами конвенций.

но он, похоже, не делает того, что я хочу. Есть ли способ ограничить механизм маршрутизации определенным пространством имен?

Ответ от разработчиков:

Вместо того, чтобы использовать список пространств имен для группировки контроллеров, мы рекомендуем использовать области. Вы можете связать свои контроллеры (независимо от того, какая их сборка) с определенным Областью, а затем создать маршрут для этого Района.

Вы можете увидеть тестовый сайт, на котором показан пример использования областей в MVC 6 здесь: https://github.com/aspnet/Mvc/tree/dev/test/WebSites/RoutingWebSite.

Пример использования области с маршрутизацией на основе условных обозначений

Контроллер:

//Reached through /admin/users
//have to be located into: project_root/Areas/Admin/
[Area("Admin")]
public class UsersController : Controller
{

}

Настройка маршрутизации на основе протокола:

 app.UseMvc(routes =>
 {
         routes.MapRoute(
         "areaRoute",
         "{area:exists}/{controller}/{action}",
         new { controller = "Home", action = "Index" });
 }

Пример использования области с маршрутизацией на основе атрибутов

//Reached through /admin/users
//have to be located into: project_root/Areas/Admin/
[Area("Admin")]
[Route("[area]/[controller]/[action]", Name = "[area]_[controller]_[action]")]
public class UsersController : Controller
{

}