简体   繁体   English

MVC 属性路由 RoutePrefix 不适用于默认路由

[英]MVC Attribute Routing RoutePrefix does not work with default routing

I have a work-around, but I'd really like to know why this doesn't appear to work in MVC.我有一个变通方法,但我真的很想知道为什么这在 MVC 中似乎不起作用。 (.Net 4.6.1) (.Net 4.6.1)

I have a controller which I want to use a RoutePrefix:我有一个我想使用 RoutePrefix 的控制器:

[RoutePrefix("entry")]
public class DefaultController : Controller
{
    [HttpGet]
    [Route(), Route("Index")]
    public ActionResult Index()
    {
        // ...
    }
}

In the route config:在路由配置中:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapMvcAttributeRoutes();

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "entry", action = "index", id = UrlParameter.Optional }

The issue is that with this configuration, running under local IIS to test, navigating to "localhost/testApp/entry" works, "localhost/testApp/entry/index" works, however the default "localhost/testApp/" results in a 404.问题是使用此配置,在本地 IIS 下运行进行测试,导航到“localhost/testApp/entry”有效,“localhost/testApp/entry/index”有效,但是默认的“localhost/testApp/”导致 404 .

This has been doing my head in because on a fresh project with the default controllers and a default set to "home" and "index" the "localhost/testApp" would render Home/Index without an issue.这一直是我的头脑,因为在一个带有默认控制器和默认设置为“home”和“index”的新项目中,“localhost/testApp”将毫无问题地呈现 Home/Index。

I narrowed it down to the RoutePrefix being the issue.我将范围缩小到RoutePrefix是问题所在。 If I remove the RoutePrefix and change the defaults to: new { controller = "default", action = "index", id = UrlParameter.Optional }如果我删除RoutePrefix并将默认值更改为: new { controller = "default", action = "index", id = UrlParameter.Optional }

Then "localhost/testApp" works, but obviously this requires using /default for other routes rather than /entry.然后“localhost/testApp”工作,但显然这需要对其他路由使用/default而不是/entry。

Also, if I leave the prefix in (switching the default controller back to "entry") and add Route("~/") to the Index method, then "localhost/testApp" also works as according to the doco that a ~ route overrides the route prefix.此外,如果我保留前缀(将默认控制器切换回“entry”)并将Route("~/")Index方法,那么“localhost/testApp”也可以根据 ~ 路由的 doco 工作覆盖路由前缀。

I'd like to know if there is an explanation why RoutePrefix doesn't seem to play nice with default routing?我想知道是否有解释为什么 RoutePrefix 似乎与默认路由不兼容? I'm fine with adding a ~/ route for that default action, but it seems I'm missing some understanding on how RoutePrefix is intended to be used.我可以为该默认操作添加 ~/ 路由,但似乎我对如何使用 RoutePrefix 缺少一些了解。

Action attribute routing has the highest priority.动作属性路由具有最高优先级。 If you use it only route attributes will be working, everything else will be ignored.如果您使用它,则只有路由属性有效,其他所有内容都将被忽略。 You can to one action as many routes as you need.您可以根据需要对任意多条路线执行一项操作。

Since you have 2 variants - Route() and Route("Index") it works only for 2 urls -"localhost/testApp/entry" and "localhost/testApp/entry/index".由于您有 2 个变体 - Route() 和 Route("Index") 它仅适用于 2 个 url -"localhost/testApp/entry" 和 "localhost/testApp/entry/index"。

if you remove Route() it will work only for one url-lcalhost/testApp/entry/index".如果您删除 Route() 它将仅适用于一个 url-lcalhost/testApp/entry/index”。

If you add 3rd Route("~/") it will work for 3rd url "localhost/testApp" Sign ~ means that any prefixes should be ignored, it starts from root.如果添加第 3 条 Route("~/") 它将适用于第 3 个 url "localhost/testApp" Sign ~ 表示应忽略任何前缀,它从 root 开始。

So you can not use default conventional routing on Index action since it is only obeys routing attributes.所以你不能在 Index action 上使用默认的常规路由,因为它只服从路由属性。

Also, you have a controller [RoutePrefix("entry")] attribute routing too and it that next highest priority and because of this it overrides your convention routing in the config file.此外,您还有一个控制器 [RoutePrefix("entry")] 属性路由,它是下一个最高优先级,因此它会覆盖配置文件中的约定路由。 This is why default routing doesn't work for this controller and it doesn't go to Index automaticaly.这就是默认路由不适用于此控制器并且它不会自动转到索引的原因。 To make default route work you need to remove route prefix and fix web config要使默认路由工作,您需要删除路由前缀并修复 Web 配置

defaults: new { controller = "default", action = "index", id = UrlParameter.Optional }

Current default controller = "entry" doesn't exist at all.当前的默认控制器 = "entry" 根本不存在。

So you have two choices to have Index as default route action - remove all attribute routing and lost all another extra routes or add one more.因此,您有两种选择将 Index 作为默认路由操作 - 删除所有属性路由并丢失所有其他额外路由或添加更多路由。

Thanks to Serge for helping point out a bad assumption I had about [RoutePrefix] .感谢 Serge 帮助指出我对[RoutePrefix]的错误假设。 The problem here turns out that [RoutePrefix] is not a substitute name for a controller, (though that is how it behaves on the surface) but rather a prefix to each individual action.这里的问题是[RoutePrefix]不是控制器的替代名称(尽管这是它在表面上的行为),而是每个单独操作的前缀。 While the mapping in the URL will be identical:虽然 URL 中的映射将是相同的:

Example 1:示例 1:

public class EntryController
{
    public ActionResult Index() { ... }
}

Example 2:示例 2:

[RoutePrefix("Entry")]
public class DefaultController
{
    [Route("Index")]
    public ActionResult Index() { ... }
}

Both of these examples would resolve "localhost/testApp/entry/index", however only the first mapping would be considered as a match for {controller}/{action} and resolve a "defaults" mapping of "entry/index".这两个示例都将解析“localhost/testApp/entry/index”,但是只有第一个映射会被视为匹配 {controller}/{action} 并解析“entry/index”的“默认”映射。

So if an action /w Attribute-based routing needs to be made a root default you need to explicitly declare it as the root using [Route()] if there is no [RoutePrefix] , or [Route("~/")] if there is a [RoutePrefix] .因此,如果一个动作 /w 基于属性的路由需要成为根默认值,如果没有[RoutePrefix]或 [Route("~/")] ,则需要使用[Route()]将其显式声明为根如果有[RoutePrefix] since it won't be included in the {controller}/{action} routing.因为它不会包含在 {controller}/{action} 路由中。 (Verified by removing the Default {controller}/{action} routing entirely). (通过完全删除默认的 {controller}/{action} 路由来验证)。

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

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