Есть ли метод, проверяющий, равны ли 2 URL-адреса, т.е. указывают ли они на одно и то же место. Я не говорю о двух URL-адресах с разными доменными именами, указывающими на один и тот же IP-адрес, но, например, о двух URL-адресах, которые указывают на одну и ту же страницу .aspx:
Равно этим:
- http://example.com/Products/Default.aspx
- http://example.com/Products/
- ~ / Товары / Default.aspx
- ~ / Товары /
Примечание / предположения
- Значения QueryString игнорируются
- ASP.NET (предпочтительный C #)
- Default.aspx - это страница по умолчанию
< Сильный > ---- UPDATE ----
Это очень грубый метод, который проверяет URL-адрес на соответствие текущему URL-адресу: я попытался создать новый Uri () как с локальным, так и с проверочным URL-адресами, но не знаю, что работает, и пошел по проспекту проверки строк. Реализация SiteMapProvider пропускает этот шаг, если URL-адрес начинается с «Http», поскольку это предполагает внешний URL-адрес. Поскольку у меня есть фреймворк SaaS, который всегда будет обеспечивать относительные пути (поскольку они могут находиться в разных поддоменах), проще разобрать вещи.
Есть комментарии по оптимизации? Думаю, для начала мы можем передать переменную, содержащую текущий URL? Не уверены в накладных расходах на многократный вызов HttpContext.Current.Request.Url.LocalPath?
/// <summary>
/// Assumes URL is relative aspx page or folder path
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static bool CurrentURLMatch(string url)
{
string localURL = HttpContext.Current.Request.Url.LocalPath;
if (HttpContext.Current.Request.Url.Host == "localhost")
{
localURL = localURL.Substring(localURL.IndexOf('/') + 1);
localURL = localURL.Substring(localURL.IndexOf('/'));
}
string compareURL = url.ToLower();
// Remove QueryString Values
if (localURL.Contains("?"))
{
localURL = localURL.Split('?')[0];
}
if (compareURL.Contains("?"))
{
compareURL = compareURL.Split('?')[0];
}
if (localURL.Contains("#"))
{
localURL = localURL.Split('#')[0];
}
if (compareURL.Contains("?"))
{
compareURL = compareURL.Split('#')[0];
}
// Prepare End of Local URL
if (!localURL.Contains("aspx"))
{
if (!localURL.EndsWith("/"))
{
localURL = String.Concat(localURL, "/");
}
}
// Prepare End of Compare URL
if (!compareURL.Contains("aspx"))
{
if (!compareURL.EndsWith("/"))
{
compareURL = String.Concat(localURL, "/");
}
}
if (localURL.EndsWith(@"/"))
{
localURL = String.Concat(localURL, "Default.aspx");
}
if (compareURL.EndsWith(@"/"))
{
compareURL = String.Concat(compareURL, "Default.aspx");
}
if (compareURL.Contains(@"//"))
{
compareURL = compareURL.Replace(@"//", String.Empty);
compareURL = compareURL.Substring(compareURL.IndexOf("/") + 1);
}
compareURL = compareURL.Replace("~", String.Empty);
if (localURL == compareURL)
{
return true;
}
return false;
}
6 ответов
Возможно, вам нужны методы нормализации URL. Они могут быть хорошей отправной точкой :)
После того, как вы нормализовали URL-адреса, вам просто нужно проверить, равны ли они (помните о своих предположениях, например, вы отбрасываете строку запроса).
Для записи, вот перевод http://en.wikipedia.org/wiki/URL%5Fnormalization на C #:
using System;
using System.Web;
namespace UrlNormalizationTest
{
public static class UrlNormalization
{
public static bool AreTheSameUrls(this string url1, string url2)
{
url1 = url1.NormalizeUrl();
url2 = url2.NormalizeUrl();
return url1.Equals(url2);
}
public static bool AreTheSameUrls(this Uri uri1, Uri uri2)
{
var url1 = uri1.NormalizeUrl();
var url2 = uri2.NormalizeUrl();
return url1.Equals(url2);
}
public static string[] DefaultDirectoryIndexes = new[]
{
"default.asp",
"default.aspx",
"index.htm",
"index.html",
"index.php"
};
public static string NormalizeUrl(this Uri uri)
{
var url = urlToLower(uri);
url = limitProtocols(url);
url = removeDefaultDirectoryIndexes(url);
url = removeTheFragment(url);
url = removeDuplicateSlashes(url);
url = addWww(url);
url = removeFeedburnerPart(url);
return removeTrailingSlashAndEmptyQuery(url);
}
public static string NormalizeUrl(this string url)
{
return NormalizeUrl(new Uri(url));
}
private static string removeFeedburnerPart(string url)
{
var idx = url.IndexOf("utm_source=", StringComparison.Ordinal);
return idx == -1 ? url : url.Substring(0, idx - 1);
}
private static string addWww(string url)
{
if (new Uri(url).Host.Split('.').Length == 2 && !url.Contains("://www."))
{
return url.Replace("://", "://www.");
}
return url;
}
private static string removeDuplicateSlashes(string url)
{
var path = new Uri(url).AbsolutePath;
return path.Contains("//") ? url.Replace(path, path.Replace("//", "/")) : url;
}
private static string limitProtocols(string url)
{
return new Uri(url).Scheme == "https" ? url.Replace("https://", "http://") : url;
}
private static string removeTheFragment(string url)
{
var fragment = new Uri(url).Fragment;
return string.IsNullOrWhiteSpace(fragment) ? url : url.Replace(fragment, string.Empty);
}
private static string urlToLower(Uri uri)
{
return HttpUtility.UrlDecode(uri.AbsoluteUri.ToLowerInvariant());
}
private static string removeTrailingSlashAndEmptyQuery(string url)
{
return url
.TrimEnd(new[] { '?' })
.TrimEnd(new[] { '/' });
}
private static string removeDefaultDirectoryIndexes(string url)
{
foreach (var index in DefaultDirectoryIndexes)
{
if (url.EndsWith(index))
{
url = url.TrimEnd(index.ToCharArray());
break;
}
}
return url;
}
}
}
Со следующими тестами:
using NUnit.Framework;
using UrlNormalizationTest;
namespace UrlNormalization.Tests
{
[TestFixture]
public class UnitTests
{
[Test]
public void Test1ConvertingTheSchemeAndHostToLowercase()
{
var url1 = "HTTP://www.Example.com/".NormalizeUrl();
var url2 = "http://www.example.com/".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test2CapitalizingLettersInEscapeSequences()
{
var url1 = "http://www.example.com/a%c2%b1b".NormalizeUrl();
var url2 = "http://www.example.com/a%C2%B1b".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test3DecodingPercentEncodedOctetsOfUnreservedCharacters()
{
var url1 = "http://www.example.com/%7Eusername/".NormalizeUrl();
var url2 = "http://www.example.com/~username/".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test4RemovingTheDefaultPort()
{
var url1 = "http://www.example.com:80/bar.html".NormalizeUrl();
var url2 = "http://www.example.com/bar.html".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test5AddingTrailing()
{
var url1 = "http://www.example.com/alice".NormalizeUrl();
var url2 = "http://www.example.com/alice/?".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test6RemovingDotSegments()
{
var url1 = "http://www.example.com/../a/b/../c/./d.html".NormalizeUrl();
var url2 = "http://www.example.com/a/c/d.html".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test7RemovingDirectoryIndex1()
{
var url1 = "http://www.example.com/default.asp".NormalizeUrl();
var url2 = "http://www.example.com/".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test7RemovingDirectoryIndex2()
{
var url1 = "http://www.example.com/default.asp?id=1".NormalizeUrl();
var url2 = "http://www.example.com/default.asp?id=1".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test7RemovingDirectoryIndex3()
{
var url1 = "http://www.example.com/a/index.html".NormalizeUrl();
var url2 = "http://www.example.com/a/".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test8RemovingTheFragment()
{
var url1 = "http://www.example.com/bar.html#section1".NormalizeUrl();
var url2 = "http://www.example.com/bar.html".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test9LimitingProtocols()
{
var url1 = "https://www.example.com/".NormalizeUrl();
var url2 = "http://www.example.com/".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test10RemovingDuplicateSlashes()
{
var url1 = "http://www.example.com/foo//bar.html".NormalizeUrl();
var url2 = "http://www.example.com/foo/bar.html".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test11AddWww()
{
var url1 = "http://example.com/".NormalizeUrl();
var url2 = "http://www.example.com".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
[Test]
public void Test12RemoveFeedburnerPart()
{
var url1 = "http://site.net/2013/02/firefox-19-released/?utm_source=rss&utm_medium=rss&utm_campaign=firefox-19-released".NormalizeUrl();
var url2 = "http://site.net/2013/02/firefox-19-released".NormalizeUrl();
Assert.AreEqual(url1, url2);
}
}
}
Вероятно, вы могли бы использовать класс Uri
для проверки отдельных частей URL-адресов после преобразования каждой в правильный формат.
// Create the URI objects
// TODO: Use the right constructor overloads,
// or do some processing beforehand to accomodate for the different scenarios
Uri uri1 = new Uri(url1);
Uri uri2 = new Uri(url2);
// There are overlaods for the constructor too
Uri uri3 = new Uri(url3, UriKind.Absolute);
// Check the correct properties
// TODO: Use the right properties...
if (uri1.AbsolutePath == uri2.AbsolutePath)
{
// Urls match
}
Может быть, этот учебник может быть вам полезен?
"... Вы хотите узнать, как обрабатывать идентичные URL-адреса в карте сайта (что запрещено стандартным SiteMapProvider) ..."
/// <summary>
/// SiteMap datasources cannot have duplicate Urls with the default provider.
/// This finds duplicate urls in your heirarchy and tricks the provider into treating
/// them correctly
/// </summary>
private void modifyDuplicateUrls()
{
StringCollection urls = new StringCollection();
string rowUrl = String.Empty;
uint duplicateCounter = 0;
string urlModifier = String.Empty;
foreach (DataTable dt in this.DataSource.Tables)
{
foreach (DataRow dr in dt.Rows)
{
rowUrl = (string)dr["Url"];
if (urls.Contains(rowUrl))
{
duplicateCounter++;
if (rowUrl.Contains("?"))
{
urlModifier = "&instance=" + duplicateCounter.ToString();
}
else
{
urlModifier = "?instance=" + duplicateCounter.ToString();
}
dr["Url"] = rowUrl + urlModifier;
}
else
{
urls.Add(rowUrl);
}
}
}
}
}
Как насчет того, чтобы увидеть, равен ли Server.MapPath для обоих URL-адресов? (при условии, что это приложение ASP.NET, а не ASP.NET MVC)
if (Server.MapPath(url1).ToLower() == Server.MapPath(url2).ToLower())
{
return true;
}
else
{
return false;
}
Честно говоря, просто загрузить URL-адреса и сравнить их HTML-содержимое?
Похожие вопросы
Связанные вопросы
Новые вопросы
c#
C # (произносится как «резкий») - это высокоуровневый, статически типизированный язык программирования с несколькими парадигмами, разработанный Microsoft. Код C # обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, включая, среди прочего, .NET Framework, .NET Core и Xamarin. Используйте этот тег для вопросов о коде, написанном на C # или в формальной спецификации C #.