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

时间:2009-07-26 22:29:46

标签: asp.net-mvc iis url routing asp.net-routing

场景

我有一个应用程序,我们采用了旧的查询字符串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中检测到无效字符。

当我们的网址超过一定长度时,IIS会抛出此错误。

Nitty Gritty

以下是我们发现的:

这不是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路由这一事实使其影响更大。

您怎么看?

7 个答案:

答案 0 :(得分:45)

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

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

答案 1 :(得分:26)

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

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

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

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

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

答案 2 :(得分:25)

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

此上下文中的“网址细分”是网址中“/”字符之间的内容。例如:

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.如果指定的值较大,则将忽略该值。 (图片来源:Juan Mendes)

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

答案 3 :(得分:14)

好的,我发布这个的部分原因也是因为我们找到了解决方法。

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

解决方法

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

由于我们知道站点的哪些部分需要使用动态参数(因此将具有动态路径和长度),因此我们可以通过在它甚至命中ASP之前拦截它来避免将此长URL发送到ASP.NET路由。 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路径。

网址的其余部分在哪里?

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

HTTP_X_ORIGINAL_URL

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

HttpContext.Request.Url.PathAndQuery

我们会查看该标题:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

问题解决了......几乎!

Snags

访问标题

如果您需要知道,要访问IIS7重写模块标题,您可以通过两种方式实现:

HttpContext.Request.ServerVariables["HTTP_X_ORIGINAL_URL"]

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

修复相对路径

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

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

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

希望这有帮助!

答案 4 :(得分:2)

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

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

答案 5 :(得分:1)

硬编码的最大网址长度似乎为fixed in .NET 4.0。特别是,现在有一个web.config部分:

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

可让您扩展允许的网址范围。

答案 6 :(得分:1)

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

404 Error

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

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

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