web-dev-qa-db-ja.com

相対パスから絶対URLを取得(リファクタリングされたメソッド)

相対URLから絶対URLを取得するためのネイティブ.NETメソッドがないことに本当に驚いています。私はこれが何度も議論されていることを知っていますが、これをうまく処理する満足のいく方法に出会ったことはありません。以下の方法を微調整できますか?

あとは、プロトコルをハードコーディング(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('/');
    }
55
TruMan1

これは常にこの小さな迷惑に対する私のアプローチでした。 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));
}
87
Nathan Taylor
new System.Uri(Page.Request.Url, "/myRelativeUrl.aspx").AbsoluteUri
66
g.breeze

これは私のために働く...

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

ASP.NETでは、「相対URL」の参照ポイントを考慮する必要があります。それは、ページリクエスト、ユーザーコントロール、または「〜/」を使用するだけで「相対」である場合に相対的ですか?

Uriクラスには、相対URLを絶対URLに変換する簡単な方法が含まれています(相対URLの参照ポイントとして絶対URLを指定した場合)。

var uri = new Uri(absoluteUrl, relativeUrl);

relativeUrlが実際に絶対URLである場合、absoluteUrlは無視されます。

唯一の質問は、参照ポイントが何であるか、および「〜/」URLが許可されているかどうかです(Uriコンストラクターはこれらを変換しません)。

5
Stephen Cleary

これは、ユーザーの現在の場所オプションからの多くの検証と相対パスを処理する独自のバージョンです。ここからリファクタリングしてください:)

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

それでもネイティブのものを使用しても十分なものはありません。ここに私が終わったものがあります:

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

以前のすべての苦情(ポート、論理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);
}
1
yazanpro

次のコードをチェックして絶対Urlを取得します。

Page.Request.Url.AbsoluteUri

役に立つことを願っています。

0
DEVMBM

MVCコントローラーまたはビューのコンテキストにいる場合は、UrlだけでアクセスできるUrlHelperを使用できます

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

完全に/virtual_directoryname/content/images/myimage.jpgに展開されます

これは、コントローラーまたは.cshtmlファイルで使用できます

はい、それはContentと呼ばれるのは少し奇妙ですが、それは意味があるようにリソースへの絶対パスを取得するために使用されることを意図しています

0
Simon_Weaver

ビジネスロジックレイヤーからURLを生成する場合、ASP.NET Webフォームのページクラス/コントロールのResolveUrl(..)などを使用する柔軟性がありません。さらに、ASP .NET MVCコントローラー WebフォームのResolveUrl(..)メソッドを見逃すだけでなく、Url.Actionがコントローラー名とアクション名のみを取り、Url.Action(..)を取得できない場合も相対URL。

使ってみた

var uri = new Uri(absoluteUrl、relativeUrl)

アプローチですが、問題もあります。 WebアプリケーションがIIS仮想ディレクトリでホストされている場合、アプリのURLは次のようになります:http://localhost/MyWebApplication1/、および相対URLが「/ myPage」の場合、相対URLは「http://localhost/MyPage "これは別の問題です。

したがって、このような問題を克服するために、クラスライブラリから機能するUrlUtilsクラスを作成しました。したがって、Pageクラスには依存しませんが、ASP.NET MVCに依存します。したがって、クラスライブラリプロジェクトにMVC dllへの参照を追加してもかまわない場合、クラスはスムーズに動作します。 WebアプリケーションのURLが次のような仮想ディレクトリシナリオであるIISでテストしました:http://localhost/MyWebApplication/MyPage。私は、絶対URLがSSL URLまたは非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;
        }
    }   
0
Emran Hussain