场景
我在这里我们把美好的旧查询字符串的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会抛出这个错误。
细节问题
下面是我们发现:
这不是一个IIS问题
IIS确实有一个最大路径长度的限制,但上面的错误是不是这个。
学习“基于请求限制过滤器”点IIS点网如何使用请求筛选科
如果路径太长了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个字符的路径。
在这送终由菲尔·哈克本人证实:
堆栈溢出ASP.NET网址MAX_PATH限制问题ID 265251
问题
那么,有什么问题?
现在的问题是,一个限制是多大呢?
对于我的应用程序,这是一个交易的杀手。 对于大多数的应用程序,它可能是一个非问题。
怎么样披露? 无论身在何处ASP.NET路由提到我在哪里听说过有关此限制的窥视。 这ASP.NET MVC使用ASP.NET路由的事实使得这种更大的影响。
你怎么看?
我结束了使用在web.config以下解决使用MVC2和.NET Framework 4.0这个问题
<httpRuntime maxUrlLength="1000" relaxedUrlToFileSystemMapping="true" />
为了解决这个问题,这样做:
在根web.config为您的项目,对System.Web节点下:
<system.web>
<httpRuntime maxUrlLength="10999" maxQueryStringLength="2097151" />
...
此外,我不得不在system.webServer节点下添加此或我有一个安全的错误我长的查询字符串:
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxUrl="10999" maxQueryString="2097151" />
</requestFiltering>
</security>
...
HTTP.SYS服务是编码与默认的最大的每地址段260个字符。
一个“地址段”在此上下文中是在URL“/”字符之间的内容。 例如:
http://www.example.com/segment-one/segment-two/segment-three
最大允许的地址段长度可以用注册表设置进行更改:
- 关键:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
- 价值:
UrlSegmentMaxLength
- 类型:REG_DWORD
- 数据:(你所需的新地址段允许的最大长度,例如4096)
更多关于HTTP.SYS设置: http://support.microsoft.com/kb/820129
最大允许值是32766如果指定一个较大的值,它会被忽略。 (来源:胡安·门德斯)
重新启动PC,需要做出改变这个设置生效。 (来源:大卫Rettenbacher,胡安·门德斯)
行,所以我公布这部分原因是还因为我们已经找到一个变通。
我希望这将是有人在将来有用:d
解决方法
解决方法很简单,这是相当不错的了。
因为我们知道该网站的部分将需要使用动态参数(因此将有一个动态路径和长度),我们能够避免它甚至命中ASP.NET之前拦截它发送这个长的URL到ASP.NET路由
输入IIS7 URL重写(或任何等同的重写模块)。
我们建立了这样的规则:
<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定义的URL HtmlHelper
和UrlHelper
方法(如Url.Route("Bla")
这是进入ASP.NET MVC的代码是真棒。
在System.Web.Mvc.PathHelper.GenerateClientUrlInternal()
方法,有被进行检查,看是否在同一URL重写模块标头中存在(见上文):
// 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
。这样做的原因是,我需要在请求管道进入头值以后。)
希望这可以帮助!
我想你想很难使用GET。 试着改变请求方法POST并把这些查询字符串参数到请求主体。
长URL不利于SEO为好,不是吗?
看来,硬编码的最大URL长度已被固定在.NET 4.0中 。 特别是,现在有一个web.config
有部分:
<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" />
可以让你扩大允许的URL的范围。
我在使用的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>