好的,所以我发布此内容的部分原因也是因为我们找到了解决方法。
我希望这对将来的某人有用: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 MVCHtmlHelper
和UrlHelper
方法(如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
. 原因是我需要稍后在请求管道中访问标头值。)
希望这可以帮助!