【问题标题】:How to build a Url?如何建立一个网址?
【发布时间】:2013-12-08 11:32:08
【问题描述】:

.NET 中是否有任何帮助类可以让我构建 Url?

例如,如果用户输入一个字符串:

stackoverflow.com

我尝试将其传递给HttpWebRequest

WebRequest.CreateHttp(url);

它会失败,因为它不是一个有效的 url(它没有前缀)。

我想要的是能够解析用户输入的部分网址:

Uri uri = new Uri(url);

然后修复缺失的部分:

if (uri.Port == 0)
   uri.Port = 3333;
if (uri.Scheme == "")
   uri.Scheme = "https";

.NET 是否有任何可用于解析和操作 Uri 的类?

UriBuilder 类无法完成这项工作

用户输入的值(例如stackoverflow.com:3333)有效;我只需要一堂课来把它分开。我尝试过使用UriBuilder 类:

UriBuilder uriBuilder = new UriBuilder("stackoverflow.com:3333");

很遗憾,UriBuilder 类无法处理 URI:

  • uriBuilder.Path = 3333
  • uriBuilder.Port = -1
  • uriBuidler.Scheme = stackoverflow.com

所以我需要一个能够理解host:port 的课程,这在it's not particularly http, but could be 时尤为重要。

奖金聊天

控制台应用程序。

从另一个问题

一些需要解析的 URL 示例:

  • server:8088
  • server:8088/func1
  • server:8088/func1/SubFunc1
  • http://server
  • http://server/func1
  • http://server/func/SubFunc1
  • http://server:8088
  • http://server:8088/func1
  • http://server:8088/func1/SubFunc1
  • magnet://server
  • magnet://server/func1
  • magnet://server/func/SubFunc1
  • magnet://server:8088
  • magnet://server:8088/func1
  • magnet://server:8088/func1/SubFunc1
  • http://[2001:db8::1]
  • http://[2001:db8::1]:80

Url 的格式为:

  foo://example.com:8042/over/there?name=ferret#nose
  \_/   \_________/ \__/\_________/\__________/ \__/
   |         |        |     |           |        |
scheme      host    port   path       query   fragment

奖金聊天

再次指出 UriBuilder 不起作用:

【问题讨论】:

  • 看起来UriBuilder 正确处理了这个问题——stackoverflow.com:3333 是一个 URI,其方案为 stackoverflow.com,路径为 3333。如果您想要以不同方式解析它,则必须指定您希望行为如何不同。您可能只能假设未知方案是主机名,或者编写自己的 UriParser
  • 问题是方案不是stackoverflow.com。只需询问 Lynx、Netscape Navigator、Internet Explorer、FireFox、Chrome、Edge 和 living standard。他们都意识到stackoverflow.com 是主机。我想要每个实际的现实世界解析器都能理解的 Uri 解析器。如果您建议我自己编写,那很好 - 请参阅 this question 我询问如何操作。理想情况下,该类已经存在于 FCL 中。

标签: c# .net


【解决方案1】:

如果您需要确保作为用户输入的某些字符串是有效的 url,您可以使用 Uri.TryCreate 方法:

Uri uri;
string someUrl = ...
if (!Uri.TryCreate(someUrl, UriKind.Absolute, out uri))
{
    // the someUrl string did not contain a valid url 
    // inform your users about that
}
else
{
    var request = WebRequest.Create(uri);
    // ... safely proceed with executing the request
}

另一方面,如果您想在 .NET 中构建 url,则可以使用专门为此目的设计的 UriBuilder 类。让我们举个例子。假设您要构建以下 url:http://example.com/path?foo=bar&baz=bazinga#some_fragment,其中 barbazinga 值来自用户:

string foo = ... coming from user input
string baz = ... coming from user input

var uriBuilder = new UriBuilder("http://example.com/path");
var parameters = HttpUtility.ParseQueryString(string.Empty);
parameters["foo"] = foo;
parameters["baz"] = baz;
uriBuilder.Query = parameters.ToString();
uriBuilder.Fragment = "some_fragment";

Uri finalUrl = uriBuilder.Uri;
var request = WebRequest.Create(finalUrl);
... safely proceed with executing the request

【讨论】:

  • HttpUtility.ParseQueryString 是获取内部HttpValueCollection 的一种偷偷摸摸的方式(这就是为什么它的.ToString() 会这样工作)。不确定使用内部框架类并依赖它们未记录的行为是否是一个好主意。这种洞察力归功于codereview.stackexchange.com/questions/91783/…
  • @JesseHufstetler - 我认为使用它是安全的,因为关于它的MSDN article 没有提及任何警告,并且有使用示例。
  • 请注意,UriBuilder 在stackoverflow.com:3389 上阻塞
【解决方案2】:

您可以使用UriBuilder 类。

var builder = new UriBuilder(url);
builder.Port = 3333
builder.Scheme = "https";

var result = builder.Uri;

【讨论】:

  • stackoverflow.com:3389 卡住了
【解决方案3】:

要有效,URI 需要具有方案组件。 “server:8088”不是有效的 URI。 “http://server:8088”是。见https://www.rfc-editor.org/rfc/rfc3986

【讨论】:

  • 当您输入stackoverflow.com:80 时,您的 Chrome 浏览器知道我的意思。什么 .NET 类能够解析 URI。
  • 实际上,server:8080 是一个完全有效的 URI,尽管可能没有人会理解您对服务器方案的意思。
  • 一直认为方案是 server:// 而不是 server:port 但思考基本的理解规则很有趣
  • @IanBoyd:有些浏览器只知道最常见的拼写错误是什么,并自行调整;-)
猜你喜欢
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 2013-01-03
  • 2020-09-29
  • 1970-01-01
  • 2023-03-26
  • 2010-09-19
相关资源
最近更新 更多