如何允许“路径中的非法字符”?

19

我有一个MVC.NET应用程序,其中包含以下一个路由:

routes.MapRoute("member", "member/{id}/{*name}", new { controller = "member", action = "Details", id = "" }, new { id = @"\d+" });

因此,链接可能类似于这样:http://domain/member/123/any_kind_of_username

一般来说这很好用,但如果路径包含非法字符(例如双引号:http://domain/member/123/my_"user"_name),我会收到“System.ArgumentException: Illegal characters in path.”的错误提示。

在经过大量搜索后,最好的建议似乎是确保url不包含任何这样的字符。不幸的是,在这种情况下,这是我无法控制的。

是否有一种方法可以解决这个问题?


2
据推测,它们被称为非法字符,因为你不能使用它们... - Mitch Wheat
1
@Mitch - 好的,例如双引号在Apache中可以正常工作,所以我不明白为什么IIS不允许它。@Oded - 问题是我无法控制这些URL。 - hbruce
4个回答

10

Scott Hanselman发布了一篇关于允许在路径中包含非法字符的好文章。

如果你真的想允许受限制的字符,可以通过编辑Web.config将它们从列表中移除(这可能只适用于.NET 4和IIS7):

<system.web>
    <httpRuntime requestValidationMode="2.0" relaxedUrlToFileSystemMapping="true" requestPathInvalidCharacters="&lt;,&gt;,*,%,:,&amp;,\" />
</system.web>

你可能还需要像hbruce建议的那样做:

<system.webServer>
    <security>
        <requestFiltering allowDoubleEscaping="true"/>
    </security>
</system.webServer>

仍有一些特定路径是无法使用的(例如/search/%),因为您将收到400“错误请求 - 无效的URL”消息。我找到的唯一解决方法是将该部分用作查询字符串:/search?q=% 并按照上述步骤操作。


有没有 .net 2 的替代方案? - lathomas64

4
原来您可以通过在web.Config中为requestFiltering设置allowDoubleEscaping="false"来避免这种情况发生。例如:
<configuration>
  <system.webServer>
    <security>
      <requestFiltering allowDoubleEscaping="false" />
    </security>
  </system.webServer>
</configuration>

也许这不是最完美的解决方案(如果有更好的建议,我们非常感激),但它可以解决问题。

1
比较严重的副作用是,如果启用了此设置,则无法在URL中再使用像+这样的字符。请参见:https://dev59.com/wnM_5IYBdhLWcg3wQQzw - Jeff Atwood

0

在提交之前,您应该在客户端对URL进行URL编码。尝试使用UrlHelper.Encode方法。


1
抱歉,和迄今为止其他建议一样,我恐怕无法控制客户端的URL。 - hbruce
3
即使从客户端发送了编码后的URI,我仍然可以得到它。 - IsmailS
建议似乎是要确保URL不包含任何这样的字符。 不幸的是,在这种情况下,我无法控制。 - Chris Moschini

-1
在URL中使用“&”怎么办?例如:mysite.com/JellyBeans/PB&J,其中“PB&J”是控制器操作方法中的参数值。如何避免MVC和ASP.NET引擎将其视为基本URL字符串中的非法字符?使用%26进行编码似乎不起作用。奇怪的是,当启动VS调试本地Web服务器(VS内置Web服务器)时,可以很好地处理该情况(作为&和%26),但是当部署到运行IIS7的Web服务器时,URL会导致“Bad Request”。

2
VS.NET内置的Web服务器相当有缺陷且不符合标准。如果您遇到任何奇怪的行为,最好忽略它并使用IIS。 - Eamon Nerbonne
这是一个后续问题,最好作为新问题发布。如果在此处链接,请在评论中链接,而不是回答中链接。在这种情况下,很可能已经有人问过了,所以最好找到现有的问题而不是再次提问。 - Chris Moschini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接