Path.Combine per URL?

Path.Combine è utile, ma esiste una funzione simile nel framework .NET per gli URL ?

Sto cercando una syntax come questa:

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

che restituirebbe:

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

Uri ha un costruttore che dovrebbe fare questo per te: new Uri(Uri baseUri, string relativeUri)

Ecco un esempio:

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

Usa 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); } 

Sarà di ritorno:

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

Questa potrebbe essere una soluzione opportunamente semplice:

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

Ci sono già alcune grandi risposte qui. In base al suggerimento di mdsharpe, ecco un metodo di estensione che può essere facilmente utilizzato quando si desidera gestire istanze di 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('/')))); } } 

E esempio di utilizzo:

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

Ciò produrrà http://example.com/subpath/part1/part2

Questa domanda ha delle risposte fantastiche e molto votate!

La risposta di Ryan Cook è vicina a quello che sto cercando e potrebbe essere più appropriata per altri sviluppatori. Tuttavia, aggiunge http: // all’inizio della stringa e in generale fa un po ‘più di formattazione di quello che sto cercando.

Inoltre, per i miei casi d’uso, la risoluzione dei percorsi relativi non è importante.

La risposta di mdsharp contiene anche il seme di una buona idea, sebbene quell’attuale implementazione necessitasse di qualche altro dettaglio per essere completata. Questo è un tentativo di estrapolarlo (e sto usando questo in produzione):

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 

Questo codice supera il test seguente, che si verifica in VB:

  Public Sub UrlCombineTest() Dim target As StringHelpers = New StringHelpers() Assert.IsTrue(target.UrlCombine("test1", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("test1/", "/test2") = "test1/test2") Assert.IsTrue(target.UrlCombine("/test1/", "/test2/") = "/test1/test2/") Assert.IsTrue(target.UrlCombine("", "/test2/") = "/test2/") Assert.IsTrue(target.UrlCombine("/test1/", "") = "/test1/") End Sub 

In base all’URL di esempio che hai fornito, assumerò che desideri combinare gli URL relativi al tuo sito.

Sulla base di questa ipotesi proporrò questa soluzione come la risposta più appropriata alla tua domanda che era: “Path.Combine è a portata di mano, esiste una funzione simile nel framework per gli URL?”

Dal momento che c’è una funzione simile nel framework per URL che propongo il corretto è: metodo “VirtualPathUtility.Combine”. Ecco il link di riferimento MSDN: VirtualPathUtility.Combine Method

C’è un avvertimento: credo che funzioni solo per gli URL relativi al tuo sito (cioè, non puoi usarlo per generare collegamenti a un altro sito Web. Per esempio var url = VirtualPathUtility.Combine("www.google.com", "accounts/widgets"); ).

Path.Combine non funziona per me perché possono esistere caratteri come “|” in argomenti QueryString e quindi l’Url, che genererà ArgumentException.

Ho provato per la prima volta il nuovo approccio Uri (Uri baseUri, stringa relativaUri), che mi ha fallito a causa di Uri come http://www.mediawiki.org/wiki/Special:SpecialPages :

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

risulterà in Special: SpecialPages, a causa dei due punti dopo Special che denota uno schema.

Quindi alla fine ho dovuto prendere il percorso mdsharpe / Brian MacKays e l’ho sviluppato un po ‘oltre per lavorare con più parti uri:

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

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

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

Ho appena messo insieme un piccolo metodo di estensione

 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('/'); } 

può essere usato in questo modo:

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

Esempio spiritoso, Ryan, per finire con un link alla funzione. Molto bene.

Una raccomandazione Brian: se si avvolge questo codice in una funzione, è ansible che si desideri utilizzare un UriBuilder per racchiudere l’URL di base prima della chiamata TryCreate.

In caso contrario, l’URL di base DEVE includere lo schema (dove UriBuilder assumerà http: //). Solo un pensiero:

 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"); } 

Combinare più parti di un URL potrebbe essere un po ‘complicato. È ansible utilizzare il costruttore di parametri 2 Uri(baseUri, relativeUri) oppure è ansible utilizzare la funzione di utilità Uri.TryCreate() . In entrambi i casi, potresti finire per restituire un risultato errato perché questi metodi continuano a troncare le parti relative al primo parametro baseUri , ad esempio da qualcosa come http://google.com/some/thing a http://google.com

Per poter combinare più parti in un url finale, puoi copiare le 2 funzioni seguenti:

  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; } 

Il codice completo con test unitari per dimostrare l’utilizzo è disponibile su https://uricombine.codeplex.com/SourceControl/latest#UriCombine/Uri.cs

Ho dei test unitari per coprire i 3 casi più comuni: inserisci la descrizione dell'immagine qui

Questa risposta probabilmente si è persa in tutte le risposte sopra, ma ho trovato che UriBuilder funzionato molto bene per questo genere di cose.

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

Vedi Classe UriBuilder – MSDN per ulteriori costruttori e documentazione.

So che questo è stato risposto, ma un modo semplice per combinarli e assicurarsi che sia sempre corretto è ..

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

Ecco il metodo Microsoft (OfficeDev PnP) UrlUtility.Combine :

  const char PATH_DELIMITER = '/'; ///  /// Combines a path and a relative path. ///  ///  ///  ///  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); } 

Fonte: GitHub

La mia soluzione generica:

 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; } 

so che sono in ritardo per la festa, ma ho creato questa funzione che renderà la vita più facile

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

funziona per URL e percorsi normali

Uso:

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

So che questa domanda ha una buona risposta, tuttavia trovo questo utile in quanto ha le seguenti caratteristiche

  • Getti su spazio nullo o bianco
  • Classe statica che imita più da vicino System.Io.Path
  • Prende parametro params per più segmenti Url

Nota: l’URL del nome class potrebbe essere modificato, poiché esiste una class di sistema System.Security.Policy.Url

Classe

 public static class Url { private static string InternalCombine(string source, string dest) { // If the source is null or white space retune the dest only if (string.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 (string.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 string.Format("{0}/{1}", source, dest); // return $"{source}/{dest}"; // c# 6.0 string interpolation } public static string Combine(string source, params string[] args) { return args.Aggregate(source, InternalCombine); } } 

risultati

 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 

Cosa ne pensi di questo?

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

Ecco il mio approccio e lo userò anche per me stesso

 public static string UrlCombine(string part1, string part2) { string newPart1 = string.Empty; string newPart2 = string.Empty; string seprator = "/"; // if either part1 or part 2 is empty, // we don't need to combine with seprator if (string.IsNullOrEmpty(part1) || string.IsNullOrEmpty(part2)) { seprator = 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, seprator, newPart2); } 
  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); } 

Ha i vantaggi di comportarsi esattamente come Path.Combine

Regole durante la combinazione di URL con URI

Per evitare comportamenti strani c’è una regola da seguire:

  • percorso (directory) deve terminare con ‘/’. se il percorso termina senza ‘/’, l’ultima parte viene trattata come un nome di file e verrà concatenata quando si cerca di combinare con la prossima parte url.
  • c’è 1 eccezione: l’indirizzo URL di base (senza informazioni sulla directory) non deve terminare con ‘/’
  • la parte del percorso non deve iniziare con ‘/’, se inizia con ‘/’ ogni informazione relativa esistente dall’URL viene eliminata … aggiungendo string. Il percorso della parte vuota rimuoverà anche la relativa directory dall’URL!

Se si seguono le regole di cui sopra, è ansible combinare gli URL con il seguente codice. A seconda della situazione, puoi aggiungere più parti “directory” all’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(); }); 

Perché non usare solo quanto segue

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

C’è un commento di Todd Menier sopra che Flurl include un Url.Combine.

Più dettagli:

Url.Combine è fondamentalmente un Path.Combine per URL, che garantisce un solo carattere separatore tra le parti:

 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" 

Altri suggerimenti … Ho combinato tutto quanto sopra:

  public static string UrlPathCombine(string path1, string path2) { path1 = path1.TrimEnd('/') + "/"; path2 = path2.TrimStart('/'); return Path.Combine(path1, path2) .Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } [TestMethod] public void TestUrl() { const string 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); } 

Bene, ho solo concatenato due stringhe e uso le espressioni regolari per eseguire la parte di pulizia.

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

Quindi, puoi usare in questo modo:

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

Spero che possa essere utile per qualcuno!

Ho usato questo codice per risolvere il problema:

 string[] brokenBaseUrl = Context.Url.TrimEnd('/').Split('/'); string[] 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]); } } } 

Entrambi questi lavori

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

O

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

vale a dire

Se

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

e

relativePath = "To_Folder"

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

Alcuni errori appariranno per il codice qui sotto

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

Una semplice fodera:

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

Ispirato alla risposta di @Matt Sharpe.

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

 public static string JoinUrlParts(params string[] urlParts) { return string.Join("/", urlParts.Where(up => !string.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