c# - 限制路由到 ASP.NET Core 中的 Controller 命名空间

标签 c# asp.net asp.net-core-mvc

我试图将我的 ASP.NET Core 路由的 Controller 限制到某个命名空间。

在以前版本的 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
    );
});

但它似乎并没有做我想做的事。有没有办法将路由引擎限制在某个命名空间?

更新

我刚刚意识到这可能与我在每个单独的 Controller 上使用属性路由这一事实有关?属性路由是否会破坏 app.UseMvc() 定义的路由?

更新 2

更多详情:

我有两个完全独立的 Web API 项目。顺便说一下,两者中的一些路由是相同的(即 ~/api/ping)。这些项目在生产中是独立的,一个是用户的端点,一个是管理员的端点。

我还有单元测试,使用 Microsoft.AspNet.TestHost。其中一些单元测试需要这两个 Web API 项目的功能(即需要“管理”端点来为“用户”完全设置测试用例)。但是当我引用这两个 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()

最佳答案

更新:

我通过使用 ActionConstraint 找到了解决方案。您必须添加有关重复操作的自定义操作约束属性。

具有重复索引方法的示例。

第一个家庭 Controller

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

第二个家庭 Controller

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

Action 约束

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

第一个答案:

Does attribute routing funk up the routes defined by app.UseMvc()?

属性路由和基于约定的路由(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.

使用 Area 和基于约定的路由的示例

Controller :

//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" });
 }

使用 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
{
    
}

关于c# - 限制路由到 ASP.NET Core 中的 Controller 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34306891/

相关文章:

c# - 多线程中的数学类给出错误

c# - 递归算法

c# - [HttpPost] 和 [WebMethod] 有什么区别?

javascript - 使用日期时间选择器进行日期和时间验证 (ASP.Net MVC Core v1.1)

.net-core - 是否已在ASP.NET Core MVC 2.1中替换了bundleconfig.json?

c# - 如何在托管函数中 Hook 非托管函数?

c# - 属性路由 - 枚举未解析

asp.net-mvc - 我必须附加到什么进程才能使用 IIS Express 配置文件在 MVC 6 Web 应用程序中进行调试?

c# - 为什么 c# 编译器在某些情况下会发出 newobj/stobj 而不是 'call instance .ctor' 来进行结构初始化

javascript - 这是什么 comboBox 或 dropDownList?