从相对path(重构方法)获取绝对URL

我真的很惊讶,没有本地的.NET方法从相对url获取绝对url。 我知道这已经被讨论了很多次了,但是从来没有遇到过处理这个问题的令人满意的方法。 你能帮助调整下面的方法吗?

我想我所需要的只是自动select协议而不是硬编码(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('/'); } 

这一直是我对这个小麻烦的方法。 请注意,使用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, "/myRelativeUrl.aspx").AbsoluteUri 

这个适合我…

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

这是我自己的版本,处理用户的当前位置选项的许多validation和相对path。 随意从这里重构:)

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

使用ASP.NET,您需要考虑“相对URL”的参考点 – 它是相对于页面请求,用户控件,还是仅仅通过使用“〜/”而是“相对的”?

Uri类包含一个将相对URL转换为绝对URL的简单方法(给定绝对URL作为相对URL的参考点):

 var uri = new Uri(absoluteUrl, relativeUrl); 

如果relativeUrl实际上是一个绝对URL,那么absoluteUrl被忽略。

唯一的问题就是参考点是什么,以及是否允许“〜/”URL( Uri构造函数不能转换这些)。

仍然没有足够的使用本地的东西。 这是我最后的结果:

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

如果你在一个MVC控制器或视图的上下文中,你可以使用UrlHelper,它只能通过Url访问

 Url.Content("~/contenthttp://img.dovov.commyimage.jpg") 

这将完全展开到/virtual_directoryname/contenthttp://img.dovov.commyimage.jpg

这可以在控制器或.cshtml文件中使用

是的,它被称为Content有点奇怪,但是它被用来获取资源的绝对path,所以它是有意义的

检查下面的代码来检索绝对的Url:

 Page.Request.Url.AbsoluteUri 

我希望是有用的。

当你想从业务逻辑层生成URL时,你没有使用ASP.NET Web Form的Page类/控件的ResolveUrl(..)等的灵活性。另外,你可能需要从ASP.NET MVC控制器即使Url.Action只采用控制器名称和操作名称,而不是相对的URL,也不能错过Web窗体的ResolveUrl(..)方法,但是也不能获取Url.Action(..)。

我试过使用

var uri = new Uri(absoluteUrl,relativeUrl)

的方法,但也有一个问题。 如果Web应用程序托pipe在IIS虚拟目录中,其中应用程序的URL如下所示: http://localhost/MyWebApplication1/ ,相对URL是“/ myPage”,则相对URL将parsing为“ http://localhost/MyPage “这是另一个问题。

因此,为了克服这些问题,我写了一个UrlUtils类,它可以从类库中工作。 所以,它不会依赖于Page类,但它依赖于ASP.NET MVC 。 所以,如果你不介意在你的类库项目中添加对MVC dll的引用,那么我的课程将顺利进行。 我已经在IIS虚拟目录的情况下testing,其中的Web应用程序的URL是这样的: http://localhost/MyWebApplication/MyPage 。 我意识到,有时我们需要确保绝对url是SSLurl或非SSLurl。 所以,我写了我的类库支持这个选项。 我已经限制这个类库,以便相对url可以是绝对url或以'〜/'开头的相对url。

使用这个库,我可以打电话

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

返回: http://localhost/Contact当页面url为: http://localhost/Home/About

当页面url为: http://localhost/MyWebApplication/Home/About时返回: http://localhost/MyWebApplication/Contact

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

返回: **https**://localhost/MyWebApplication/Contact当页面url为: http://localhost/MyWebApplication/Home/About

这是我的class库:

  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) 

相对path如“〜/ foo / file.jpg”

考虑到当前处理程序的最终版本照顾所有以前的投诉(端口,逻辑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); }