Path.Combine berguna, tetapi apakah ada fungsi yang serupa dalam kerangka .NET untuk URL ?
Saya mencari sintaks seperti ini:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
yang akan kembali:
"http://MyUrl.com/Images/Image.jpg"
Path.Combine berguna, tetapi apakah ada fungsi yang serupa dalam kerangka .NET untuk URL ?
Saya mencari sintaks seperti ini:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
yang akan kembali:
"http://MyUrl.com/Images/Image.jpg"
Jawaban:
Ada komentar Todd Menier di atas bahwa Flurl termasuk a Url.Combine
.
Keterangan lebih lanjut:
Url.Combine pada dasarnya adalah Path.Combine untuk URL, memastikan satu dan hanya satu karakter pemisah antara bagian:
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"
Dapatkan Flurl.Http di NuGet :
PM> Instal-Paket Flurl.Http
Atau dapatkan pembuat URL yang berdiri sendiri tanpa fitur HTTP:
PM> Paket Instalasi Flurl
Flurl
dan akan membatalkan
Uri
memiliki konstruktor yang harus melakukan ini untuk Anda: new Uri(Uri baseUri, string relativeUri)
Ini sebuah contoh:
Uri baseUri = new Uri("http://www.contoso.com");
Uri myUri = new Uri(baseUri, "catalog/shownew.htm");
Catatan dari editor: Hati-hati, metode ini tidak berfungsi seperti yang diharapkan. Itu dapat memotong bagian baseUri dalam beberapa kasus. Lihat komentar dan jawaban lain.
Ini mungkin solusi sederhana yang sesuai:
public static string Combine(string uri1, string uri2)
{
uri1 = uri1.TrimEnd('/');
uri2 = uri2.TrimStart('/');
return string.Format("{0}/{1}", uri1, uri2);
}
Anda menggunakan 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);
}
Akan kembali:
http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx
int.TryParse
, DateTime.TryParseExact
) memiliki param output ini untuk membuatnya lebih mudah untuk menggunakannya dalam pernyataan-if. Btw, Anda tidak perlu menginisialisasi variabel seperti yang dilakukan Ryan dalam contoh ini.
test.com/mydirectory/
dan /helloworld.aspx
akan menghasilkan test.com/helloworld.aspx
yang tampaknya bukan yang Anda inginkan.
Sudah ada beberapa jawaban bagus di sini. Berdasarkan saran mdsharpe, berikut ini adalah metode ekstensi yang dapat dengan mudah digunakan ketika Anda ingin berurusan dengan instance 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('/'))));
}
}
Dan contoh penggunaan:
var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri;
Ini akan menghasilkan http://example.com/subpath/part1/part2
Jawaban Ryan Cook dekat dengan apa yang saya cari dan mungkin lebih cocok untuk pengembang lain. Namun, ia menambahkan http: // ke awal string dan secara umum ia melakukan sedikit lebih banyak format daripada yang saya kejar.
Juga, untuk kasus penggunaan saya, menyelesaikan jalur relatif tidak penting.
Jawaban mdsharp juga mengandung benih ide yang bagus, meskipun implementasi aktual membutuhkan beberapa detail lagi untuk lengkap. Ini adalah upaya untuk menyempurnakannya (dan saya menggunakan ini dalam produksi):
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
Kode ini lolos tes berikut, yang kebetulan berada di 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")
jika argumennya Nothing
? Maaf, hanya pilih-pilih ;-). Perhatikan bahwa backslash tidak ada hubungannya di URI (dan jika ada, tidak boleh dipangkas), sehingga Anda dapat menghapusnya dari TrimXXX Anda.
Path.Combine tidak berfungsi untuk saya karena mungkin ada karakter seperti "|" dalam argumen QueryString dan karenanya URL, yang akan menghasilkan ArgumentException.
Saya pertama kali mencoba Uri(Uri baseUri, string relativeUri)
pendekatan baru , yang gagal bagi saya karena URI seperti http://www.mediawiki.org/wiki/Special:SpecialPages
:
new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages")
akan menghasilkan Special: SpecialPages, karena titik dua setelah Special
itu menunjukkan skema.
Jadi saya akhirnya harus mengambil rute mdsharpe / Brian MacKays dan mengembangkannya sedikit lebih jauh untuk bekerja dengan beberapa bagian 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;
}
Pemakaian: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")
Berdasarkan pada URL contoh Anda berikan, saya akan menganggap Anda ingin menggabungkan URL yang relatif dengan situs Anda.
Berdasarkan asumsi ini saya akan mengusulkan solusi ini sebagai jawaban yang paling tepat untuk pertanyaan Anda yaitu: "Path.Combine berguna, apakah ada fungsi yang sama dalam kerangka kerja untuk URL?"
Karena ada fungsi serupa dalam kerangka kerja untuk URL yang saya usulkan yang benar adalah: "VirtualPathUtility.Combine" metode. Berikut tautan referensi MSDN: Metode VirtualPathUtility.Combine
Ada satu peringatan: Saya percaya ini hanya berfungsi untuk URL relatif ke situs Anda (yaitu, Anda tidak dapat menggunakannya untuk menghasilkan tautan ke situs web lain. Misalnya, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");
).
Server.MapPath
dan menggabungkan.
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
path.Replace(Path.DirectorySeparatorChar, '/');
path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
Saya hanya mengumpulkan metode ekstensi kecil:
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('/');
}
Dapat digunakan seperti ini:
"www.example.com/".UriCombine("/images").UriCombine("first.jpeg");
Contoh cerdas, Ryan, untuk mengakhiri dengan tautan ke fungsi. Sudah selesai dilakukan dengan baik.
Satu rekomendasi Brian: jika Anda membungkus kode ini dalam suatu fungsi, Anda mungkin ingin menggunakan UriBuilder untuk membungkus URL dasar sebelum panggilan TryCreate.
Jika tidak, URL dasar HARUS menyertakan skema (di mana UriBuilder akan menganggap http: //). Hanya pemikiran saja:
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");
}
Cara mudah untuk menggabungkannya dan memastikan selalu benar adalah:
string.Format("{0}/{1}", Url1.Trim('/'), Url2);
Menggabungkan beberapa bagian dari URL bisa sedikit rumit. Anda dapat menggunakan konstruktor dua parameter Uri(baseUri, relativeUri)
, atau Anda dapat menggunakan Uri.TryCreate()
fungsi utilitas.
Dalam kedua kasus, Anda mungkin berakhir kembali hasil yang salah karena metode ini terus truncating bagian relatif off dari parameter pertama baseUri
, yaitu dari sesuatu seperti http://google.com/some/thing
untuk http://google.com
.
Agar dapat menggabungkan beberapa bagian menjadi URL akhir, Anda dapat menyalin dua fungsi di bawah ini:
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;
}
Kode lengkap dengan tes unit untuk menunjukkan penggunaan dapat ditemukan di https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs
Saya memiliki unit test untuk mencakup tiga kasus paling umum:
Saya menemukan UriBuilder
bekerja dengan sangat baik untuk hal semacam ini:
UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;
Lihat Kelas UriBuilder - MSDN untuk lebih banyak konstruktor dan dokumentasi.
Berikut ini UrlUtility.Combine metode Microsoft (OfficeDev PnP) :
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);
}
Sumber: GitHub
Saya menemukan hal-hal berikut yang bermanfaat dan memiliki fitur-fitur berikut:
params
parameter untuk beberapa segmen UrlKelas
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);
}
Tes
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
Solusi umum saya:
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;
}
Saya membuat fungsi ini yang akan membuat hidup Anda lebih mudah:
/// <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;
}
Ini berfungsi untuk URL dan juga jalur normal.
Pemakaian:
// 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
Mengapa tidak menggunakan saja yang berikut ini.
System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")
[System.IO.Path]::Combine("http://MyUrl.com/","/Images/Image.jpg")
namun ini gagal dengan hasil: /Images/Image.jpg
. Hapus /
dari subPath kedua dan berfungsi:[System.IO.Path]::Combine("http://MyUrl.com/","Images/Image.jpg")
Aturan saat menggabungkan URL dengan URI
Untuk menghindari perilaku aneh ada satu aturan yang harus diikuti:
string.Empty
jalur bagian juga akan menghapus direktori relatif dari URL!Jika Anda mengikuti aturan di atas, Anda dapat menggabungkan URL dengan kode di bawah ini. Bergantung pada situasi Anda, Anda dapat menambahkan beberapa bagian 'direktori' ke 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();
});
Jika Anda tidak ingin menambahkan ketergantungan pihak ketiga seperti Flurl atau membuat metode ekstensi kustom, di ASP.NET Core (juga tersedia di Microsoft.Owin), Anda dapat menggunakan PathString
yang dimaksudkan untuk tujuan membangun URI jalan. Anda kemudian dapat membuat URI lengkap menggunakan kombinasi ini, Uri
dan UriBuilder
.
Dalam hal ini, itu akan menjadi:
new Uri(new UriBuilder("http", "MyUrl.com").Uri, new PathString("/Images").Add("/Image.jpg").ToString())
Ini memberi Anda semua bagian konstituen tanpa harus menentukan pemisah di URL dasar. Sayangnya, PathString
mengharuskan yang /
diawali dengan masing-masing string kalau tidak itu sebenarnya melempar ArgumentException
! Tetapi setidaknya Anda dapat membangun URI Anda secara deterministik dengan cara yang mudah diuji unit.
Jadi saya punya pendekatan lain, mirip dengan semua orang yang menggunakan UriBuilder.
Saya tidak ingin membagi BaseUrl saya (yang dapat berisi bagian dari jalan - misalnya http://mybaseurl.com/dev/ ) seperti yang dilakukan javajavajavajavajavajava .
Cuplikan berikut menunjukkan kode + Tes.
Hati-hati: Solusi ini menurunkan host dan menambahkan port. Jika ini tidak diinginkan, seseorang dapat menulis representasi string dengan misalnya memanfaatkan Uri
Properti 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));
}
}
Diuji dengan .NET Core 2.1 pada Windows 10.
Mengapa ini bekerja?
Meskipun Path.Combine
akan mengembalikan garis miring terbalik (pada Windows minimal), UriBuilder menangani kasus ini di Setter of Path
.
Diambil dari https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.cs (ingat panggilan untuk string.Replace
)
[AllowNull]
public string Path
{
get
{
return _path;
}
set
{
if ((value == null) || (value.Length == 0))
{
value = "/";
}
_path = Uri.InternalEscapeString(value.Replace('\\', '/'));
_changed = true;
}
}
Apakah ini pendekatan terbaik?
Tentu saja solusi ini cukup menggambarkan diri (setidaknya menurut saya). Tetapi Anda mengandalkan "fitur" tidak berdokumen (setidaknya saya tidak menemukan apa-apa dengan pencarian google cepat) dari. NET API. Ini dapat berubah dengan rilis di masa mendatang jadi harap tutupi Metode dengan Tes.
Ada tes di https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FunctionalTests/UriBuilderTests.cs ( Path_Get_Set
) yang memeriksa, jika diperiksa dengan \
benar.
Catatan Sisi: Seseorang juga dapat bekerja dengan UriBuilder.Uri
properti secara langsung, jika uri akan digunakan untuk System.Uri
aktor.
Bagi siapa saja yang mencari satu-liner dan hanya ingin bergabung dengan bagian dari jalan tanpa membuat metode baru atau referensi perpustakaan baru atau membangun nilai URI dan mengonversinya menjadi string, maka ...
string urlToImage = String.Join("/", "websiteUrl", "folder1", "folder2", "folder3", "item");
Ini cukup mendasar, tetapi saya tidak melihat apa lagi yang Anda butuhkan. Jika Anda takut dua kali lipat '/' maka Anda bisa melakukan .Replace("//", "/")
sesudahnya. Jika Anda takut mengganti '//' yang dilipatgandakan dalam 'https: //', alih-alih lakukan satu bergabung, ganti '/' yang digandakan, kemudian bergabunglah dengan url situs web (namun saya cukup yakin sebagian besar browser akan secara otomatis konversikan apa pun dengan 'https:' di depannya untuk membaca dalam format yang benar). Ini akan terlihat seperti:
string urlToImage = String.Join("/","websiteUrl", String.Join("/", "folder1", "folder2", "folder3", "item").Replace("//","/"));
Ada banyak jawaban di sini yang akan menangani semua hal di atas, tetapi dalam kasus saya, saya hanya membutuhkannya sekali di satu lokasi dan tidak perlu terlalu bergantung padanya. Juga, sangat mudah untuk melihat apa yang sedang terjadi di sini.
Lihat: https://docs.microsoft.com/en-us/dotnet/api/system.string.join?view=netframework-4.8
Menggunakan:
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);
}
Ini memiliki manfaat berperilaku persis seperti Path.Combine
.
Inilah pendekatan saya dan saya akan menggunakannya untuk diri saya juga:
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);
}
Gunakan ini:
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);
}
}
Untuk apa nilainya, berikut beberapa metode ekstensi. Yang pertama akan menggabungkan jalur dan yang kedua menambahkan parameter ke 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();
}
Seperti yang ditemukan di jawaban lain, baik yang baru Uri()
atau TryCreate()
dapat melakukan centang. Namun, basis Uri harus diakhiri dengan /
dan relatif harus TIDAK mulai dengan /
; jika tidak, ia akan menghapus bagian akhir dari Url dasar
Saya pikir ini paling baik dilakukan sebagai metode ekstensi, yaitu
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);
}
dan untuk menggunakannya:
var baseUri = new Uri("http://test.com/test/");
var combinedUri = baseUri.Append("/Do/Something");
Dalam hal kinerja, ini menghabiskan lebih banyak sumber daya daripada yang dibutuhkan, karena kelas Uri yang melakukan banyak parsing dan validasi; profil yang sangat kasar (Debug) melakukan sejuta operasi dalam waktu sekitar 2 detik. Ini akan berfungsi untuk sebagian besar skenario, namun agar lebih efisien, lebih baik memanipulasi segala sesuatu sebagai string, ini membutuhkan 125 milidetik untuk 1 juta operasi. Yaitu
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;
}
Dan jika Anda masih ingin mengembalikan URI, dibutuhkan sekitar 600 milidetik untuk 1 juta operasi.
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);
}
Saya harap ini membantu.
Saya pikir ini akan memberi Anda lebih banyak fleksibilitas karena Anda dapat menangani sebanyak mungkin segmen jalur yang Anda inginkan:
public static string UrlCombine(this string baseUrl, params string[] segments)
=> string.Join("/", new[] { baseUrl.TrimEnd('/') }.Concat(segments.Select(s => s.Trim('/'))));
Url.Combine
metode yang melakukan hal itu.