尝试迁移要在Azure上使用的Web应用程序。该应用程序在标准IIS上运行良好。使用Azure模拟器在本地测试Web应用程序时,所有回发都会导致
错误请求 - 主机名无效
HTTP错误400.请求主机名无效。
我无法在哪里寻找收集更多信息。到目前为止,我已经尝试过:
调试应用程序。我可以验证初始页面加载时是否遇到断点,因此调试肯定有效。导致回发时,调试器不会捕获任何异常。
查看事件查看器。在应用程序或系统Windows日志中,实际上没有针对此问题的日志。
检出Azure模拟器创建的IIS绑定。我注意到在IP地址127.255.0.0,端口8081上创建了绑定。如果我将此IP地址绑定更改为127.0.0.1,则回发可以再次正常工作。这就是为什么我认为问题是负载平衡的结果:如果我绕过负载均衡器,我们再次开展业务。显然,这不是一个永久的解决方案。
我不确定在哪里看这一点:我很难找到有关负载均衡器或其工作原理的信息。有什么地方我可以寻找更多信息吗?此Web应用程序必须执行特定的操作才能导致错误,即使看起来没有抛出异常。可能导致这种情况的原因是什么?
答案 0 :(得分:2)
我找到了一个几乎可以解释这一切的链接:http://social.msdn.microsoft.com/Forums/en-AU/windowsazuredevelopment/thread/87c729e8-094c-4578-b9d1-9c8ff7311577。
在应用程序中,仅使用Request.Url
来确定用户所在的实际页面,然后可以使用它来构建URL以将其路由到其他位置。这在IIS中运行良好,因为在http://somedomain.com/page.aspx?var=1查看Web应用程序的人将此设置为Request.Url参数。就我的localhost示例而言,这只是http://127.0.0.1:8080/page.aspx?var=1。
对于Azure,负载均衡器实际上是在此端口上侦听此IP的设置。然后,负载均衡器将请求传输到其中一个实例,并在另一个端口上运行。这会导致Request.Url属性为http://127.0.0.1:8081/page.aspx?var=1。然后,此属性用于构建要在Server.Transfer调用中使用的URL,这会导致错误请求,因为它们应构建在原始端口8080上,而不是此特定实例的端口8081上。
我深入研究反编译代码,尝试最好地模仿Request.Url属性,但让它映射到原始请求。 Request.Url的代码有点奇怪:
public Uri Url {
get {
if (this._url == (Uri) null && this._wr != null) {
string s = this.QueryStringText;
if (!string.IsNullOrEmpty(s))
s = "?" + HttpEncoder.CollapsePercentUFromStringInternal(s, this.QueryStringEncoding);
if (AppSettings.UseHostHeaderForRequestUrl) {
string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
try {
if (!string.IsNullOrEmpty(knownRequestHeader))
this._url = new Uri(this._wr.GetProtocol() + "://" + knownRequestHeader + this.Path + s);
}
catch (UriFormatException ex){}
}
if (this._url == (Uri) null) {
string str = this._wr.GetServerName();
if (str.IndexOf(':') >= 0 && (int) str[0] != 91)
str = "[" + str + "]";
this._url = new Uri(this._wr.GetProtocol() + "://" + str + ":" + this._wr.GetLocalPortAsString() + this.Path + s);
}
}
return this._url;
}
}
我找不到关于HttpWorkerRequest.GetKnownRequestHeader(28)
的任何信息。 MSDN没有帮助。
返回与指定索引对应的标准HTTP请求标头。
好。什么是指数?此方法的反编译代码只返回(string)null
。所以,我猜这没有任何作用。
反正。我最后用这个替换了这个属性:
new Uri( HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Headers[ "Host" ] + HttpContext.Current.Request.Url.PathAndQuery )
HttpContext.Current.Request.Headers[ "Host" ]
返回原始请求hostname:port。主机是必需的标头,所以这应该是好的。希望使用它可以提供以前行为的所有一致性,同时允许Web应用程序在Azure上运行。