70

情景

我有一个应用程序,我们在其中采用了良好的旧查询字符串 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 个字符的路径。

棺材上的钉子是菲尔·哈克本人证实的:

Stack Overflow ASP.NET url MAX_PATH 限制问题 ID 265251

问题

那么问题是什么?

问题是,这个限制有多大?

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

披露呢?没有任何地方提到过 ASP.NET 路由,我从来没有听说过这个限制。ASP.NET MVC 使用 ASP.NET 路由这一事实使这种影响更大。

你怎么看?

4

7 回答 7

46

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

<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />
于 2011-04-07T18:23:49.327 回答
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
  • 数据:(您想要的新 URL 段最大允许长度,例如 4096)

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

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

需要重新启动 PC 才能使对此设置的更改生效。(来源:大卫·雷滕巴赫、胡安·门德斯)

于 2011-10-19T07:12:20.320 回答
33

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

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

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

此外,我必须在 system.webServer 节点下添加它,否则我的长查询字符串出现安全错误:

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxUrl="10999" maxQueryString="2097151" />
      </requestFiltering>
    </security>
...
于 2013-09-19T21:45:45.913 回答
17

好的,所以我发布此内容的部分原因也是因为我们找到了解决方法。

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

解决方法

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

由于我们知道站点的哪些部分需要使用动态参数(因此将具有动态路径和长度),我们可以通过在它到达 ASP.NET 之前拦截它来避免将这个长 url 发送到 ASP.NET 路由

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

我们设置了这样的规则:

    <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. 原因是我需要稍后在请求管道中访问标头值。)

希望这可以帮助!

于 2009-07-26T22:54:09.650 回答
4

我在使用 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>
于 2018-08-09T18:28:28.510 回答
2

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

长 URL 对 SEO 也没有帮助,是吗?

于 2009-07-26T22:36:59.157 回答
1

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

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

可让您扩展允许的 URL 范围。

于 2011-04-05T09:23:15.690 回答