好的,所以我发布此消息的部分原因还在于我们找到了解决方法。
我希望这对将来的某人有用:D
解决方法
解决方法很简单,也很不错。
由于我们知道站点的哪些部分将需要使用动态参数(因此将具有动态路径和长度),因此可以避免在将其发送到ASP.NET之前将其截取,以免将其发送给ASP.NET路由。
输入IIS7网址重写(或任何等效的重写模块)。
我们建立了如下规则:
<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模块头(请参见上文):
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
。原因是稍后需要在请求管道中访问标头值。)
希望这可以帮助!