【问题标题】:Automatic URL Parameter Encoding Failing自动 URL 参数编码失败
【发布时间】:2013-08-10 10:07:50
【问题描述】:

背景

HomeController.cs 我有:

[HttpGet]
public GetPerson(string name)
{
    return View(new PersonModel { ... });
}

Global.asax.cs 我有:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Word", "person/{name}",
         new { controller = "Home", action = "GetPerson" });

    routes.MapRoute(
        "Default", "{controller}/{action}",
        new { controller = "Home", action = "Index" });
}

SomePage.cshtml 中,我实际上有这个:

@{ var name = "Winston S. Churchill"; }
<a href="@Url.Action("GetPerson", "Home", new { name })">@name</a>

问题

如果我点击 Winston S. Churchill 的链接,我会被路由到 URL http://localhost/person/Winston%20S.%20Churchill,这会产生标准的 404 页面:

HTTP 错误 404.0 - 未找到

您要查找的资源已被删除、更改名称或暂时不可用。

仅当 name 变量包含 .(句点)时才会发生这种情况。 例如,当名称为 Winston Churchill 时,我的所有代码都可以正常工作。

如何使 ASP.NET MVC 3% 对 URL 中的 .(句点)进行编码?

或者,如果没有对.(句点)进行百分比编码,如何使路由正常工作?

不可接受的解决方法(如果没有说明理由)

如果我将路线更改为以下,一切正常。

routes.MapRoute(
    "Word", "person",
     new { controller = "Home", action = "GetPerson" });

但是,URL 变成了http://localhost/person?name=Winston%20S.%20Churchill,这不是我想要的。我想要 URL 的路径部分中的 name,而不是查询。

【问题讨论】:

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


    【解决方案1】:

    包含句点和未知扩展名的路由被 IIS 解释为静态文件,而不是通过 .NET 管道发送。例如,您引用的 URL 被解释为带有 %20Churchill 扩展名的静态文件。

    您可以通过将其添加到web.config 来强制 ASP.NET 处理所有请求:

    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true" />
    </system.webServer>
    

    您还需要这个来处理以句点结尾的name 值(而不是只包含一个):

    <system.web>
        <httpRuntime relaxedUrlToFileSystemMapping="true" />
    </system.web>
    

    所有/person/{name} URL 将被您的 ASP.NET 代码拾取。

    如果您不想使用此设置,最简单的解决方法是使用自定义编码:

    name.Replace(".","--")
    

    【讨论】:

    • 这是否存在任何意外的安全问题?
    • 另外,虽然这适用于Winston S. Churchill(我刚刚尝试过),但它对于Albert Gore Jr. 却失败了(注意句号在末尾)。
    • 没有安全问题,但这意味着 ASP.NET 将尝试处理所有请求,因此实际上是静态文件(图像、CSS 等)的加载时间会稍长一些。在实践中,您不太可能注意到差异。要解决终止期的问题,请尝试将&lt;httpRuntime relaxedUrlToFileSystemMapping="true" /&gt; 添加到&lt;system.web&gt;
    • runAllManagedModulesForAllRequests 的问题并不是真正的安全问题,而是性能问题,因为所有请求都将由托管模块处理,甚至请求静态文件。
    • 优秀。我的网站几乎没有静态内容(目前为止是快捷方式图标)。您概述的两个更改效果很好。我将编辑您的答案以突出显示 relaxedUrlToFileSystemMapping 设置。