Ответ 1
Что произойдет, если вы просто используете Url.Action( "Действие", "Контроллер" )? Это должно просто генерировать относительный URL-адрес, который должен работать.
(Или, может быть, лучший вопрос: почему вы не используете эту перегрузку?)
Я создаю веб-сайт с использованием MVC3, я использую синтаксис бритвы для создания представлений, и все это работает под лазурью.
В настоящее время я запускаюсь под лазурным эмулятором локально.
У меня есть вид на URL: http://localhost:81/Blah/Foo '.
В этой точке зрения я хочу получить Url для другого действия.
Для этого я использую: Url.Action( "SomeAction", "SomeController", null, this.Request.Url.Scheme)
Однако из-за балансировки нагрузки лазурный эмулятор делает номер порта, который выполняется при изменениях.
то есть. в то время как он работает на порту 81, запрос может поступать с порта 82.
Это приводит к созданию неправильного url http://localhost:82/Blah/Bar ', и я получаю ошибку 400, bad hostname.
Следуя информации в этом сообщении http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/9142db8d-0f85-47a2-91f7-418bb5a0c675/, я обнаружил, что могу получить правильный номер хоста и порта с помощью HttpContext.Request.Headers [ "Host" ].
Но я могу передать имя хоста Url.Action, если я попытаюсь передать имя хоста и порт, то он все еще добавляет то, что, по его мнению, является правильным портом, поэтому я заканчиваю localhost: 81: 82.
EDIT: Я нашел кого-то с той же проблемой. Кажется, что они собрали ту же самую информацию (кроме того, что они включили воспроизведение), но у них нет полезного исправления, поскольку я не могу указать номер порта вручную.
Я полагаю, что одно исправление должно было бы сделать мою собственную перегрузку Url.Action, которая позволяет мне указать порт.
Что произойдет, если вы просто используете Url.Action( "Действие", "Контроллер" )? Это должно просто генерировать относительный URL-адрес, который должен работать.
(Или, может быть, лучший вопрос: почему вы не используете эту перегрузку?)
Для всех, кто приходит сюда, кто НАХОДИТСЯ в абсолютном пути и находится за балансировкой нагрузки, вот что я придумал:
//http://stackoverflow.com/questions/126242/how-do-i-turn-a-relative-url-into-a-full-url
public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName, object routeValues = null)
{
Uri publicFacingUrl = GetPublicFacingUrl(url.RequestContext.HttpContext.Request, url.RequestContext.HttpContext.Request.ServerVariables);
string relAction = url.Action(actionName, controllerName, routeValues);
//this will always have a / in front of it.
var newPort = publicFacingUrl.Port == 80 || publicFacingUrl.Port == 443 ? "" : ":"+publicFacingUrl.Port.ToString();
return publicFacingUrl.Scheme + Uri.SchemeDelimiter + publicFacingUrl.Host + newPort + relAction;
}
И затем из https://github.com/aarnott/dotnetopenid/blob/v3.4/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs через http://go4answers.webhost4life.com/Example/azure-messing-port-numbers-creates-28516.aspx
/// <summary>
/// Gets the public facing URL for the given incoming HTTP request.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="serverVariables">The server variables to consider part of the request.</param>
/// <returns>
/// The URI that the outside world used to create this request.
/// </returns>
/// <remarks>
/// Although the <paramref name="serverVariables"/> value can be obtained from
/// <see cref="HttpRequest.ServerVariables"/>, it useful to be able to pass them
/// in so we can simulate injected values from our unit tests since the actual property
/// is a read-only kind of <see cref="NameValueCollection"/>.
/// </remarks>
internal static Uri GetPublicFacingUrl(HttpRequestBase request, NameValueCollection serverVariables)
{
//Contract.Requires<ArgumentNullException>(request != null);
//Contract.Requires<ArgumentNullException>(serverVariables != null);
// Due to URL rewriting, cloud computing (i.e. Azure)
// and web farms, etc., we have to be VERY careful about what
// we consider the incoming URL. We want to see the URL as it would
// appear on the public-facing side of the hosting web site.
// HttpRequest.Url gives us the internal URL in a cloud environment,
// So we use a variable that (at least from what I can tell) gives us
// the public URL:
if (serverVariables["HTTP_HOST"] != null)
{
//ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols.");
string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme;
Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + serverVariables["HTTP_HOST"]);
UriBuilder publicRequestUri = new UriBuilder(request.Url);
publicRequestUri.Scheme = scheme;
publicRequestUri.Host = hostAndPort.Host;
publicRequestUri.Port = hostAndPort.Port; // CC missing Uri.Port contract that on UriBuilder.Port
return publicRequestUri.Uri;
}
// Failover to the method that works for non-web farm enviroments.
// We use Request.Url for the full path to the server, and modify it
// with Request.RawUrl to capture both the cookieless session "directory" if it exists
// and the original path in case URL rewriting is going on. We don't want to be
// fooled by URL rewriting because we're comparing the actual URL with what in
// the return_to parameter in some cases.
// Response.ApplyAppPathModifier(builder.Path) would have worked for the cookieless
// session, but not the URL rewriting problem.
return new Uri(request.Url, request.RawUrl);
}
Я нашел, что это сработало для меня...
var request = HttpContext.Request;
string url = request.Url.Scheme + "://" +
request.UserHostAddress + ":" +
request.Url.Port;