MVC路由识别段错误

时间:2014-05-15 15:29:24

标签: c# asp.net-mvc asp.net-mvc-routing

我有这条路线:
忽略XML格式

<route name="note" url="{noteId}-{title}">
    <constraints>
        <segment name="noteId" value="\d+" />
        <segment name="title" value=".+" />
    </constraints>
</route>

我希望它与 / 1234-hello-kitty / 5578-abc-ddd-fg <等网址相匹配/强>

MVC路由处理程序似乎遇到了一些麻烦。

我一直在读这个主题,我发现了一些有趣的事实:

  • MVC 首先识别路线段 然后检查约束
  • MVC从 从右到左 读取细分,这意味着它首先识别标题,然后 noteId

以第一个例子为例,我猜测MVC将 noteId 识别为 1234-hello title < / em> 作为 kitty

检查约束时会失败,因此路由不匹配。

还有其他办法吗?

请注意我要保留我的细分 noteId 标题,并且它们应该用连字符 -分隔(这是 强制

2 个答案:

答案 0 :(得分:2)

我可以看到解决此问题的方法的几种选择:

URL重写

一种可能性是重写URL(类似于mod_rewrite),将它们从强加于你的格式转换为MVC可以本地路由的格式。有一个IIS Module from Microsoft可以做到这一点,我相信(虽然不确定)会有必要的功能来完成你的情况下的任务。这里的基本原则是,如果由于路由模板解析规则而无法由MVC处理格式,则将URL转换为在它甚至到达MVC路由处理之前可以管理的内容。 URL Rewrite是一个IIS模块,它位于MVC处理程序之前,检查请求,并能够将请求从一个表单重写到另一个表单。然后,这种改变的形式是MVC所看到的,并且可以被它理解和解析。例如。 /1234-hello-kitty的URL可以由模块重写为/1234/hello-kitty,然后MVC路由模板将是一个简单的{noteId}/{*title}。这里的缺点是生成链接可能不起作用,因为生成的链接看起来像/1234/hello-kitty而不是/1234-hello-kitty。但是,缓解可能是专门用于链路生成的路由,而不是用于定义为{noteId}-{title}的路由。我相信(应该验证)这实际上会生成/1234-hello-kitty形式的链接(尽管无法在传入的请求中解析它)。

自定义MVC路由处理程序

这个基本上是基于这样的想法,即如果MVC不为你做,那么覆盖它的行为来做你希望它做的事情。 SO post on how to provide your own handler中描述了这方面的战术方面。您使用它的方式是,您可以提供自己的解析url段的路径数据的解释,并在将它们解析为requestContext.RouteData.Values["nodeId"] = /* your code that gets noteId out of URL. */时提供实际值。该应用程序的其余部分与其他应用程序一样,对路由中的这种外科干预一无所知。

答案 1 :(得分:1)

  

我一直在读这个主题,我发现了一些   有趣的事实:

     
      
  • MVC 首先识别路线段 然后检查约束
  •   
  • MVC从 从右到左 读取细分,这意味着它首先识别标题,然后 noteId
  •   
     

以第一个例子为例,我猜测MVC正在识别 noteId    1234-hello title kitty 点。

     

检查约束时会失败,因此路由不会   匹配。

这些事实和猜测是完全正确的。不幸的是,这就是ASP.NET路由的工作方式。

为什么?

ASP.NET路由简单地分为两个阶段,首先解析所有路由,然后尝试为每个请求匹配它们。

考虑你的情况,首先解析:

  • routeUrl拆分"/"。每个段都是路径段。你只有一个:"{noteId}-{title}"
  • 对于每个路径段,将它们拆分为子段:参数和文字。参数由{}括起,其余的是文字。您有3个子细分:{noteId}-{title}

然后,尝试匹配(当有多个子段时):

  • 找到最后一个文字(-)的最后次出现,并将文字后面的文字与最后一个参数(title)相匹配。
  • 重复第1步以完成所有参数和文字。如果URL或子段较长,则匹配失败。

可能的解决方案

因此,为了使用文字,您必须确保您的文字不会出现在参数中。既然你坚持使用破折号,你可能会有一些可能的解决方案。

  • 您可以使用一个参数而不使用具有匹配约束的文字(例如^\d+-[\w-]+$),然后尝试解析控制器操作中的id。这不需要更改现有的URL结构。
  • 您可以切换titlenoteId的地点,例如/hello-kitty-1234
  • 您可以尝试使用双短划线作为文字,例如/1234--hello-kitty