Path.Combine pour les URL?

Path.Combine est pratique, mais existe-t-il une fonction similaire dans le framework .NET pour les URL ?

Je cherche une syntaxe comme celle-ci:

Url.Combine("http://soffr.miximages.com/c%23/f") 

qui retournerait:

"http://soffr.miximages.com/c%23/f"

Uri a un constructeur qui devrait le faire pour vous: new Uri(Uri baseUri, ssortingng relativeUri)

Voici un exemple:

 Uri baseUri = new Uri("http://www.contoso.com"); Uri myUri = new Uri(baseUri, "catalog/shownew.htm"); 

Vous utilisez 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); } 

Reviendra:

http://msdn.microsoft.com/en-us/library/system.uri.trycreate.aspx

Cela peut être une solution simple:

 public static ssortingng Combine(ssortingng uri1, ssortingng uri2) { uri1 = uri1.TrimEnd('/'); uri2 = uri2.TrimStart('/'); return ssortingng.Format("{0}/{1}", uri1, uri2); } 

Il y a déjà quelques bonnes réponses ici. Basé sur la suggestion de mdsharpe, voici une méthode d’extension qui peut facilement être utilisée lorsque vous souhaitez gérer des instances Uri:

 using System; using System.Linq; public static class UriExtensions { public static Uri Append(this Uri uri, params ssortingng[] paths) { return new Uri(paths.Aggregate(uri.AbsoluteUri, (current, path) => ssortingng.Format("{0}/{1}", current.TrimEnd('/'), path.TrimStart('/')))); } } 

Et exemple d’utilisation:

 var url = new Uri("http://example.com/subpath/").Append("/part1/", "part2").AbsoluteUri; 

Cela produira http://example.com/subpath/part1/part2

Cette question a obtenu d’excellentes réponses, hautement votées!

La réponse de Ryan Cook est proche de ce que je recherche et peut être plus appropriée pour d’autres développeurs. Cependant, il ajoute http: // au début de la chaîne et en général, il fait un peu plus de formatage que par la suite.

De plus, pour mes cas d’utilisation, la résolution des chemins relatifs n’est pas importante.

La réponse de mdsharp contient également le germe d’une bonne idée, bien que cette mise en œuvre nécessite quelques détails supplémentaires pour être complète. Ceci est une tentative de le compléter (et je l’utilise en production):

C #

 public ssortingng UrlCombine(ssortingng url1, ssortingng url2) { if (url1.Length == 0) { return url2; } if (url2.Length == 0) { return url1; } url1 = url1.TrimEnd('/', '\\'); url2 = url2.TrimStart('/', '\\'); return ssortingng.Format("{0}/{1}", url1, url2); } 

VB.NET

 Public Function UrlCombine(ByVal url1 As Ssortingng, ByVal url2 As Ssortingng) As Ssortingng 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 Ssortingng.Format("{0}/{1}", url1, url2) End Function 

Ce code passe le test suivant, qui se trouve être dans VB:

  Public Sub UrlCombineTest() Dim target As SsortingngHelpers = New SsortingngHelpers() 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 

En fonction de l’ URL d’ exemple que vous avez fournie, je suppose que vous souhaitez combiner des URL relatives à votre site.

Sur la base de cette hypothèse, je proposerai cette solution comme la réponse la plus appropriée à votre question: “Path.Combine est pratique, existe-t-il une fonction similaire dans le framework pour les URL?”

Comme il existe une fonction similaire dans le framework pour les URL que je propose, la méthode correcte est: “VirtualPathUtility.Combine”. Voici le lien de référence MSDN: Méthode VirtualPathUtility.Combine

Il y a une mise en garde: je crois que cela ne fonctionne que pour les URL relatives à votre site (c’est-à-dire que vous ne pouvez pas l’utiliser pour générer des liens vers un autre site Web. Par exemple, var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); ).

Path.Combine ne fonctionne pas pour moi car il peut y avoir des caractères comme “|” dans les arguments QuerySsortingng et donc l’URL, ce qui entraînera une exception ArgumentException.

J’ai d’abord essayé la nouvelle approche Uri (Uri baseUri, ssortingng relativeUri), qui a échoué pour moi en raison d’Uri comme http://www.mediawiki.org/wiki/Special:SpecialPages :

 new Uri(new Uri("http://www.mediawiki.org/wiki/"), "Special:SpecialPages") 

entraînera Special: SpecialPages, à cause du deux-points après Special qui dénote un schéma.

J’ai donc finalement dû prendre la route mdsharpe / Brian MacKays et l’avoir développée un peu plus pour travailler avec plusieurs pièces URI:

 public static ssortingng CombineUri(params ssortingng[] uriParts) { ssortingng uri = ssortingng.Empty; if (uriParts != null && uriParts.Count() > 0) { char[] sortingms = new char[] { '\\', '/' }; uri = (uriParts[0] ?? ssortingng.Empty).TrimEnd(sortingms); for (int i = 1; i < uriParts.Count(); i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; } 

Utilisation: CombineUri("http://www.mediawiki.org/", "wiki", "Special:SpecialPages")

 Path.Combine("Http://MyUrl.com/", "/Images/Image.jpg").Replace("\\", "/") 

Je viens de mettre en place une petite méthode d’extension

 public static ssortingng UriCombine (this ssortingng val, ssortingng append) { if (Ssortingng.IsNullOrEmpty(val)) return append; if (Ssortingng.IsNullOrEmpty(append)) return val; return val.TrimEnd('/') + "/" + append.TrimStart('/'); } 

peut être utilisé comme ceci:

 "www.example.com/".UriCombine("/images").UriCombine("first.jpeg"); 

Witty exemple, Ryan, pour terminer avec un lien vers la fonction. Bien joué.

Une recommandation Brian: si vous emballez ce code dans une fonction, vous souhaiterez peut-être utiliser un UriBuilder pour envelopper l’URL de base avant l’appel TryCreate.

Sinon, l’URL de base DOIT inclure le schéma (où UriBuilder prendra http: //). Juste une pensée:

 public ssortingng CombineUrl(ssortingng baseUrl, ssortingng relativeUrl) { UriBuilder baseUri = new UriBuilder(baseUrl); Uri newUri; if (Uri.TryCreate(baseUri.Uri, relativeUrl, out newUri)) return newUri.ToSsortingng(); else throw new ArgumentException("Unable to combine specified url values"); } 

La combinaison de plusieurs parties d’une URL peut être un peu délicate. Vous pouvez utiliser le constructeur de parameters à 2 parameters Uri(baseUri, relativeUri) , ou vous pouvez utiliser la fonction d’utilitaire Uri.TryCreate() . Dans les deux cas, vous risquez de retourner un résultat incorrect car ces méthodes continuent de tronquer les parties relatives du premier paramètre baseUri , par exemple de quelque chose comme http://google.com/some/thing à http://google.com

Pour pouvoir combiner plusieurs parties dans une URL finale, vous pouvez copier les 2 fonctions ci-dessous:

  public static ssortingng Combine(params ssortingng[] parts) { if (parts == null || parts.Length == 0) return ssortingng.Empty; var urlBuilder = new SsortingngBuilder(); foreach (var part in parts) { var tempUrl = tryCreateRelativeOrAbsolute(part); urlBuilder.Append(tempUrl); } return VirtualPathUtility.RemoveTrailingSlash(urlBuilder.ToSsortingng()); } private static ssortingng tryCreateRelativeOrAbsolute(ssortingng s) { System.Uri uri; System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out uri); ssortingng tempUrl = VirtualPathUtility.AppendTrailingSlash(uri.ToSsortingng()); return tempUrl; } 

Le code complet avec des tests unitaires pour démontrer l’utilisation peut être trouvé à https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs

J’ai des tests unitaires pour couvrir les 3 cas les plus courants: entrer la description de l'image ici

Cette réponse sera probablement perdue dans toutes les réponses ci-dessus, mais j’ai trouvé UriBuilder fonctionnait vraiment bien pour ce genre de chose.

 UriBuilder urlb = new UriBuilder("http", _serverAddress, _webPort, _filePath); Uri url = urlb.Uri; return url.AbsoluteUri; 

Voir Classe UriBuilder – MSDN pour plus de constructeurs et de documentation.

Je sais que cela a été répondu, mais un moyen facile de les combiner et de s’assurer qu’il est toujours correct est ..

 ssortingng.Format("{0}/{1}", Url1.Trim('/'), Url2); 

Voici la méthode de Microsoft (OfficeDev PnP) UrlUtility.Combine :

  const char PATH_DELIMITER = '/'; ///  /// Combines a path and a relative path. ///  ///  ///  ///  public static ssortingng Combine(ssortingng path, ssortingng relative) { if(relative == null) relative = Ssortingng.Empty; if(path == null) path = Ssortingng.Empty; if(relative.Length == 0 && path.Length == 0) return Ssortingng.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); } 

Source: GitHub

Ma solution générique:

 public static ssortingng Combine(params ssortingng[] uriParts) { ssortingng uri = ssortingng.Empty; if (uriParts != null && uriParts.Any()) { char[] sortingms = new char[] { '\\', '/' }; uri = (uriParts[0] ?? ssortingng.Empty).TrimEnd(sortingms); for (int i = 1; i < uriParts.Length; i++) { uri = string.Format("{0}/{1}", uri.TrimEnd(trims), (uriParts[i] ?? string.Empty).TrimStart(trims)); } } return uri; } 

Je sais que je suis en retard à la fête, mais j’ai créé cette fonction qui vous facilitera la vie

  ///  /// the ultimate Path combiner of all time ///  ///  /// 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 ///  /// just adds the separator at the beginning /// fix the paths from within (by removing duplicate separators and correcting the separators) /// the paths to combine /// the combined path public static ssortingng PathCombine(bool IsURL , bool IsRelative , bool IsFixInternal , params ssortingng[] parts) { if (parts == null || parts.Length == 0) return ssortingng.Empty; char separator = IsURL ? '/' : '\\'; if (parts.Length == 1 && IsFixInternal) { ssortingng validsingle; if (IsURL) { validsingle = parts[0].Replace('\\' , '/'); } else { validsingle = parts[0].Replace('/' , '\\'); } validsingle = validsingle.Trim(separator); return (IsRelative ? separator.ToSsortingng() : ssortingng.Empty) + validsingle; } ssortingng final = parts .Aggregate ( (ssortingng first , ssortingng second) => { ssortingng validfirst; ssortingng validsecond; if (IsURL) { validfirst = first.Replace('\\' , '/'); validsecond = second.Replace('\\' , '/'); } else { validfirst = first.Replace('/' , '\\'); validsecond = second.Replace('/' , '\\'); } var prefix = ssortingng.Empty; if (IsFixInternal) { if (IsURL) { if (validfirst.Contains("://")) { var tofix = validfirst.Subssortingng(validfirst.IndexOf("://") + 3); prefix = validfirst.Replace(tofix , ssortingng.Empty).TrimStart(separator); var tofixlist = tofix.Split(new[] { separator } , SsortingngSplitOptions.RemoveEmptyEnsortinges); validfirst = separator + ssortingng.Join(separator.ToSsortingng() , tofixlist); } else { var firstlist = validfirst.Split(new[] { separator } , SsortingngSplitOptions.RemoveEmptyEnsortinges); validfirst = ssortingng.Join(separator.ToSsortingng() , firstlist); } var secondlist = validsecond.Split(new[] { separator } , SsortingngSplitOptions.RemoveEmptyEnsortinges); validsecond = ssortingng.Join(separator.ToSsortingng() , secondlist); } else { var firstlist = validfirst.Split(new[] { separator } , SsortingngSplitOptions.RemoveEmptyEnsortinges); var secondlist = validsecond.Split(new[] { separator } , SsortingngSplitOptions.RemoveEmptyEnsortinges); validfirst = ssortingng.Join(separator.ToSsortingng() , firstlist); validsecond = ssortingng.Join(separator.ToSsortingng() , secondlist); } } return prefix + validfirst.Trim(separator) + separator + validsecond.Trim(separator); } ); return (IsRelative ? separator.ToSsortingng() : ssortingng.Empty) + final; } 

cela fonctionne pour les URL aussi bien que les chemins normaux

Utilisation:

  //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 

Je sais que cette question est bien répondu, mais je trouve cela utile car il a les caractéristiques suivantes

  • Lance sur un espace vide ou blanc
  • Classe statique qui imite de plus près System.Io.Path
  • Prend le paramètre params pour plusieurs segments Url

Remarque: Le nom de classe Url peut être modifié car il existe une classe système System.Security.Policy.Url

Classe

 public static class Url { private static ssortingng InternalCombine(ssortingng source, ssortingng dest) { // If the source is null or white space retune the dest only if (ssortingng.IsNullOrWhiteSpace(source)) { throw new ArgumentException("Cannot be null or white space", "source"); // throw new ArgumentException("Cannot be null or white space", nameof(source)); // c# 6.0 Nameof Expression } if (ssortingng.IsNullOrWhiteSpace(dest)) { throw new ArgumentException("Cannot be null or white space", "dest"); // throw new ArgumentException("Cannot be null or white space", nameof(dest)); // c# 6.0 Nameof Expression } source = source.TrimEnd('/', '\\'); dest = dest.TrimStart('/', '\\'); return ssortingng.Format("{0}/{1}", source, dest); // return $"{source}/{dest}"; // c# 6.0 ssortingng interpolation } public static ssortingng Combine(ssortingng source, params ssortingng[] args) { return args.Aggregate(source, InternalCombine); } } 

Résultats

 Url.Combine("test1", "test2"); Url.Combine("test1//", "test2"); Url.Combine("test1", "/test2"); // Result = test1/test2 Url.Combine(@"test1\/\/\/", @"\/\/\\\\\//test2", @"\/\/\\\\\//test3\") ; // Result = test1/test2/test3 Url.Combine("/test1/", "/test2/", null); Url.Combine("", "/test2/"); Url.Combine("/test1/", null); // Throws an ArgumentException 

Que dis-tu de ça?

  public static class WebPath { public static ssortingng Combine(params ssortingng[] args) { var prefixAdjusted = args.Select(x => x.StartsWith("/") && !x.StartsWith("http") ? x.Subssortingng(1) : x); return ssortingng.Join("/", prefixAdjusted); } } 

Voici mon approche et je vais l’utiliser pour moi aussi

 public static ssortingng UrlCombine(ssortingng part1, ssortingng part2) { ssortingng newPart1 = ssortingng.Empty; ssortingng newPart2 = ssortingng.Empty; ssortingng seprator = "/"; // if either part1 or part 2 is empty, // we don't need to combine with seprator if (ssortingng.IsNullOrEmpty(part1) || ssortingng.IsNullOrEmpty(part2)) { seprator = ssortingng.Empty; } // if part1 is not empty // remove '/' at last if (!ssortingng.IsNullOrEmpty(part1)) { newPart1 = part1.TrimEnd('/'); } // if part2 is not empty // remove '/' at first if (!ssortingng.IsNullOrEmpty(part2)) { newPart2 = part2.TrimStart('/'); } // now finally combine return ssortingng.Format("{0}{1}{2}", newPart1, seprator, newPart2); } 
  private Uri UriCombine(ssortingng path1, ssortingng path2, ssortingng path3 = "", ssortingng path4 = "") { ssortingng path = System.IO.Path.Combine(path1, path2.TrimStart('\\', '/'), path3.TrimStart('\\', '/'), path4.TrimStart('\\', '/')); ssortingng url = path.Replace('\\','/'); return new Uri(url); } 

A l’avantage de se comporter exactement comme Path.Combine

Règles lors de la combinaison d’URL avec l’URI

Pour éviter les comportements étranges, il existe une règle à suivre:

  • chemin (répertoire) doit se terminer par ‘/’. Si le chemin se termine sans ‘/’, la dernière partie est traitée comme un nom de fichier et sera concaténée lors de la tentative de combinaison avec la partie suivante de l’URL.
  • il y a 1 exception: l’adresse URL de base (sans les informations d’annuaire) ne doit pas se terminer par ‘/’
  • chemin partie ne doit pas commencer par ‘/’, si elle commence par ‘/’, toutes les informations relatives à l’URL existantes sont supprimées … ajout de chaîne.Le chemin de la partie vide supprimera également le répertoire relatif de l’URL!

Si vous suivez les règles ci-dessus, vous pouvez combiner les URL avec le code ci-dessous. Selon votre situation, vous pouvez append plusieurs parties “répertoires” à url …

  var pathParts = new ssortingng[] { destinationBaseUrl, destinationFolderUrl, fileName }; var destination = pathParts.Aggregate((left, right) => { if (ssortingng.IsNullOrWhiteSpace(right)) return left; return new Uri(new Uri(left), right).ToSsortingng(); }); 

Pourquoi ne pas simplement utiliser les éléments suivants?

 System.IO.Path.Combine(rootUrl, subPath).Replace(@"\", "/") 

Il y a un commentaire de Todd Menier ci – dessus que Flurl inclut un Url.Combine.

Plus de détails:

Url.Combine est fondamentalement un Path.Combine pour les URL, assurant un seul et unique séparateur entre les parties:

 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" 

Plus de suggestions … J’ai combiné tout ce qui précède:

  public static ssortingng UrlPathCombine(ssortingng path1, ssortingng path2) { path1 = path1.TrimEnd('/') + "/"; path2 = path2.TrimStart('/'); return Path.Combine(path1, path2) .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } [TestMethod] public void TestUrl() { const ssortingng P1 = "http://msdn.microsoft.com/slash/library//"; Assert.AreEqual("http://msdn.microsoft.com/slash/library/site.aspx", UrlPathCombine(P1, "//site.aspx")); var path = UrlPathCombine("Http://MyUrl.com/", "Images/Image.jpg"); Assert.AreEqual( "Http://MyUrl.com/Images/Image.jpg", path); } 

Eh bien, je ne fais que concaténer deux chaînes et j’utilise les expressions régulières pour effectuer le nettoyage.

  public class UriTool { public static Uri Join(ssortingng path1, ssortingng path2) { ssortingng url = path1 + "/" + path2; url = Regex.Replace(url, "(? 

Donc, vous pouvez utiliser comme ceci:

  ssortingng path1 = "http://someaddress.com/something/"; ssortingng path2 = "/another/address.html"; Uri joinedUri = UriTool.Join(path1, path2); // joinedUri.ToSsortingng() returns "http://someaddress.com/something/another/address.html" 

J'espère que cela peut être utile pour quelqu'un!

J’ai utilisé ce code pour résoudre le problème:

 ssortingng[] brokenBaseUrl = Context.Url.TrimEnd('/').Split('/'); ssortingng[] brokenRootFolderPath = RootFolderPath.Split('/'); for (int x = 0; x < brokenRootFolderPath.Length; x++) { //if url doesn't already contain member, append it to the end of the string with / in front if (!brokenBaseUrl.Contains(brokenRootFolderPath[x])) { if (x == 0) { RootLocationUrl = Context.Url.TrimEnd('/'); } else { RootLocationUrl += String.Format("/{0}", brokenRootFolderPath[x]); } } } 

Both of these work

  Uri final = new Uri(Regex.Replace(baseUrl + "/" + relativePath, "(? 

Ou

  Uri final =new Uri(ssortingng.Format("{0}/{1}", baseUrl.ToSsortingng().TrimEnd('/'), relativePath.ToSsortingng().TrimStart('/'))); 

c'est à dire

si

baseUrl = " http://tesrurl.test.com/Int18 "

et

relativePath = "To_Folder"

output = http://tesrurl.test.com/Int18/To_Folder

Some errors will appear for code below

  // if you use below code, some issues will be there in final uri Uri final= new Uri(baseUrl ,relativePath ); 

A simple one liner:

 public static ssortingng Combine(this ssortingng uri1, ssortingng uri2) => $"{uri1.TrimEnd('/')}/{uri2.TrimStart('/')}"; 

Inspired by @Matt Sharpe’s answer.

We use the following simple helper method to join arbitrary number of URL parts together:

 public static ssortingng JoinUrlParts(params ssortingng[] urlParts) { return ssortingng.Join("/", urlParts.Where(up => !ssortingng.IsNullOrEmpty(up)).ToList().Select(up => up.Trim('/')).ToArray()); } 

Note, that it doesn’t support ‘../../something/page.htm’-style relative URL-s!

I have to point out that Path.Combine appears to work for this also directly atleast on .NET4