Як перевірити правильність рядка uri


82

Як перевірити, що рядок uri є дійсним (що ви можете подати його до конструктора Uri)?

Поки що у мене є лише таке, але зі зрозумілих причин я віддаю перевагу менш грубому способу:

    Boolean IsValidUri(String uri)
    {
        try
        {
            new Uri(uri);
            return true;
        }
        catch
        {
            return false;
        }
    }

Я спробував Uri.IsWellFormedUriString, але, здається, не подобається все, що можна кинути на конструктор. Наприклад:

String test = @"C:\File.txt";
Console.WriteLine("Uri.IsWellFormedUriString says: {0}", Uri.IsWellFormedUriString(test, UriKind.RelativeOrAbsolute));
Console.WriteLine("IsValidUri says: {0}", IsValidUri(test));

Результатом буде:

Uri.IsWellFormedUriString says: False
IsValidUri says: True

Оновлення / відповідь

Конструктор Uri використовує тип Absolute за замовчуванням. Це спричиняло розбіжності, коли я намагався використовувати Uri.TryCreate та конструктор. Ви отримуєте очікуваний результат, якщо ви відповідаєте UriKind як для конструктора, так і для TryCreate.

Відповіді:


82

Добре сформований URI передбачає відповідність певним RFC. Локальний шлях у вашому прикладі не відповідає їм. Детальніше читайте в IsWellFormedUriStringдокументації.

Помилковий результат цього методу не означає, що Uriклас не зможе проаналізувати введення. Хоча вхід URI може не відповідати RFC, він все одно може бути дійсним URI.

Оновлення : І щоб відповісти на ваше запитання - як показує документація Uri, існує статичний метод, TryCreateякий буде викликати саме те, що ви хочете, і повертати true або false (і фактичний Uriекземпляр, якщо true).


Питання: "Як перевірити, що рядок uri є дійсним (що ви можете подати його до конструктора Uri)?"
Мануель

1
TryCreate насправді не повідомляє вам, чи буде прийнятий конструктор рядком. Див. Оновлення.
Мануель

@ Мануель: це взагалі не має сенсу - результат TryCreateі Uriконструктор повинні бути однаковими - спробуйте передати те, UriKindщо ви робили раніше TryCreate.
BrokenGlass

1
Ти маєш рацію. Конструктор використовує тип Absolute за замовчуванням. Дякую.
Мануель

3
Згідно з джерелами .Net, метод IsWellFormedUriString містить виклик методу TryCreate плюс додаткові перевірки , тому я вважаю за краще використовувати метод IsWellFormedUriString як більш потужний для таких завдань.
Ігор Кустов

43

Оскільки прийнята відповідь не дає явного прикладу, ось деякий код для перевірки URI в C #:

Uri outUri;

if (Uri.TryCreate("ThisIsAnInvalidAbsoluteURI", UriKind.Absolute, out outUri)
   && (outUri.Scheme == Uri.UriSchemeHttp || outUri.Scheme == Uri.UriSchemeHttps))
{
    //Do something with your validated Absolute URI...
}

2
Не довіряйте функції Uri.TryCreate! Це також дозволить неправильні URL-адреси. Спробуйте "http: // http: // google.com/page" (видалити пробіли). Ця URL-адреса передає функцію TryCreate, але це неправильно.
No1Lives4Завжди

5
@ No1Lives4Ever Ви правильно вважаєте, що воно аналізує як дійсне те, що ви згадали, але це технічно не неправильно. Пояснення англійською мовою: використовуючи протокол http ( http: // ), підключіться до запису DNS для "http" (http: // ** http **), використовуючи явний (але пропущений) порт ( http **: * *) - отже, я прийму за замовчуванням протокол; ви надали порожню папку першого рівня ( http : ** // **), але я знаю, що ви мали на увазі;), а потім сегмент шляху "google.com" ( http: / ** google.com / **), а потім ресурс "сторінка" ( http://google.com ** сторінка **)
mlhDev

9

Припускаючи, що ми хочемо підтримувати лише абсолютні запити URI та HTTP, ось функція, яка робить те, що ви хочете:

public static bool IsValidURI(string uri)
{
    if (!Uri.IsWellFormedUriString(uri, UriKind.Absolute))
        return false;
    Uri tmp;
    if (!Uri.TryCreate(uri, UriKind.Absolute, out tmp))
        return false;
    return tmp.Scheme == Uri.UriSchemeHttp || tmp.Scheme == Uri.UriSchemeHttps;
}


1
Друга перевірка потрібна, щоб зробити можливою третю (і остаточну) перевірку. Без нього немає tmp. Перший крок у цьому випадку, мабуть, зайвий ...
Джо

1

У моєму випадку я просто хотів протестувати uri, я не хочу гальмувати програму, яка тестує uri.

Boolean IsValidUri(String uri){
  return Uri.IsWellFormedUriString(uri, UriKind.Absolute);
}

0

У вашому випадку аргумент uri - це абсолютний шлях, який посилається на розташування файлу, тому згідно з документом методу він повертає false. Зверніться до цього


Я використовую UriKind.RelativeOrAbsolute, тому це не має значення. У будь-якому випадку, це не працює з UriKind.Relative або UriKind.Absolute, тому там не везе.
Мануель
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.