Я нашел ссылку, которая в значительной степени объясняет все это: 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, этот параметр был бы установлен в параметре Request.Url.С точки зрения моего локального примера это просто будет http://127.0.0.1:8080/page.aspx?var=1.
В Azure балансировщик нагрузки фактически настроен для прослушивания этого IP-адреса на этом порту.Затем балансировщик нагрузки передает запрос одному из экземпляров, работающих на другом порту.Это приводит к тому, что свойство Request.Url имеет значение http://127.0.0.1:8081/page.aspx?var=1. Это свойство затем использовалось для создания URL-адресов, которые будут использоваться в вызовах Server.Transfer, что приводило к ошибочным запросам, поскольку они должны быть построены на исходном порту 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.Хост - обязательный заголовок, так что это должно быть хорошо.Надеемся, что использование этого обеспечивает всю согласованность предыдущего поведения, в то же время позволяя веб-приложению функционировать в Azure.