Path.Combine很方便,但在.NET框架中是否有类似的URL功能?
我正在寻找这样的语法:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
将返回:
"http://MyUrl.com/Images/Image.jpg"
Uri
有一个构造函数,应该为您执行此操作: new Uri(Uri baseUri, string relativeUri)
这是一个例子:
Uri baseUri = new Uri("http://www.contoso.com"); Uri myUri = new Uri(baseUri, "catalog/shownew.htm");
编者注意:请注意,此方法无法按预期工作.在某些情况下,它可以削减部分baseUri.查看评论和其他答案.
这可能是一个非常简单的解决方案:
public static string Combine(string uri1, string uri2) { uri1 = uri1.TrimEnd('/'); uri2 = uri2.TrimStart('/'); return string.Format("{0}/{1}", uri1, uri2); }
你用Uri.TryCreate( ... )
:
Uri result = null; if (Uri.TryCreate(new Uri("http://msdn.microsoft.com/en-us/library/"), "/en-us/library/system.uri.trycreate.aspx", out result)) { Console.WriteLine(result); }
将返回:
http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx
这里已经有了一些很棒的答案.基于mdsharpe建议,这里是一个扩展方法,可以在想要处理Uri实例时轻松使用:
using System; using System.Linq; public static class UriExtensions { public static Uri Append(this Uri uri, params string[] paths) { return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => string.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/')))); } }
用法示例:
var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri;
这将生成http://example.com/subpath/part1/part2
Ryan Cook的答案接近我所追求的,可能更适合其他开发人员.但是,它将http://添加到字符串的开头,并且通常它比我之后的格式更多.
另外,对于我的用例,解析相对路径并不重要.
mdsharp的答案还包含一个好主意的种子,尽管实际的实现需要更多细节才能完成.这是尝试充实它(我在生产中使用它):
C#
public string UrlCombine(string url1, string url2) { if (url1.Length == 0) { return url2; } if (url2.Length == 0) { return url1; } url1 = url1.TrimEnd('/', '\\'); url2 = url2.TrimStart('/', '\\'); return string.Format("{0}/{1}", url1, url2); }
VB.NET
Public Function UrlCombine(ByVal url1 As String, ByVal url2 As String) As String
If url1.Length = 0 Then
Return url2
End If
If url2.Length = 0 Then
Return url1
End If
url1 = url1.TrimEnd("/"c, "\"c)
url2 = url2.TrimStart("/"c, "\"c)
Return String.Format("{0}/{1}", url1, url2)
End Function
此代码通过以下测试,恰好在VB中:
Public Sub UrlCombineTest()
Dim target As StringHelpers = New StringHelpers()
Assert.IsTrue(target.UrlCombine("test1", "test2") = "test1/test2")
Assert.IsTrue(target.UrlCombine("test1/", "test2") = "test1/test2")
Assert.IsTrue(target.UrlCombine("test1", "/test2") = "test1/test2")
Assert.IsTrue(target.UrlCombine("test1/", "/test2") = "test1/test2")
Assert.IsTrue(target.UrlCombine("/test1/", "/test2/") = "/test1/test2/")
Assert.IsTrue(target.UrlCombine("", "/test2/") = "/test2/")
Assert.IsTrue(target.UrlCombine("/test1/", "") = "/test1/")
End Sub
上面有一个Todd Menier的评论,Flurl包含了一个Url.Combine.
更多细节:
Url.Combine基本上是URL的Path.Combine,确保部分之间只有一个分隔符:
var url = Url.Combine( "http://foo.com/", "/too/", "/many/", "/slashes/", "too", "few?", "x=1", "y=2" // result: "http://www.foo.com/too/many/slashes/too/few?x=1&y=2"
在NuGet上获取Flurl.Http:
PM> Install-Package Flurl.Http
或者获取没有HTTP功能的独立URL构建器:
PM> Install-Package Flurl
根据您提供的示例网址,我将假设您要组合相对于您网站的网址.
基于这个假设,我将提出这个解决方案作为对你的问题的最恰当的回答:"Path.Combine很方便,URL的框架中是否有类似的功能?"
由于URL框架中存在类似的功能,我建议正确的是:"VirtualPathUtility.Combine"方法.这是MSDN参考链接:VirtualPathUtility.Combine方法
有一点需要注意:我认为这仅适用于相对于您网站的网址(也就是说,您无法使用它来生成指向其他网站的链接.例如,var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");
).
Path.Combine对我不起作用,因为可能有像"|"这样的字符 在QueryString参数中,因此是URL,这将导致ArgumentException.
我首先尝试了新的Uri(Uri baseUri, string relativeUri)
方法,由于URI的原因,我失败了http://www.mediawiki.org/wiki/Special:SpecialPages
:
new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")
将导致Special:SpecialPages,因为之后的冒号Special
表示一个方案.
所以我最终不得不采用mdsharpe/Brian MacKays路线并进一步开发它以处理多个URI部分:
public static string CombineUri(params string[] uriParts) { string uri = string.Empty; if (uriParts != null && uriParts.Length > 0) { char[] trims = new char[] { '\\', '/' }; uri = (uriParts[0] ?? string.Empty).TrimEnd(trims); for (int i = 1; i < uriParts.Length; i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; }
用法: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
我只是把一个小的扩展方法放在一起:
public static string UriCombine (this string val, string append) { if (String.IsNullOrEmpty(val)) return append; if (String.IsNullOrEmpty(append)) return val; return val.TrimEnd('/') + "/" + append.TrimStart('/'); }
它可以像这样使用:
"www.example.com/".UriCombine("/images").UriCombine("first.jpeg");
一个很好的例子,Ryan,以这个功能的链接结束.做得好.
一个建议Brian:如果将此代码包装在函数中,您可能希望在TryCreate调用之前使用UriBuilder来包装基本URL.
否则,基本URL必须包含该方案(UriBuilder将采用http://).只是一个想法:
public string CombineUrl(string baseUrl, string relativeUrl) { UriBuilder baseUri = new UriBuilder(baseUrl); Uri newUri; if (Uri.TryCreate(baseUri.Uri, relativeUrl, out newUri)) return newUri.ToString(); else throw new ArgumentException("Unable to combine specified url values"); }
一种简单的方法来组合它们并确保它始终是正确的:
string.Format("{0}/{1}", Url1.Trim('/'), Url2);
组合URL的多个部分可能有点棘手.您可以使用双参数构造函数Uri(baseUri, relativeUri)
,也可以使用Uri.TryCreate()
实用程序函数.
在这两种情况下,你可能最终会返回一个不正确的结果,因为这些方法不断截断相对部分关闭的第一个参数baseUri
,即从像http://google.com/some/thing
到http://google.com
.
为了能够将多个部分组合成最终的URL,您可以复制以下两个函数:
public static string Combine(params string[] parts) { if (parts == null || parts.Length == 0) return string.Empty; var urlBuilder = new StringBuilder(); foreach (var part in parts) { var tempUrl = tryCreateRelativeOrAbsolute(part); urlBuilder.Append(tempUrl); } return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToString()); } private static string tryCreateRelativeOrAbsolute(string s) { System.Uri uri; System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri); string tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToString()); return tempUrl; }
可以在https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs上找到用于演示用法的单元测试的完整代码.
我有单元测试来涵盖三种最常见的情况:
我发现UriBuilder
这种事情非常好用:
UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;
有关更多构造函数和文档,请参阅UriBuilder类 - MSDN.