Я очень удивлена, что нет родных .Чистый способ, чтобы получить абсолютный URL из относительного. Я знаю, что это обсуждалось много раз, но никогда не сталкивался удовлетворительный метод, который обрабатывает это хорошо. Вы можете помочь тонкой настройки способ ниже?
Я думаю, что все, что мне нужно осталось, это авто нужно выбрать протокол вместо жесткого кодирования его (HTTP или https). Ничего другого мне не хватает (предостережения, представления, etc)?
public static string GetAbsoluteUrl(string url)
{
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return url;
}
//GET PAGE REFERENCE FOR CONTEXT PROCESSING
Page page = HttpContext.Current.Handler as Page;
//RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
if (url.StartsWith("~/"))
{
url = page.ResolveUrl(url);
}
//BUILD AND RETURN ABSOLUTE URL
return "http://" + page.Request.ServerVariables["SERVER_NAME"] + "/"
+ url.TrimStart('/');
}
Это всегда был мой подход к этой маленькой неприятностью. Обратите внимание на использование VirtualPathUtility.ToAbsolute(relativeUrl) позволяет методу быть объявлен как расширение в статический класс.
/// <summary>
/// Converts the provided app-relative path into an absolute Url containing the
/// full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string ToAbsoluteUrl(this string relativeUrl) {
if (string.IsNullOrEmpty(relativeUrl))
return relativeUrl;
if (HttpContext.Current == null)
return relativeUrl;
if (relativeUrl.StartsWith("/"))
relativeUrl = relativeUrl.Insert(0, "~");
if (!relativeUrl.StartsWith("~/"))
relativeUrl = relativeUrl.Insert(0, "~/");
var url = HttpContext.Current.Request.Url;
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
return String.Format("{0}://{1}{2}{3}",
url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
}
Это один работает для меня...
new System.Uri(Page.Request.Url, ResolveClientUrl("~/mypage.aspx")).AbsoluteUri
С ASP.NET необходимо учесть точки и "относительный URL-адрес, то" - это относительно страницы запросу пользователя контроля, или если он является "относительная" и просто в силу использования и"~/" и?
Класс Ури
содержит простой способ, как преобразовать относительный URL-адрес абсолютный URL-адрес (учитывая абсолютный URL-адрес в качестве точки отсчета для относительных URL-адресов):
var uri = new Uri(absoluteUrl, relativeUrl);
Если relativeUrl на самом деле является abolute URL-адрес, затем absoluteUrl
игнорируется.
Тогда остается вопрос, что исходная точка находится, и есть ли на "~/" и URL-адреса разрешены (Ури
конструктор не перевести).
Вот моя собственная версия, которая выполняет множество проверок и относительная свобода перемещения пользователя'с текущего места. Не стесняйтесь рефакторинг отсюда :)
/// <summary>
/// Converts the provided app-relative path into an absolute Url containing
/// the full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string GetAbsoluteUrl(string relativeUrl)
{
//VALIDATE INPUT
if (String.IsNullOrEmpty(relativeUrl))
return String.Empty;
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
return relativeUrl;
//VALIDATE CONTEXT
if (HttpContext.Current == null)
return relativeUrl;
//GET CONTEXT OF CURRENT USER
HttpContext context = HttpContext.Current;
//FIX ROOT PATH TO APP ROOT PATH
if (relativeUrl.StartsWith("/"))
relativeUrl = relativeUrl.Insert(0, "~");
//GET RELATIVE PATH
Page page = context.Handler as Page;
if (page != null)
{
//USE PAGE IN CASE RELATIVE TO USER'S CURRENT LOCATION IS NEEDED
relativeUrl = page.ResolveUrl(relativeUrl);
}
else //OTHERWISE ASSUME WE WANT ROOT PATH
{
//PREPARE TO USE IN VIRTUAL PATH UTILITY
if (!relativeUrl.StartsWith("~/"))
relativeUrl = relativeUrl.Insert(0, "~/");
relativeUrl = VirtualPathUtility.ToAbsolute(relativeUrl);
}
var url = context.Request.Url;
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
//BUILD AND RETURN ABSOLUTE URL
return String.Format("{0}://{1}{2}{3}",
url.Scheme, url.Host, port, relativeUrl);
}
Окончательный вариант, заботясь о всех предыдущих обращений (портов, логических URL-адрес, URL-адрес, существующий абсолютный URL-адрес...и т. д.) с учетом текущий обработчик страницы:
public static string ConvertToAbsoluteUrl(string url)
{
if (!IsAbsoluteUrl(url))
{
if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Handler is System.Web.UI.Page)
{
var originalUrl = HttpContext.Current.Request.Url;
return string.Format("{0}://{1}{2}{3}", originalUrl.Scheme, originalUrl.Host, !originalUrl.IsDefaultPort ? (":" + originalUrl.Port) : string.Empty, ((System.Web.UI.Page)HttpContext.Current.Handler).ResolveUrl(url));
}
throw new Exception("Invalid context!");
}
else
return url;
}
private static bool IsAbsoluteUrl(string url)
{
Uri result;
return Uri.TryCreate(url, UriKind.Absolute, out result);
}
Еще не достаточно хорошо, используя местное сырье. Вот что я получила в итоге:
public static string GetAbsoluteUrl(string url)
{
//VALIDATE INPUT
if (String.IsNullOrEmpty(url))
{
return String.Empty;
}
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return url;
}
//GET CONTEXT OF CURRENT USER
HttpContext context = HttpContext.Current;
//RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
if (url.StartsWith("~/"))
{
url = (context.Handler as Page).ResolveUrl(url);
}
//BUILD AND RETURN ABSOLUTE URL
string port = (context.Request.Url.Port != 80 && context.Request.Url.Port != 443) ? ":" + context.Request.Url.Port : String.Empty;
return context.Request.Url.Scheme + Uri.SchemeDelimiter + context.Request.Url.Host + port + "/" + url.TrimStart('/');
}
Если вы're в контексте контроллера MVC или просмотреть, вы можете использовать UrlHelper, которые должны быть доступны через просто URL-адрес
Url.Content("~/content/images/myimage.jpg")
Которая будет полностью расширена до /virtual_directoryname/content/images/myimage.jpg
Это может быть использовано в контроллере или .cshtml файл
Да, это немного странно, что это'ов под названием "содержание", но это's не предназначается, чтобы использоваться, чтобы получить абсолютный путь к ресурсу, так что есть смысл
Когда вы хотите создать URL-адрес из вашей бизнес-логики, вы не обладаете гибкостью с помощью Web ASP.NET форма's стр. класс/ управления'ы ResolveUrl(..) и т. д. Кроме того, вам может понадобиться, чтобы создать URL-адрес с контроллер MVC ASP.NET слишком где можно не только пропустить веб-формы'ы ResolveUrl(..) метод, но и вы не можете получить URL-адрес.Действия (..), даже если URL-адрес.Действие занимает только имя контроллера и имя действия, а не относительный url.
Я попытался с помощью
ВАР Ури = новый URI(absoluteUrl, relativeUrl)
подход, но есть проблема тоже. Если веб-приложения, размещенного в IIS виртуальный каталог, где URL-адрес приложения, как это : http://localhost/MyWebApplication1/ и относительный URL-адрес является "/Моя страница" тогда относительный URL-адрес будет решен как "
http://localhost/MyPage в`" что есть еще одна проблема.
Поэтому, для того, чтобы преодолеть подобные проблемы, я написал класс UrlUtils, который может работать с библиотекой классов. Таким образом, это не будет зависеть от класса Page, но это зависит от ASP.NET в MVC. Поэтому, если вы не возражаете против добавления ссылки в MVC DLL в свой проект библиотеки классов, то мой класс будет работать гладко. Я испытал в сценарий виртуального каталога IIS, где URL-адрес веб-приложения, как это : http://localhost/MyWebApplication/MyPage
. Я поняла, что иногда мы должны убедиться, что абсолютный URL-адрес является URL-адрес SSL или URL-адрес SSL. Итак, я написал библиотеку классов, поддерживающих эту опцию. Я ограничил эта библиотека классов, так что относительный URL-адрес может быть абсолютным или относительным URL, который начинается с '~/'.
Используя эту библиотеку, я могу позвонить
string absoluteUrl = UrlUtils.MapUrl("~/Contact");
Возвращает : http://localhost/Contact
когда URL-адрес страницы : http://localhost/Home/About
Возвращает : http://localhost/MyWebApplication/Contact
когда URL-адрес страницы : http://localhost/MyWebApplication/Home/About
string absoluteUrl = UrlUtils.MapUrl("~/Contact", UrlUtils.UrlMapOptions.AlwaysSSL);
Возвращает : **протоколу HTTPS**://localhost в/MyWebApplication/контакт
когда URL-адрес страницы : http://localhost/MyWebApplication/Home/About
Вот моя библиотека классов :
public class UrlUtils
{
public enum UrlMapOptions
{
AlwaysNonSSL,
AlwaysSSL,
BasedOnCurrentScheme
}
public static string MapUrl(string relativeUrl, UrlMapOptions option = UrlMapOptions.BasedOnCurrentScheme)
{
if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
return relativeUrl;
if (!relativeUrl.StartsWith("~/"))
throw new Exception("The relative url must start with ~/");
UrlHelper theHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string theAbsoluteUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +
theHelper.Content(relativeUrl);
switch (option)
{
case UrlMapOptions.AlwaysNonSSL:
{
return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
? string.Format("http://{0}", theAbsoluteUrl.Remove(0, 8))
: theAbsoluteUrl;
}
case UrlMapOptions.AlwaysSSL:
{
return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
? theAbsoluteUrl
: string.Format("https://{0}", theAbsoluteUrl.Remove(0, 7));
}
}
return theAbsoluteUrl;
}
}
Это прекрасно работает тоже:
HttpContext.Current.Server.MapPath(relativePath)
Где относительный путь-это что-то вроде " в файл~/фу/.форматы jpg"и