ASP.NET MVC,URL路由:最大路径(URL)长度


69

场景

我有一个应用程序,使用了良好的旧查询字符串URL结构:

?x=1&y=2&z=3&a=4&b=5&c=6

并将其更改为路径结构:

/x/1/y/2/z/3/a/4/b/5/c/6

我们正在使用ASP.NET MVC和(自然地)ASP.NET路由。

问题

问题在于我们的参数是动态的,并且(理论上)我们需要容纳的参数数量没有限制。

一切都好,直到我们被下列火车撞上:

HTTP错误400.0-错误请求ASP.NET在URL中检测到无效字符。

当我们的URL超过一定长度时,IIS将抛出此错误。

坚韧不拔

这是我们发现的:

这不是IIS问题

IIS确实有最大路径长度限制,但是上面的错误不是这个。

了解dot iis dot net如何使用请求过滤部分“基于请求限制的过滤”

如果该路径对于IIS而言太长,它将抛出404.14,而不是400.0。

此外,IIS最大路径(和查询)长度是可配置的:

<requestLimits


   maxAllowedContentLength="30000000"


   maxUrl="260"


   maxQueryString="25" 


              />

这是一个ASP.NET问题

经过一番戳后:

IIS论坛线程:ASP.NET 2.0的最大URL长度? http://forums.iis.net/t/1105360.aspx

原来,这是一个ASP.NET(实际上是.NET)问题。

事情的核心是,据我所知,ASP.NET无法处理长度超过260个字符的路径。

棺材上的钉子是由哈克(Phil the Haack)本人证实的:

堆栈溢出ASP.NET URL MAX_PATH限制问题ID 265251

问题

那是什么问题呢?

问题是,这有多大限制?

对于我的应用程序,这是一个交易杀手。对于大多数应用程序,这可能不是问题。

那披露呢?我从未听说过有关ASP.NET Routing的任何限制。ASP.NET MVC使用ASP.NET路由的事实使此影响更大。

你怎么看?

Answers:


46

我最终在web.config中使用以下内容来使用Mvc2和.Net Framework 4.0解决此问题

<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />

最大URL长度可以2097151
阿马尔Palsapure

Nogo限制了260个段,也更改了support.microsoft.com/en-us/kb/820129 UrlSegmentMaxCount也nogo
edelwater

是的,relaxedUrlToFileSystemMapping是唯一的方法
Mike Nelson

2
我不需要轻松的UrlToFileSystemMapping来纠正长URL上的HTTP 400错误。只需设置maxUrlLength就可以了。
乔恩·施耐德

在.NET最大路径限制现在已经在4.6.2(解决blogs.msdn.microsoft.com/dotnet/2016/08/02/...
大卫

33

Http.sys服务被编码为每个URL段默认最多260个字符。

在此上下文中,“ URL片段”是Url中“ /”字符之间的内容。例如:

http://www.example.com/segment-one/segment-two/segment-three

可以使用注册表设置更改最大允许的URL段长度:

  • 键: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
  • 值: UrlSegmentMaxLength
  • 类型:REG_DWORD
  • 数据:(您所需的新网址段的最大允许长度,例如4096)

有关http.sys设置的更多信息:http : //support.microsoft.com/kb/820129

允许的最大值是32766。如果指定了较大的值,它将被忽略。(来源:胡安·门德斯)

需要重新启动PC才能使此设置生效。(图片来源:David Rettenbacher,Juan Mendes)


这也为我解决了。我们有一个很长的网址段(注意:不是总网址长度),这导致了问题。我想在这种情况下,值得怀疑的是,当单个网址段超过260个字符时,您是否做对了!
theyetiman

1
值得注意的,此设置必须重新启动才能生效。
David Rettenbacher 2013年

3
机器重启还是只是IIS?
Andrew Bullock

1
我不得不重启整个机器。警告:我最初将此值设置得太高(2097151),并且没有粘滞。当我查看答案中链接的文档并看到最大值是32766时,它终于起作用了
Juan Mendes

我在Win Server 08的注册表中看不到此设置。我认为需要添加此设置。请说明是否需要将其添加为关键字或dword /等。谢谢。
AlexVPerl

31

要解决此问题,请执行以下操作:

在项目的根web.config中,在system.web节点下:

<system.web>
    <httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />
...

另外,我必须将此添加到system.webServer节点下,否则我的长查询字符串遇到了安全错误:

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>
...

它对我有用,system.webServer节点很重要!
2015年

1
@edelwater似乎与再次检查文件系统规则有关,但是将relaxedUrlToFileSystemMapping设置为true也不起作用。
Jerther

解决了我在rest api应用程序中的问题,以处理很长的GET查询
Grengas

16

好的,所以我发布此消息的部分原因还在于我们找到了解决方法。

我希望这对将来的某人有用:D

解决方法

解决方法很简单,也很不错。

由于我们知道站点的哪些部分将需要使用动态参数(因此将具有动态路径和长度),因此可以避免在将其发送到ASP.NET之前将其截取,以免将其发送给ASP.NET路由。

输入IIS7网址重写(或任何等效的重写模块)。

我们建立了如下规则:

    <rewrite>
        <rules>
            <rule>
                <rule name="Remove Category Request Parameters From Url">
                <match url="^category/(\d+)/{0,1}(.*)$" />
                <action type="Rewrite" url="category/{R:1}" />
            </rule>
        </rules>
    </rewrite>

基本上,我们正在做的只是保留足够的路径,以便能够在下游调用正确的路由。我们正在破解的其余URL路径。

URL的其余部分在哪里?

好吧,当引发重写规则时,IIS7 URL重写模块会自动在请求中设置此标头:

HTTP_X_ORIGINAL_URL

下游,在应用程序的解析动态路径部分,而不是查看路径:

HttpContext.Request.Url.PathAndQuery

我们改为查看该标头:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

问题解决了...差不多!

障碍

访问标题

如果需要知道,要访问IIS7重写模块标头,可以通过两种方式进行:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

要么

HttpContext.Request.Headers["X-ORIGINAL-URL"]

固定相对路径

您还将注意到的是,通过上述设置,所有相对路径都中断了(用“〜”定义的URL)。

这包括用ASP.NET MVCHtmlHelperUrlHelper方法(如Url.Route("Bla"))定义的URL 。

这是访问ASP.NET MVC代码的地方。

在该System.Web.Mvc.PathHelper.GenerateClientUrlInternal()方法中,将进行检查以查看是否存在相同的URL Rewrite模块头(请参见上文):

// we only want to manipulate the path if URL rewriting is active, else we risk breaking the generated URL
NameValueCollection serverVars = httpContext.Request.ServerVariables;
bool urlRewriterIsEnabled = (serverVars != null && serverVars[_urlRewriterServerVar] != null);
if (!urlRewriterIsEnabled) {
    return contentPath;
}

如果是这样,则需要做一些工作来保留原始URL。

在我们的情况下,由于我们没有以“常规”方式使用URL重写,因此我们希望缩短此过程。

我们希望假装没有发生URL重写,因为我们不想在原始URL的上下文中考虑相对路径。

我想到的最简单的技巧是完全删除该服务器变量,因此ASP.NET MVC找不到它:

protected void Application_BeginRequest()
{
    string iis7UrlRewriteServerVariable = "HTTP_X_ORIGINAL_URL";

    string headerValue = Request.ServerVariables[iis7UrlRewriteServerVariable];

    if (String.IsNullOrEmpty(headerValue) == false)
    {
        Request.ServerVariables.Remove(iis7UrlRewriteServerVariable);

        Context.Items.Add(iis7UrlRewriteServerVariable, headerValue);
    }
}

(请注意,在上述方法中,我从中删除了标头,Request.ServerVariables但仍保留了标头,将其保存在中Context.Items。原因是稍后需要在请求管道中访问标头值。)

希望这可以帮助!


请您将此设置为答案吗?
丹·阿特金森

我根据您的要求将此设置为答案。
Martin Suchanek 2009年

如果这样做,是否还需要更改web.config文件?我想避免更改web.config文件,这样我就可以只允许对一个特定URL的长时间请求,而对于所有其余URL则正常阻止它们。
克里斯·福克斯(ChrisFox)

3

使用ASP.NET Web API 4时,我遇到了类似的最大URL长度问题,该问题产生了一个稍有不同的错误:

404错误

上面通过使用以下两个标签更新Web.config来描述了针对我的修复程序:

<system.web>
    <httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>

2

我认为您正在努力使用GET。尝试将请求方法更改为POST并将那些查询字符串参数放入请求正文中。

长网址对SEO也没有帮助,对吗?


5
我使用GET的原因有两个:1)这些URL需要共享,并且需要保持不变2)我什么都没有发布。这是读取操作。>长网址对SEO也没有帮助,对吗?我不确定,但是如果请求很复杂,查询也是如此……除非我使用非语义网址,否则无法解决。
2009年

1

似乎硬编码的最大URL长度已在.NET 4.0中修复。特别是,现在有一个web.config部分包含:

<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" /> 

使您可以扩展允许的URL范围。


Joannes,感谢您更新此主题。这被安排固定在.NET 4中,幸运的是它取得了进去。
马丁苏查内克

6
不幸的是,这是不正确的。Microsoft改变了主意,将其更改为lmingle给出的答案。即类似于<httpRuntime maxUrlLength =“ 1024” relaxedUrlToFileSystemMapping =“ true” />
Tom

Dommer,Joannes,感谢您的跟进。我相应地更改了接受的答案。不过,我无法验证自己。
马丁·苏卡内克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.