如果需要,向 URL 添加方案

要从一个字符串创建一个 Uri,你可以这样做:

Uri u = new Uri("example.com");

但问题是,如果字符串(像上面的那个)不包含协议,你会得到一个异常: “ Invalid URI: The format of the URI could not be determined.

To avoid the exception you should secure the string includes a protocol, like below:

Uri u = new Uri("http://example.com");

但是如果您将 URL 作为输入,那么如果缺少该协议,如何添加该协议呢?
I mean apart from some IndexOf/Substring manipulation?

优雅又快捷的东西?

34745 次浏览

你也可以使用 UriBuilder:

public static Uri GetUri(this string s)
{
return new UriBuilder(s).Uri;
}

来自 MSDN 的评论:

该构造函数使用 Uri 中指定的片段、主机、路径、端口、查询、 Scheme 和 Uri 属性来初始化 UriBuilder 类的新实例。

如果 uri 没有指定方案,方案默认为“ http:”。

My solution was for protocall-less urls to make sure they have protocal was regex :

Regex.Replace(s, @"^\/\/", "http://");

如果您只想添加方案,而不验证 URL,最快/最简单的方法是使用字符串查找,例如:

string url = "mydomain.com";
if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) url = "http://" + url;

更好的方法是使用 Uri也使用 TryCreate方法验证 URL:

string url = "mydomain.com";
Uri uri;
if ((Uri.TryCreate(url, UriKind.Absolute, out uri) || Uri.TryCreate("http://" + url, UriKind.Absolute, out uri)) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
{
// Use validated URI here
}

正如@JanDavidNarkiewicz 在评论中指出的,验证 Scheme是必要的,以防止在没有方案的情况下指定端口时出现无效方案,例如 mydomain.com:80

我们有一些特殊的情况,有一个遗产津贴输入的东西,如: Localhost: 8800或类似的。也就是说我们需要分析一下。我们构建了一个稍微复杂一点的 ParseUri 方法,它将指定 URI 的可能性分离得非常松散,但也捕捉到了人们指定非标准方案的时间(以及以 IP 长符号表示的主机,因为有时人们会这样做)

就像 UriBuilder 一样,如果没有指定任何参数,它将默认为 http 方案。如果指定了基本身份验证,并且密码仅由数字组成,则会出现问题。(请随意修复那个社区)

        private static Uri ParseUri(string uri)
{


if (uri.StartsWith("//"))
return new Uri("http:" + uri);
if (uri.StartsWith("://"))
return new Uri("http" + uri);


var m = System.Text.RegularExpressions.Regex.Match(uri, @"^([^\/]+):(\d+)(\/*)", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
if (m.Success)
{
var port = int.Parse(m.Groups[2].Value);
if (port <= 65535) //part2 is a port (65535 highest port number)
return new Uri("http://" + uri);
else if (port >= 16777217) //part2 is an ip long (16777217 first ip in long notation)
return new UriBuilder(uri).Uri;
else
throw new ArgumentOutOfRangeException("Invalid port or ip long, technically could be local network hostname, but someone needs to be hit on the head for that one");
}
else
return new Uri(uri);
}

有趣的是,尽管 UriUriBuilder在没有方案的情况下完全破坏了任何 URL,但是 WebProxy做得很好。

打电话给我:

new WebProxy(proxy.ProxyServer).Address

接受的答案是 http 而不是 https

namespace UrlHelper
{
using System;


public class UrlExtensions
{
public static Uri AddHttpsPrefixToString(string url)
{
if (string.IsNullOrWhiteSpace(url))
{
return null;
}


Uri uri;
try
{
uri = new UriBuilder(url) {
Scheme = Uri.UriSchemeHttps,
Port = -1 // default port for scheme
}.Uri;
}
catch
{
Console.WriteLine($"UrlExtensions.AddHttpsPrefixToString: Could not parse {url}");
return null;
}


return uri;
}
}
}

Use it like this: Var termsStringOrNull = UrlExtensions.AddHttpsPrefixToString (“ example.com”) ? . ToString ()