Path.Combineは便利ですが、URLの .NETフレームワークにも同様の機能はありますか?
私はこのような構文を探しています:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
返すでしょう:
"http://MyUrl.com/Images/Image.jpg"
Path.Combineは便利ですが、URLの .NETフレームワークにも同様の機能はありますか?
私はこのような構文を探しています:
Url.Combine("http://MyUrl.com/", "/Images/Image.jpg")
返すでしょう:
"http://MyUrl.com/Images/Image.jpg"
回答:
そこトッド・ムニエのコメントは上記であることをFlurlが含まれますUrl.Combine
。
詳細:
Url.Combineは基本的にURLのPath.Combineであり、パーツ間に1つだけの区切り文字を保証します。
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"
PM>インストールパッケージFlurl.Http
または、HTTP機能なしのスタンドアロンURLビルダーを取得します。
PM>インストールパッケージのFlurl
Flurl
しないで軽量バージョンを使用する場合は、github.com / jean
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
int.TryParse
、DateTime.TryParseExact
)にこの出力パラメーターがあり、ifステートメントで簡単に使用できます。ところで、この例のRyanのように変数を初期化する必要はありません。
test.com/mydirectory/
と参加すると、/helloworld.aspx
結果的に、test.com/helloworld.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にある次のテストに合格します。
<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")
言えば、もし議論がそうであるならば、Nothing
どうですか?すみません、うるさいだけです;-)。バックスラッシュはURIでは何もしないことに注意してください(バックスラッシュがある場合は、削除しないでください)。TrimXXXから削除できます。
「|」などの文字が含まれている可能性があるため、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
がスキームを示すため、Special:SpecialPagesになります。
だから私はようやく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")
提供されたサンプルURLに基づいて、サイトに関連するURLを結合することを想定します。
この仮定に基づいて、「Path.Combineは便利ですが、URLのフレームワークに同様の機能はありますか?」という質問に対する最も適切な回答として、このソリューションを提案します。
URLのフレームワークにも同様の関数があるので、正しい方法は「VirtualPathUtility.Combine」メソッドです。これは、MSDNリファレンスリンクです。VirtualPathUtility.Combineメソッド
注意点が1つあります。これは、自分のサイトに関連するURLに対してのみ機能すると思います(つまり、これを使用して別のWebサイトへのリンクを生成することはできません。たとえば、var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets");
)。
Server.MapPath
を結合するためのショートカットになります。
Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/")
path.Replace(Path.DirectorySeparatorChar, '/');
path.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
私は小さな拡張メソッドをまとめました:
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");
機知に富んだ例、ライアン、関数へのリンクで終わる。よくやった。
1つの推奨事項Brian:このコードを関数でラップする場合、UriBuilderを使用して、TryCreate呼び出しの前にベース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");
}
URLの複数の部分を組み合わせるのは少し難しいかもしれません。2パラメータコンストラクタUri(baseUri, relativeUri)
を使用するか、Uri.TryCreate()
ユーティリティ関数を使用できます。
どちらの場合でも、これらのメソッドは最初のパラメーターの相対部分baseUri
、つまりhttp://google.com/some/thing
to からの相対部分を切り捨て続けるため、誤った結果を返す可能性がありますhttp://google.com
。
複数の部分を最終的なURLに結合できるようにするには、以下の2つの関数をコピーできます。
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にあります。
最も一般的な3つのケースをカバーする単体テストがあります。
私UriBuilder
はこの種のもののために本当にうまくいったことがわかりました:
UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath);
Uri url = urlb.Uri;
return url.AbsoluteUri;
その他のコンストラクターとドキュメントについては、UriBuilderクラス-MSDNを参照してください。
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);
}
出典:GitHub
私は次のものが役に立ち、次の機能を備えています:
params
複数のURLセグメントの複数のパラメーターを受け取りますクラス
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);
}
テスト
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
私の一般的な解決策:
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;
}
私はあなたの人生を楽にするこの関数を作りました:
/// <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;
}
これは、URLと通常のパスで機能します。
使用法:
// 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
以下を使用しないでください。
System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/")
[System.IO.Path]::Combine("http://MyUrl.com/","/Images/Image.jpg")
の結果で失敗します:/Images/Image.jpg
。削除/
二サブパスから、それが動作します:[System.IO.Path]::Combine("http://MyUrl.com/","Images/Image.jpg")
URLとURIを組み合わせる際のルール
奇妙な振る舞いを避けるために、従うべきルールが1つあります。
string.Empty
パーツパスを追加すると、URLからも相対ディレクトリが削除されます。上記のルールに従う場合、URLを以下のコードと組み合わせることができます。状況に応じて、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();
});
Flurlなどのサードパーティの依存関係を追加したくない場合や、ASP.NET Core(Microsoft.Owinでも利用可能)でカスタム拡張メソッドを作成したくない場合PathString
は、URIの構築を目的としたものを使用できます。パス。次に、これUri
との組み合わせを使用して完全なURIを作成できますUriBuilder
。
この場合は、次のようになります。
new Uri(new UriBuilder("http", "MyUrl.com").Uri, new PathString("/Images").Add("/Image.jpg").ToString())
これにより、ベースURLで区切り文字を指定する必要なく、すべての構成部分が得られます。残念ながら、各文字列の前にが付加されているPathString
必要が/
あります。そうでない場合、実際にはArgumentException
!しかし、少なくとも、簡単に単体テストが可能な方法でURIを確定的に構築できます。
そのため、UriBuilderを使用したすべての人に似た別のアプローチがあります。
-私は(例えば、パスの一部含めることができます私のBASEURL分割したくなかったhttp://mybaseurl.com/dev/として)javajavajavajavajavaはなかったが。
次のスニペットは、コードとテストを示しています。
注意:このソリューションは、ホストを小文字にし、ポートを追加します。これが望ましくない場合は、たとえばのUri
プロパティを利用して文字列表現を記述できます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));
}
}
Windows 10の.NET Core 2.1でテスト済み。
なぜこれが機能するのですか?
Path.Combine
(Windowsでは少なくとも)バックスラッシュを返しますが、UriBuilderはSetter ofでこのケースを処理しPath
ます。
https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/src/System/UriBuilder.csから取得(への呼び出しに注意してくださいstring.Replace
)
[AllowNull]
public string Path
{
get
{
return _path;
}
set
{
if ((value == null) || (value.Length == 0))
{
value = "/";
}
_path = Uri.InternalEscapeString(value.Replace('\\', '/'));
_changed = true;
}
}
これは最善の方法ですか?
確かに、このソリューションはかなり自己記述的です(少なくとも私の意見では)。しかし、あなたは.NET APIのドキュメント化されていない(少なくとも、Googleのクイック検索で何も見つからなかった)「機能」に依存しています。これは将来のリリースで変更される可能性があるため、テストによる方法をカバーしてください。
https://github.com/dotnet/corefx/blob/master/src/System.Private.Uri/tests/FunctionalTests/UriBuilderTests.cs(Path_Get_Set
)に\
は、が正しく変換されているかどうかをチェックするテストがあります。
補足:UriBuilder.Uri
uriがSystem.Uri
ctorに使用される場合は、プロパティを直接操作することもできます。
ワンライナーを探していて、新しいメソッドを作成したり、新しいライブラリを参照したり、URI値を構築したり、それを文字列に変換したりせずに、パスの一部を結合したい場合は、...
string urlToImage = String.Join("/", "websiteUrl", "folder1", "folder2", "folder3", "item");
かなり基本的なことですが、それ以上必要なものはわかりません。「/」が2倍になるのが怖い場合は、.Replace("//", "/")
あとで簡単に行うことができます。「https://」の二重の「//」を置き換えるのが怖い場合は、代わりに1つの結合を行い、二重の「/」を置き換えてから、WebサイトのURLに結合します(ただし、ほとんどのブラウザーは自動的に正しい形式で読み取るために、先頭に「https:」があるものをすべて変換します)。これは次のようになります。
string urlToImage = String.Join("/","websiteUrl", String.Join("/", "folder1", "folder2", "folder3", "item").Replace("//","/"));
上記のすべてを処理する答えはたくさんありますが、私の場合は、1つの場所で1回だけ必要であり、大きく依存する必要はありません。また、ここで何が行われているのかを簡単に確認できます。
参照:https : //docs.microsoft.com/en-us/dotnet/api/system.string.join?view=netframework-4.8
使用する:
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);
}
とまったく同じように動作するという利点がありPath.Combine
ます。
これが私のアプローチであり、私自身もそれを使用します。
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);
}
これを使って:
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);
}
}
価値のあるものとして、ここでいくつかの拡張メソッドを紹介します。1つ目はパスを組み合わせ、2つ目はパラメータを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();
}
他の答えで見られるように、新しいUri()
かTryCreate()
、ダニを行うことができます。ただし、ベースUriで終わる必要が/
あり、親戚はで始まってはなりません/
。それ以外の場合は、ベースURLの末尾部分を削除します
これは拡張メソッドとして行うのが最善だと思います。
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);
}
そしてそれを使うには:
var baseUri = new Uri("http://test.com/test/");
var combinedUri = baseUri.Append("/Do/Something");
パフォーマンスの点では、これは必要以上のリソースを消費します。これは、Uriクラスが多くの解析と検証を行うためです。非常に大まかなプロファイリング(デバッグ)は、約2秒で100万回の操作を実行しました。これはほとんどのシナリオで機能しますが、より効率的にするには、すべてを文字列として操作する方が良いです。これは、100万回の操作に125ミリ秒かかります。すなわち
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;
}
それでもURIを返したい場合は、100万回の操作に約600ミリ秒かかります。
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);
}
これがお役に立てば幸いです。
Url.Combine
それを行うメソッドが含まれています。