2010-09-09 143 views
49

我真的很驚訝,沒有本地.NET方法從相對URL獲取絕對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('/'); 
    } 
+1

一個小建議。您應該使用String.Format,而不是在最後連接URL位。 – Bernd 2010-09-10 05:22:16

回答

82

這一直是我的這種小麻煩的方法。請注意,使用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

快速注意..有時我不想要根的路徑,但根源於我。像這樣的:Page.ResolveUrl(「SomePage.aspx」)。在你的方法中,當我真的想要〜/ path/to/where/I/currently/am/SomePage.aspx時,這會假定我想〜/ SomePage.aspx。偉大的方法! – TruMan1 2010-09-23 21:29:23

+0

..順便說一句VirtualPathUtility.ToAbsolute要求你在開始時有一個〜。但是如果我想要一個相對路徑到我的位置,那麼(context.Handler作爲Page).ResolveUrl起作用。 – TruMan1 2010-09-23 21:41:50

+0

Hummm我是如何設法制作這個社區維基的? >。<@ TruMan1在外部擴展方法(如這個)中,從「Something.aspx」派生一個位置在語義上是不可能的,這就是爲什麼該方法自動將「〜/」追加到路徑的前面。也就是說,只要Handler總是一個頁面,你的(context.Handler as Page)方案就可以工作。如果從HttpHandler或類似程序調用,該解決方案肯定會失敗。 – 2010-09-23 22:23:10

0

檢查下面的代碼來獲取絕對URL:

Page.Request.Url.AbsoluteUri 

我希望對大家有用。

4

使用ASP.NET,您需要考慮「相對URL」的參考點 - 是相對於頁面請求,用戶控件還是相對「簡單地憑藉使用」〜/ 「?

Uri類包含一個簡單的方法相對URL轉換爲絕對URL(指定的絕對URL作爲參考點相對URL):

var uri = new Uri(absoluteUrl, relativeUrl); 

如果relativeUrl實際上是一個abolute網址,那麼absoluteUrl將被忽略。

然後,唯一的問題仍然是參考點是什麼,以及是否允許「〜/」URL(Uri構造函數不能轉換這些)。

1

仍然沒有足夠的使用本機的東西。這是我結束了:

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

這是我自己的版本,它處理用戶當前位置選項的許多驗證和相對路徑。隨意從這裏到重構:)

/// <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); 
} 
58
new System.Uri(Page.Request.Url, "/myRelativeUrl.aspx").AbsoluteUri 
+1

謝謝。至少對於Windows應用商店應用來說,這非常有效。 – Hong 2014-01-17 04:22:11

+0

認爲這應該是現在的答案..作品優秀的網絡應用以及 – Nirman 2015-11-30 07:02:34

+0

這似乎失敗,如果相對Url提供的實際上是一個絕對的URL。例如,'new System.Uri(「http://example.com」,「http://google.com」)應該返回google鏈接。 – Nacht 2017-01-17 06:22:12

8

這一個對我的作品......

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

ResolveClientUrl值得我+投票 – stackuser83 2014-09-13 22:55:44

-1

這工作太細:

HttpContext.Current.Server.MapPath(relativePath) 

如果相對路徑是什麼像「〜/ foo/file.jpg」

+1

我不得不不同意。 Server.MapPath引用一個物理位置,而不是像OP請求那樣絕對的Uri。參考http://stackoverflow.com/questions/275781/server-mappath-server-mappath-server-mappath-server-mappath – 2015-12-29 02:48:38

1

如果喲你就像在MVC控制器的上下文或查看您可以使用哪些應通過公正Url

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

,將完全擴展到/virtual_directoryname/content/images/myimage.jpg

這可以在控制器中使用,或者是訪問的UrlHelper 。CSHTML文件

是的,它是一個有點古怪,這就是所謂的Content但它的意思被使用,因此它是有道理的

0

當你想從你的業務邏輯層生成URL來獲得一個資源的絕對路徑,您不具有使用ASP.NET Web窗體的Page類/ Control的ResolveUrl(..)等的靈活性。此外,您可能需要從ASP.NET MVC控制器生成URL,您不僅可以錯過Web窗體的ResolveUrl (..)方法,但即使Url.Action只接受控制器名稱和操作名稱,也不能獲取Url.Action(..),而不是相對URL。

我嘗試使用

變種的uri =新的URI(absoluteUrl,relativeUrl)

方法,但有一個問題了。如果Web應用程序託管在IIS虛擬目錄中,其中應用程序的URL如下所示:http://localhost/MyWebApplication1/,並且相對URL爲「/ myPage」,則相對URL將解析爲「http://localhost/MyPage」,這是另一個問題。

因此,爲了克服這些問題,我寫了一個可以從類庫中工作的UrlUtils類。所以,它不會依賴於Page類,但它取決於ASP.NET MVC的。所以,如果你不介意在你的類庫項目中添加對MVC dll的引用,那麼我的課程將順利進行。我已經在IIS虛擬目錄場景中測試了Web應用程序url是這樣的:http://localhost/MyWebApplication/MyPage。我意識到,有時我們需要確保絕對網址是SSL網址或非SSL網址。所以,我寫了支持這個選項的類庫。我限制了這個類庫,以便相對url可以是絕對url或以'〜/'開頭的相對url。

使用這個庫,我可以叫

string absoluteUrl = UrlUtils.MapUrl("~/Contact"); 

返回:http://localhost/Contact 當網頁的網址爲:http://localhost/Home/About

返回:http://localhost/MyWebApplication/Contact 當網頁的網址爲:http://localhost/MyWebApplication/Home/About

string absoluteUrl = UrlUtils.MapUrl("~/Contact", UrlUtils.UrlMapOptions.AlwaysSSL); 

退貨:**https**://localhost/MyWebApplication/Contact 當網頁的網址爲: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

最終版本採取一切以前的投訴(端口,邏輯URL,相對URL,現有的絕對URL的照顧.. 。.etc)考慮目前的處理程序是頁:爲您的代碼

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