В С#, как вы проверяете, является ли путь виртуальным или нет?

Возможные виртуальные пути:

/folder1/folder2/image.jpg
~/folder1/folder2/image.jpg
folder1/folder2/image.jpg

Конкретный путь:

C:\folder1\folder2\image.jpg
D:\folder1\folder2\image.jpg
C:/folder1/folder2/image.jpg
C:/folder1\folder2/image.jpg

Как вы проверяете, является ли путь виртуальным или нет таким образом, который не подвержен сбою? Причина, по которой я спрашиваю, заключается в том, что, когда я использую Server.MapPath() по конкретному пути, он генерирует исключение. Однако то, что я передаю в Server.MapPath(), может быть любым из приведенных выше примеров, и я не знаю, что это такое до выполнения.

Ответы

Ответ 1

Это достаточно хорошо для меня:

protected string GetPath(string path)
{
    if (Path.IsPathRooted(path))
    {
        return path;
    }

    return Server.MapPath(path);
}

Ответ 2

Будет ли Path.GetFullPath(string path) соответствовать вашим потребностям? Вы можете использовать этот метод, а затем сравнить, изменился ли путь.

if (path == Path.GetFullPath(path))
{
    // This is the full path (no changes)
}
else
{
    // This is not the full path i.e. 'virtual' (changes)
}

Справка: http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx

Ответ 3

Я бы использовал Reflector, чтобы проверить, что делает Server.MapPath() и делает это.:)

Альтернативой может быть System.IO.Path.GetPathRoot() - если она возвращает null, то это относительный путь. Это немного хак, хотя, поскольку он ничего не знает о веб-путях, поэтому, если он работает, это будет работать по совпадению.

Ответ 4

Причина, по которой я спрашиваю, заключается в том, что, когда я использую Server.MapPath() по конкретному пути, он генерирует исключение

Вызывает ли это конкретное исключение для этого типа условия или бросает ли он общий? Если исключение специфично для условия, что входной путь был конкретным, я бы поймал это конкретное исключение в вашем коде. Даже если это общее исключение, я все равно поймаю это исключение, вы не сможете его декодировать, если его выбрали, потому что входной путь был виртуальным, но вы можете хотя бы написать свое собственное сообщение об исключении, включая уведомление о том, что это может быть вызвано по виртуальному пути ввода.

Я считаю, что это решение с наименьшей ошибкой, потому что вы полагаетесь на реализацию Server.MapPath(), чтобы определить условия, при которых он терпит неудачу, вместо того, чтобы пытаться создать избыточную оболочку, пытающуюся сделать то же самое. В будущем функциональность MapPath() может измениться, и она может фактически начать поддерживать виртуальные пути, тогда было бы глупо, что у вас есть код, чтобы фактически предотвратить это использование.

Ответ 5

Вы можете использовать следующее регулярное выражение...

^(?:[a-zA-Z]:(?:\\|/)|\\\\)

Если вы хотите, чтобы у вас всегда был сопоставленный путь. Вы можете использовать следующий однострочный...

VB.Net

my_path = If(Regex.IsMatch(my_path, "^(?:[a-zA-Z]:(?:\\|/)|\\\\)"), my_path, Server.MapPath(my_path))

С#

my_path = Regex.IsMatch(my_path, @"^(?:[a-zA-Z]:(?:\\|/)|\\\\)") ? my_path : Server.MapPath(my_path);

Это должно корректно работать с обычными путями дисков "c: \", а также с UNC-путями "\\".

Ответ 6

//Path.IsPathRooted( "/folder1/folder2/image.jpg" ); возвращает true

 public void Main()
        {
            var path = @"/folder1/folder2/image.jpg";
            //is valid path?
            if (!System.IO.Path.GetInvalidPathChars().Any(c => path.Contains(c.ToString())))
            {

                if (IsAbsolutePhysicalPath(path))
                {
                    // This is the full path
                }
                else
                {
                    // This is not the full path
                }

            }
        }
        private bool IsAbsolutePhysicalPath(string path)
        {
            if (path == null || path.Length < 3)
                return false;

            // e.g c:\foo
            if (path[1] == ':' && IsDirectorySeparatorChar(path[2]))
                return true;

            // e.g \\server\share\foo or //server/share/foo
            return IsUncSharePath(path);
        }
        private bool IsDirectorySeparatorChar(char ch)
        {
            return (ch == '\\' || ch == '/');
        }

        private bool IsUncSharePath(string path)
        {
            // e.g \\server\share\foo or //server/share/foo
            if (path.Length > 2 && IsDirectorySeparatorChar(path[0]) && IsDirectorySeparatorChar(path[1]))
                return true;
            return false;

        }

Справка: http://referencesource.microsoft.com/#System.Web/Util/UrlPath.cs,5e5cf20a50a858e2