首页 文章

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

提问于
浏览
65

情景

我有一个应用程序,我们采用了旧的查询字符串 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 会抛出此错误。

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 limit 问题 ID 265251

问题

那么问题是什么?

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

对于我的应用程序,它是一个交易杀手。对于大多数应用程序,它可能是 non-issue。

披露怎么样?没有提到 ASP.NET 路由的地方我听过这个限制的窥视。 ASP.NET MVC 使用 ASP.NET 路由的事实使得这种影响更大。

你怎么看?

7 回答

  • 46

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

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

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

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

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

    另外,我不得不在 system.webServer 节点下添加它,或者我的长查询字符串出现了安全性错误:

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

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

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

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

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

    • 关键:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters

    • 价值:UrlSegmentMaxLength

    • 类型:REG_DWORD

    • 数据:(您想要的新网址段最大允许长度,e.g. 4096)

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

    允许的最大值为 32766.如果指定的值较大,则将忽略该值。 (图片来源:Juan Mendes)

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

  • 16

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

    我希望这对未来的人有用: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 MVC HtmlHelperUrlHelper方法(如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中.原因是我需要稍后在请求中访问标题值 pipe.)

    希望这可以帮助!

  • 2

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

    长网址也不能帮助搜索引擎优化,是吗?

  • 1

    似乎 hard-coded 最大 URL 长度为固定在.NET 4.0。特别是,现在有一个web.config部分:

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

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

  • 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>
    

相关问题