Path.Combine rất tiện dụng, nhưng có một chức năng tương tự trong khung .NET cho URL không?
Tôi đang tìm kiếm cú pháp như thế này:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
sẽ trở lại:
"http://MyUrl.com/Images/Image.jpg"
Path.Combine rất tiện dụng, nhưng có một chức năng tương tự trong khung .NET cho URL không?
Tôi đang tìm kiếm cú pháp như thế này:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
sẽ trở lại:
"http://MyUrl.com/Images/Image.jpg"
Câu trả lời:
Có một nhận xét của Todd Menier ở trên rằng Flurl bao gồm a Url.Combine
.
Thêm chi tiết:
Url.Combine về cơ bản là một Path.Combine cho các URL, đảm bảo một và chỉ một ký tự phân tách giữa các phần:
var url = Url.Combine(
"http://MyUrl.com/",
"/too/", "/many/", "/slashes/",
"too", "few?",
"x=1", "y=2"
// result: "http://www.MyUrl.com/too/many/slashes/too/few?x=1&y=2"
Nhận Flurl.Http trên NuGet :
PM> Cài đặt-Gói Flurl.Http
Hoặc có được trình tạo URL độc lập mà không có các tính năng HTTP:
PM> Cài đặt gói
Flurl
và sẽ nhận được một phiên bản nhẹ, github.com/jean-lourenco/UrlCombine
Uri
có một hàm tạo nên làm điều này cho bạn: new Uri(Uri baseUri, string relativeUri)
Đây là một ví dụ:
Uri baseUri = new Uri("http://www.contoso.com");
Uri myUri = new Uri(baseUri, "catalog/shownew.htm");
Lưu ý từ biên tập viên: Hãy coi chừng, phương pháp này không hoạt động như mong đợi. Nó có thể cắt một phần của BaseUri trong một số trường hợp. Xem bình luận và câu trả lời khác.
Đây có thể là một giải pháp đơn giản phù hợp:
public static string Combine(string uri1, string uri2)
{
uri1 = uri1.TrimEnd('/');
uri2 = uri2.TrimStart('/');
return string.Format("{0}/{1}", uri1, uri2);
}
Bạn sử dụng 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);
}
Sẽ trở lại:
http://msdn.microsoft.com/en-us/l Library / system.uri.trycreate.aspx
int.TryParse
, DateTime.TryParseExact
) đều có tham số đầu ra này để giúp sử dụng chúng dễ dàng hơn trong câu lệnh if. Btw, bạn không phải khởi tạo biến như Ryan đã làm trong ví dụ này.
test.com/mydirectory/
và /helloworld.aspx
sẽ dẫn đến kết quả test.com/helloworld.aspx
dường như không phải là điều bạn muốn.
Đã có một số câu trả lời tuyệt vời ở đây. Dựa trên đề xuất mdsharpe, đây là một phương thức mở rộng có thể dễ dàng được sử dụng khi bạn muốn xử lý các trường hợp 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('/'))));
}
}
Và ví dụ sử dụng:
var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri;
Điều này sẽ tạo ra http://example.com/subpath/part1/part2
Câu trả lời của Ryan Cook gần với những gì tôi theo đuổi và có thể phù hợp hơn với các nhà phát triển khác. Tuy nhiên, nó thêm http: // vào đầu chuỗi và nói chung, nó có định dạng nhiều hơn một chút so với sau.
Ngoài ra, đối với các trường hợp sử dụng của tôi, việc giải quyết các đường dẫn tương đối không quan trọng.
Câu trả lời của mdsharp cũng chứa hạt giống của một ý tưởng hay, mặc dù việc triển khai thực tế đó cần thêm một vài chi tiết để hoàn thành. Đây là một nỗ lực để bổ sung nó (và tôi đang sử dụng điều này trong sản xuất):
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
Mã này vượt qua bài kiểm tra sau, xảy ra trong VB:
<TestMethod()> 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
ArgumentNullException("url1")
nếu đối số là Nothing
? Xin lỗi, chỉ là kén chọn ;-). Lưu ý rằng dấu gạch chéo ngược không có gì để làm trong URI (và nếu có, nó không nên được cắt bớt), vì vậy bạn có thể xóa nó khỏi TrimXXX.
Path.Combine không hoạt động với tôi vì có thể có các ký tự như "|" trong các đối số QueryString và do đó là URL, điều này sẽ dẫn đến một ArgumentException.
Lần đầu tiên tôi thử Uri(Uri baseUri, string relativeUri)
cách tiếp cận mới , thất bại đối với tôi vì các URI như http://www.mediawiki.org/wiki/Special:SpecialPages
:
new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")
sẽ dẫn đến Special: SpecialPages, vì dấu hai chấm sau Special
đó biểu thị một lược đồ.
Vì vậy, cuối cùng tôi đã phải đi tuyến đường mdsharpe / Brian MacKays và phát triển nó thêm một chút để làm việc với nhiều phần 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;
}
Sử dụng: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")
Dựa trên URL mẫu bạn cung cấp, tôi sẽ giả định rằng bạn muốn kết hợp các URL có liên quan đến trang web của bạn.
Dựa trên giả định này, tôi sẽ đề xuất giải pháp này là câu trả lời thích hợp nhất cho câu hỏi của bạn, đó là: "Path.Combine rất tiện dụng, có một chức năng tương tự trong khung cho URL không?"
Vì có một chức năng tương tự trong khung cho các URL mà tôi đề xuất chính xác là: phương pháp "VirtualPathUtility.Combine". Đây là liên kết tham chiếu MSDN: VirtualPathUtility.Combine Phương thức
Có một lưu ý: Tôi tin rằng điều này chỉ hoạt động đối với các URL liên quan đến trang web của bạn (nghĩa là bạn không thể sử dụng nó để tạo liên kết đến một trang web khác. Ví dụ var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");
:).
Server.MapPath
và kết hợp.
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
path.Replace(Path.DirectorySeparatorChar, '/');
path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
Tôi chỉ đưa ra một phương pháp mở rộng nhỏ:
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('/');
}
Nó có thể được sử dụng như thế này:
"www.example.com/".UriCombine("/images").UriCombine("first.jpeg");
Ví dụ dí dỏm, Ryan, để kết thúc với một liên kết đến chức năng. Làm tốt.
Một khuyến nghị Brian: nếu bạn bọc mã này trong một hàm, bạn có thể muốn sử dụng UriBuilder để bọc URL cơ sở trước lệnh gọi TryCreate.
Mặt khác, URL cơ sở PHẢI bao gồm lược đồ (trong đó UriBuilder sẽ giả sử http: //). Chỉ là một suy nghĩ:
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");
}
Một cách dễ dàng để kết hợp chúng và đảm bảo nó luôn chính xác là:
string.Format("{0}/{1}", Url1.Trim('/'), Url2);
Kết hợp nhiều phần của một URL có thể hơi khó khăn một chút. Bạn có thể sử dụng hàm tạo hai tham số Uri(baseUri, relativeUri)
hoặc bạn có thể sử dụng Uri.TryCreate()
hàm tiện ích.
Trong cả hai trường hợp, bạn có thể kết thúc trở về một kết quả không chính xác bởi vì các phương pháp này tiếp tục cắt bỏ những phần tương đối tắt của các tham số đầu tiên baseUri
, tức là từ một cái gì đó như http://google.com/some/thing
để http://google.com
.
Để có thể kết hợp nhiều phần vào một URL cuối cùng, bạn có thể sao chép hai chức năng bên dưới:
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;
}
Mã đầy đủ với các bài kiểm tra đơn vị để chứng minh việc sử dụng có thể được tìm thấy tại https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs
Tôi có các bài kiểm tra đơn vị để bao gồm ba trường hợp phổ biến nhất:
Tôi thấy UriBuilder
làm việc rất tốt cho việc này:
UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;
Xem Lớp UriBuilder - MSDN để biết thêm các hàm tạo và tài liệu.
Đây là phương pháp của Microsoft (OfficeDev PnP) UrlUtility.Combine :
const char PATH_DELIMITER = '/';
/// <summary>
/// Combines a path and a relative path.
/// </summary>
/// <param name="path"></param>
/// <param name="relative"></param>
/// <returns></returns>
public static string Combine(string path, string relative)
{
if(relative == null)
relative = String.Empty;
if(path == null)
path = String.Empty;
if(relative.Length == 0 && path.Length == 0)
return String.Empty;
if(relative.Length == 0)
return path;
if(path.Length == 0)
return relative;
path = path.Replace('\\', PATH_DELIMITER);
relative = relative.Replace('\\', PATH_DELIMITER);
return path.TrimEnd(PATH_DELIMITER) + PATH_DELIMITER + relative.TrimStart(PATH_DELIMITER);
}
Nguồn: GitHub
Tôi thấy hữu ích sau đây và có các tính năng sau:
params
tham số cho nhiều phân đoạn UrlLớp học
public static class UrlPath
{
private static string InternalCombine(string source, string dest)
{
if (string.IsNullOrWhiteSpace(source))
throw new ArgumentException("Cannot be null or white space", nameof(source));
if (string.IsNullOrWhiteSpace(dest))
throw new ArgumentException("Cannot be null or white space", nameof(dest));
return $"{source.TrimEnd('/', '\\')}/{dest.TrimStart('/', '\\')}";
}
public static string Combine(string source, params string[] args)
=> args.Aggregate(source, InternalCombine);
}
Xét nghiệm
UrlPath.Combine("test1", "test2");
UrlPath.Combine("test1//", "test2");
UrlPath.Combine("test1", "/test2");
// Result = test1/test2
UrlPath.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ;
// Result = test1/test2/test3
UrlPath.Combine("/test1/", "/test2/", null);
UrlPath.Combine("", "/test2/");
UrlPath.Combine("/test1/", null);
// Throws an ArgumentException
Giải pháp chung của tôi:
public static string Combine(params string[] uriParts)
{
string uri = string.Empty;
if (uriParts != null && uriParts.Any())
{
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;
}
Tôi đã tạo chức năng này sẽ giúp cuộc sống của bạn dễ dàng hơn:
/// <summary>
/// The ultimate Path combiner of all time
/// </summary>
/// <param name="IsURL">
/// true - if the paths are Internet URLs, false - if the paths are local URLs, this is very important as this will be used to decide which separator will be used.
/// </param>
/// <param name="IsRelative">Just adds the separator at the beginning</param>
/// <param name="IsFixInternal">Fix the paths from within (by removing duplicate separators and correcting the separators)</param>
/// <param name="parts">The paths to combine</param>
/// <returns>the combined path</returns>
public static string PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params string[] parts)
{
if (parts == null || parts.Length == 0) return string.Empty;
char separator = IsURL ? '/' : '\\';
if (parts.Length == 1 && IsFixInternal)
{
string validsingle;
if (IsURL)
{
validsingle = parts[0].Replace('\\' , '/');
}
else
{
validsingle = parts[0].Replace('/' , '\\');
}
validsingle = validsingle.Trim(separator);
return (IsRelative ? separator.ToString() : string.Empty) + validsingle;
}
string final = parts
.Aggregate
(
(string first , string second) =>
{
string validfirst;
string validsecond;
if (IsURL)
{
validfirst = first.Replace('\\' , '/');
validsecond = second.Replace('\\' , '/');
}
else
{
validfirst = first.Replace('/' , '\\');
validsecond = second.Replace('/' , '\\');
}
var prefix = string.Empty;
if (IsFixInternal)
{
if (IsURL)
{
if (validfirst.Contains("://"))
{
var tofix = validfirst.Substring(validfirst.IndexOf("://") + 3);
prefix = validfirst.Replace(tofix , string.Empty).TrimStart(separator);
var tofixlist = tofix.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
validfirst = separator + string.Join(separator.ToString() , tofixlist);
}
else
{
var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
validfirst = string.Join(separator.ToString() , firstlist);
}
var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
validsecond = string.Join(separator.ToString() , secondlist);
}
else
{
var firstlist = validfirst.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
var secondlist = validsecond.Split(new[] { separator } , StringSplitOptions.RemoveEmptyEntries);
validfirst = string.Join(separator.ToString() , firstlist);
validsecond = string.Join(separator.ToString() , secondlist);
}
}
return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator);
}
);
return (IsRelative ? separator.ToString() : string.Empty) + final;
}
Nó hoạt động cho các URL cũng như các đường dẫn bình thường.
Sử dụng:
// Fixes internal paths
Console.WriteLine(PathCombine(true , true , true , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
// Result: /folder 1/folder2/folder3/somefile.ext
// Doesn't fix internal paths
Console.WriteLine(PathCombine(true , true , false , @"\/\/folder 1\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
//result : /folder 1//////////folder2////folder3/somefile.ext
// Don't worry about URL prefixes when fixing internal paths
Console.WriteLine(PathCombine(true , false , true , @"/\/\/https:/\/\/\lul.com\/\/\/\\/\folder2\///folder3\\/" , @"/\somefile.ext\/\//\"));
// Result: https://lul.com/folder2/folder3/somefile.ext
Console.WriteLine(PathCombine(false , true , true , @"../../../\\..\...\./../somepath" , @"anotherpath"));
// Result: \..\..\..\..\...\.\..\somepath\anotherpath
Tại sao không chỉ sử dụng như sau.
System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")
[System.IO.Path]::Combine("http://MyUrl.com/","/Images/Image.jpg")
tuy nhiên điều này không thành công với kết quả là : /Images/Image.jpg
. Xóa /
khỏi subPath thứ hai và nó hoạt động:[System.IO.Path]::Combine("http://MyUrl.com/","Images/Image.jpg")
Quy tắc trong khi kết hợp URL với URI
Để tránh hành vi lạ có một quy tắc phải tuân theo:
string.Empty
đường dẫn một phần cũng sẽ xóa thư mục tương đối khỏi URL!Nếu bạn làm theo các quy tắc ở trên, bạn có thể kết hợp URL với mã bên dưới. Tùy thuộc vào tình huống của bạn, bạn có thể thêm nhiều phần 'thư mục' vào URL ...
var pathParts = new string[] { destinationBaseUrl, destinationFolderUrl, fileName };
var destination = pathParts.Aggregate((left, right) =>
{
if (string.IsNullOrWhiteSpace(right))
return left;
return new Uri(new Uri(left), right).ToString();
});
Nếu bạn không muốn thêm phụ thuộc của bên thứ ba như Flurl hoặc tạo phương thức tiện ích mở rộng tùy chỉnh, trong ASP.NET Core (cũng có sẵn trong Microsoft.Owin), bạn có thể sử dụng PathString
nhằm mục đích xây dựng URI đường dẫn. Sau đó, bạn có thể tạo URI đầy đủ của mình bằng cách sử dụng kết hợp này Uri
vàUriBuilder
.
Trong trường hợp này, nó sẽ là:
new Uri(new UriBuilder("http", "MyUrl.com").Uri, new PathString("/Images").Add("/Image.jpg").ToString())
Điều này cung cấp cho bạn tất cả các bộ phận cấu thành mà không phải chỉ định các dấu phân cách trong URL cơ sở. Thật không may, PathString
yêu cầu đó /
được thêm vào từng chuỗi nếu không nó thực sự ném một ArgumentException
! Nhưng ít nhất bạn có thể xây dựng URI của mình một cách xác định theo cách dễ kiểm tra đơn vị.
Vì vậy, tôi có một cách tiếp cận khác, tương tự như mọi người đã sử dụng UriBuilder.
Tôi không muốn tách BaseUrl của mình (có thể chứa một phần của đường dẫn - ví dụ: http://mybaseurl.com/dev/ ) như javajavajavajavajava đã làm.
Đoạn mã sau hiển thị mã + Kiểm tra.
Cẩn thận: Giải pháp này hạ thấp máy chủ và nối thêm một cổng. Nếu điều này là không mong muốn, người ta có thể viết một chuỗi đại diện bằng cách tận dụng Uri
Thuộc tính của UriBuilder
.
public class Tests
{
public static string CombineUrl (string baseUrl, string path)
{
var uriBuilder = new UriBuilder (baseUrl);
uriBuilder.Path = Path.Combine (uriBuilder.Path, path);
return uriBuilder.ToString();
}
[TestCase("http://MyUrl.com/", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
[TestCase("http://MyUrl.com/basePath", "/Images/Image.jpg", "http://myurl.com:80/Images/Image.jpg")]
[TestCase("http://MyUrl.com/basePath", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
[TestCase("http://MyUrl.com/basePath/", "Images/Image.jpg", "http://myurl.com:80/basePath/Images/Image.jpg")]
public void Test1 (string baseUrl, string path, string expected)
{
var result = CombineUrl (baseUrl, path);
Assert.That (result, Is.EqualTo (expected));
}
}
Đã thử nghiệm với .NET Core 2.1 trên Windows 10.
Tại sao điều này làm việc?
Mặc dù Path.Combine
sẽ trả về Backslashes (trên Windows ít nhất), UriBuilder xử lý trường hợp này trong Setter of Path
.
Lấy từ https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.cs (chú ý cuộc gọi đến string.Replace
)
[AllowNull]
public string Path
{
get
{
return _path;
}
set
{
if ((value == null) || (value.Length == 0))
{
value = "/";
}
_path = Uri.InternalEscapeString(value.Replace('\\', '/'));
_changed = true;
}
}
Đây có phải là cách tiếp cận tốt nhất?
Chắc chắn giải pháp này là khá tự mô tả (ít nhất là theo ý kiến của tôi). Nhưng bạn đang dựa vào tài liệu không có giấy tờ (ít nhất là tôi không tìm thấy gì với tìm kiếm nhanh trên google) "tính năng" từ API .NET. Điều này có thể thay đổi với bản phát hành trong tương lai, vì vậy vui lòng bao gồm Phương pháp bằng các Bài kiểm tra.
Có các bài kiểm tra trong https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FeftalTests/UriBuilderTests.cs ( Path_Get_Set
) để kiểm tra, nếu \
nó được chuyển đổi chính xác.
Lưu ý bên lề: Người ta cũng có thể làm việc UriBuilder.Uri
trực tiếp với tài sản, nếu uri sẽ được sử dụng cho một System.Uri
ctor.
Đối với bất kỳ ai đang tìm kiếm một lớp lót và chỉ muốn tham gia các phần của đường dẫn mà không tạo phương thức mới hoặc tham chiếu thư viện mới hoặc xây dựng giá trị URI và chuyển đổi nó thành chuỗi, sau đó ...
string urlToImage = String.Join("/", "websiteUrl", "folder1", "folder2", "folder3", "item");
Nó khá cơ bản, nhưng tôi không thấy bạn cần gì hơn nữa. Nếu bạn sợ nhân đôi '/' thì bạn có thể chỉ cần làm một.Replace("//", "/")
sau đó. Nếu bạn sợ thay thế nhân đôi '//' trong 'https: //', thì thay vào đó hãy tham gia, thay thế nhân đôi '/', sau đó tham gia url trang web (tuy nhiên tôi khá chắc chắn rằng hầu hết các trình duyệt sẽ tự động chuyển đổi bất cứ thứ gì có 'https:' ở phía trước để đọc theo đúng định dạng). Điều này sẽ trông giống như:
string urlToImage = String.Join("/","websiteUrl", String.Join("/", "folder1", "folder2", "folder3", "item").Replace("//","/"));
Có rất nhiều câu trả lời ở đây sẽ xử lý tất cả các câu hỏi trên, nhưng trong trường hợp của tôi, tôi chỉ cần nó một lần ở một địa điểm và sẽ không cần phải phụ thuộc nhiều vào nó. Ngoài ra, thật dễ dàng để xem những gì đang xảy ra ở đây.
Xem: https://docs.microsoft.com/en-us/dotnet/api/system.opes.join?view=netframework-4.8
Sử dụng:
private Uri UriCombine(string path1, string path2, string path3 = "", string path4 = "")
{
string path = System.IO.Path.Combine(path1, path2.TrimStart('\\', '/'), path3.TrimStart('\\', '/'), path4.TrimStart('\\', '/'));
string url = path.Replace('\\','/');
return new Uri(url);
}
Nó có lợi ích của việc cư xử chính xác như thế nào Path.Combine
.
Đây là cách tiếp cận của tôi và tôi cũng sẽ sử dụng nó cho bản thân mình:
public static string UrlCombine(string part1, string part2)
{
string newPart1 = string.Empty;
string newPart2 = string.Empty;
string seperator = "/";
// If either part1 or part 2 is empty,
// we don't need to combine with seperator
if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2))
{
seperator = string.Empty;
}
// If part1 is not empty,
// remove '/' at last
if (!string.IsNullOrEmpty(part1))
{
newPart1 = part1.TrimEnd('/');
}
// If part2 is not empty,
// remove '/' at first
if (!string.IsNullOrEmpty(part2))
{
newPart2 = part2.TrimStart('/');
}
// Now finally combine
return string.Format("{0}{1}{2}", newPart1, seperator, newPart2);
}
Dùng cái này:
public static class WebPath
{
public static string Combine(params string[] args)
{
var prefixAdjusted = args.Select(x => x.StartsWith("/") && !x.StartsWith("http") ? x.Substring(1) : x);
return string.Join("/", prefixAdjusted);
}
}
Đối với những gì nó có giá trị, ở đây một vài phương pháp mở rộng. Cái đầu tiên sẽ kết hợp các đường dẫn và cái thứ hai thêm các tham số vào URL.
public static string CombineUrl(this string root, string path, params string[] paths)
{
if (string.IsNullOrWhiteSpace(path))
{
return root;
}
Uri baseUri = new Uri(root);
Uri combinedPaths = new Uri(baseUri, path);
foreach (string extendedPath in paths)
{
combinedPaths = new Uri(combinedPaths, extendedPath);
}
return combinedPaths.AbsoluteUri;
}
public static string AddUrlParams(this string url, Dictionary<string, string> parameters)
{
if (parameters == null || !parameters.Keys.Any())
{
return url;
}
var tempUrl = new StringBuilder($"{url}?");
int count = 0;
foreach (KeyValuePair<string, string> parameter in parameters)
{
if (count > 0)
{
tempUrl.Append("&");
}
tempUrl.Append($"{WebUtility.UrlEncode(parameter.Key)}={WebUtility.UrlEncode(parameter.Value)}");
count++;
}
return tempUrl.ToString();
}
Như tìm thấy trong các câu trả lời khác, hoặc mới Uri()
hoặc TryCreate()
có thể đánh dấu. Tuy nhiên, Uri cơ sở phải kết thúc /
và người thân phải KHÔNG bắt đầu bằng /
; nếu không, nó sẽ loại bỏ phần đuôi của Url cơ sở
Tôi nghĩ rằng điều này được thực hiện tốt nhất như là một phương pháp mở rộng, tức là
public static Uri Append(this Uri uri, string relativePath)
{
var baseUri = uri.AbsoluteUri.EndsWith('/') ? uri : new Uri(uri.AbsoluteUri + '/');
var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
return new Uri(baseUri, relative);
}
và sử dụng nó:
var baseUri = new Uri("http://test.com/test/");
var combinedUri = baseUri.Append("/Do/Something");
Về hiệu năng, điều này tiêu tốn nhiều tài nguyên hơn mức cần thiết, bởi vì lớp Uri thực hiện nhiều phân tích cú pháp và xác nhận; một hồ sơ rất thô sơ (Debug) đã thực hiện một triệu thao tác trong khoảng 2 giây. Điều này sẽ hoạt động trong hầu hết các kịch bản, tuy nhiên để hiệu quả hơn, tốt hơn là thao tác mọi thứ dưới dạng chuỗi, việc này mất 125 mili giây cho 1 triệu thao tác. I E
public static string Append(this Uri uri, string relativePath)
{
//avoid the use of Uri as it's not needed, and adds a bit of overhead.
var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it
var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/';
var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
return baseUri + relative;
}
Và nếu bạn vẫn muốn trả về một URI, phải mất khoảng 600 mili giây cho 1 triệu thao tác.
public static Uri AppendUri(this Uri uri, string relativePath)
{
//avoid the use of Uri as it's not needed, and adds a bit of overhead.
var absoluteUri = uri.AbsoluteUri; //a calculated property, better cache it
var baseUri = absoluteUri.EndsWith('/') ? absoluteUri : absoluteUri + '/';
var relative = relativePath.StartsWith('/') ? relativePath.Substring(1) : relativePath;
return new Uri(baseUri + relative);
}
Tôi hi vọng cái này giúp được.
Tôi nghĩ rằng điều này sẽ giúp bạn linh hoạt hơn khi bạn có thể xử lý nhiều phân đoạn đường dẫn như bạn muốn:
public static string UrlCombine(this string baseUrl, params string[] segments)
=> string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));
Url.Combine
phương pháp làm việc đó.