简体   繁体   English

在ASP.NET Core中限制到控制器命名空间的路由

[英]Restrict route to controller namespace in ASP.NET Core

I'm trying to restrict the controllers of my ASP.NET Core routes to a certain namespace. 我试图将我的ASP.NET核心路由的控制器限制到某个命名空间。

In previous versions of ASP.NET MVC there was an overload that provided a string[] namespaces parameter when adding routes. 在以前版本的ASP.NET MVC中,有一个重载在添加路由时提供了string[] namespaces参数。 This is missing in ASP.NET MVC 6. So after some googling, I tried playing around with something like 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
    );
});

but it doesn't seem to do what I want. 但它似乎没有做我想要的。 Is there a way to restrict the routing engine to a certain namespace? 有没有办法将路由引擎限制到某个命名空间?

Update 更新

I just realized it may have to do something with the fact that I'm using attribute routing on each individual controller? 我刚刚意识到它可能需要对我在每个控制器上使用属性路由这一事实做些什么? Does attribute routing funk up the routes defined by app.UseMvc() ? 属性路由是否会影响app.UseMvc()定义的路由?

Update 2 更新2

More details: 更多细节:

I've two completely independent Web API projects. 我有两个完全独立的Web API项目。 Incidentally, a few of the routes are identical in both (ie. ~/api/ping ). 顺便提一下,一些路由在两者中都是相同的(即~/api/ping )。 These projects are independent in Production, one is an endpoint for users, one is an endpoint for administrators. 这些项目在Production中是独立的,一个是用户的端点,一个是管理员的端点。

I also have unit tests, using Microsoft.AspNet.TestHost . 我还使用Microsoft.AspNet.TestHost进行单元测试。 A few of these unit tests require functionality of both of these Web API projects (ie. need "admin" endpoint to fully setup a test case for "user"). 其中一些单元测试需要这两个Web API项目的功能(即需要“管理”端点来完全为“用户”设置测试用例)。 But when I reference both API projects, the TestHost gets confused because of the identical routes and it complains about "multiple matching routes": 但是,当我引用两个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()

Update: 更新:

I've found solution through using ActionConstraint. 我通过使用ActionConstraint找到了解决方案。 You have to add custom Action Constraint attribute about duplicate actions. 您必须添加有关重复操作的自定义Action Constraint属性。

Example with duplicate Index methods. 重复索引方法的示例。

First HomeController 第一个家庭控制器

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

Second HomeController 第二个HomeController

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

Configure routing 配置路由

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

Action constraint 行动约束

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;
        }
    }
}

First answer: 第一个答案:

Does attribute routing funk up the routes defined by app.UseMvc()? 属性路由是否会影响app.UseMvc()定义的路由?

Attribute routing and Convention-based routing ( routes.MapRoute(... ) work independently. And attribute routes have advantage over convention routes. 属性路由和基于约定的路由( routes.MapRoute(... )独立工作。属性路由优于常规路由。

but it doesn't seem to do what I want. 但它似乎没有做我想要的。 Is there a way to restrict the routing engine to a certain namespace? 有没有办法将路由引擎限制到某个命名空间?

Answer from developers : 开发人员回答

Instead of using a list of namespaces to group your controllers we recommend using Areas. 我们建议使用区域,而不是使用命名空间列表来对控制器进行分组。 You can attribute your controllers (regardless of which assembly they are in) with a specific Area and then create a route for that Area. 您可以将控制器(无论它们位于哪个组件中)与特定区域相关联,然后为该区域创建路径。

You can see a test website that shows an example of using Areas in MVC 6 here: https://github.com/aspnet/Mvc/tree/dev/test/WebSites/RoutingWebSite . 您可以在此处看到一个测试网站,其中显示了在MVC 6中使用区域的示例: https//github.com/aspnet/Mvc/tree/dev/test/WebSites/RoutingWebSite

Example using Area with convention-based routing 使用具有基于约定的路由的Area的示例

Controller: 控制器:

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

}

Configure convention-based routing: 配置基于约定的路由:

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

Example using Area with attribute-based routing 使用具有基于属性的路由的Area的示例

//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
{

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM