Подтвердить что ты не робот

Получить Абсолютный URL-адрес из Относительного пути (метод рефакторинга)

Я действительно удивлен, что нет собственного метода .NET для получения абсолютного URL-адреса от относительного URL-адреса. Я знаю, что это обсуждалось много раз, но никогда не сталкивались с удовлетворительным методом, который хорошо справляется с этим. Можете ли вы помочь точно настроить метод ниже?

Я думаю, что все, что мне нужно, это автоматический выбор протокола вместо жесткого его кодирования (http/https). Что-нибудь еще мне не хватает (оговорки, производительность и т.д.)?

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('/');
    }
4b9b3361

Ответ 1

Это всегда был мой подход к этой маленькой неприятности. Обратите внимание, что использование 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));
}

Ответ 2

new System.Uri(Page.Request.Url, "/myRelativeUrl.aspx").AbsoluteUri

Ответ 3

Это работает для меня...

new System.Uri(Page.Request.Url, ResolveClientUrl("~/mypage.aspx")).AbsoluteUri

Ответ 4

С ASP.NET вам нужно рассмотреть контрольную точку для "относительного URL" - это относительно запроса страницы, пользовательского элемента управления или, если он "относителен" просто в силу использования "~/",

Uri Класс содержит простой способ преобразования относительного URL в абсолютный URL (учитывая абсолютный адрес в качестве точки отсчета для относительного URL):

var uri = new Uri(absoluteUrl, relativeUrl);

Если relativeUrl на самом деле является абсолютным URL-адресом, то absoluteUrl игнорируется.

Остается только вопрос, какова точка отсчета и допустимы ли URL-адреса "~/" (конструктор Uri не переводит их).

Ответ 5

Вот моя собственная версия, которая обрабатывает многие проверки и относительное перемещение из опций текущего местоположения пользователя. Не стесняйтесь рефакторировать здесь:)

/// <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 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);
}

Ответ 6

По-прежнему ничего хорошего не получается, используя родной материал. Вот что я закончил:

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('/');
}

Ответ 7

Если вы находитесь в контексте MVC Controller или View, вы можете использовать UrlHelper, который должен быть доступен через Url

Url.Content("~/content/images/myimage.jpg")

который будет полностью расширен до /virtual_directoryname/content/images/myimage.jpg

Это может использоваться в контроллере или файле .cshtml

Да, это немного странно, что он называется Content, но он должен использоваться для получения абсолютного пути к ресурсу, поэтому имеет смысл

Ответ 8

проверьте следующий код, чтобы получить абсолютный URL:

Page.Request.Url.AbsoluteUri

Я надеюсь быть полезным.

Ответ 9

Это тоже отлично работает:

HttpContext.Current.Server.MapPath(relativePath)

Если относительный путь является чем-то вроде "~/foo/file.jpg"

Ответ 10

Если вы хотите сгенерировать URL-адрес с уровня вашей бизнес-логики, у вас нет гибкости использования класса страницы ASP.NET Web Form/Control ResolveUrl (..) и т.д. Кроме того, вам может понадобиться генерировать URL-адрес от ASP.NET MVC-контроллер тоже, где вы не только пропускаете метод Web Form ResolveUrl (..), но также не можете получить Url.Action(..), хотя Url.Action принимает только имя контроллера и действие имя, а не относительный URL.

Я попытался использовать

var uri = new Uri (absoluteUrl, relativeUrl)

но есть и проблема. Если веб-приложение размещено в виртуальном каталоге IIS, где URL-адрес приложения выглядит следующим образом: http://localhost/MyWebApplication1/, а относительный URL-адрес - "/myPage", тогда относительный URL-адрес разрешен как "http://localhost/MyPage", что является другой проблемой.

Поэтому, чтобы преодолеть такие проблемы, я написал класс UrlUtils, который может работать из библиотеки классов. Таким образом, это не зависит от класса страницы, но зависит от ASP.NET MVC. Итак, если вы не возражаете добавить ссылку на MVC dll в свой проект библиотеки классов, то мой класс будет работать плавно. Я тестировал в сценарии виртуального каталога IIS, где URL-адрес веб-приложения выглядит следующим образом: http://localhost/MyWebApplication/MyPage. Я понял, что иногда нам нужно убедиться, что Абсолютный URL-адрес - это URL-адрес SSL или не SSL-url. Итак, я написал свою библиотеку классов, поддерживающую эту опцию. Я ограничил эту библиотеку классов, чтобы относительный URL-адрес мог быть абсолютным 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/Contactкогда 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;
        }
    }   

Ответ 11

Окончательная версия, в которой рассматриваются все предыдущие жалобы (порты, логический 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);
}