C# 主机如何可能抛出UriFormatException?
消息框会显示一个地址,如 mailto:webmaster[@]somehost?webmaster 这显然是畸形的,但我不明白为什么它没有被第一个捕捉块捕捉到 它只能抛出InvalidOperationException。这是相当有问题的,因为这意味着我的应用程序可以在任何时候爆炸C# 主机如何可能抛出UriFormatException?,c#,.net,exception,url,uri,C#,.net,Exception,Url,Uri,消息框会显示一个地址,如 mailto:webmaster[@]somehost?webmaster 这显然是畸形的,但我不明白为什么它没有被第一个捕捉块捕捉到 它只能抛出InvalidOperationException。这是相当有问题的,因为这意味着我的应用程序可以在任何时候爆炸 [[snip]]如果深入研究Uri.Host属性real deep,它最终可以调用一个静态函数GetException,该函数针对无效Uri的不同情况返回UriFormatException对象。打印出您获得的完整
[[snip]]如果深入研究Uri.Host属性real deep,它最终可以调用一个静态函数GetException,该函数针对无效Uri的不同情况返回UriFormatException对象。打印出您获得的完整UriFormatException,并将其与Uri.GetException生成的比较。您可能会从中获得更多细节。首先,我想说,使用异常检查有效性并不是一个好主意,因为您可以使用方法。因此,您可以重写代码,而不依赖于抛出和捕获哪个异常 所以最好改变你的想法
foreach (var node in root.Find("a[href]"))
{
var href = node.Attributes["href"].Value;
Uri uri;
try
{
uri = new Uri(item.Value.Uri, href);
}
catch(UriFormatException)
{
continue;
}
// *snip*
try
{
if (_imageHosts.IsMatch(uri.Host)) // <--- problematic line
priority--;
}catch(UriFormatException)
{
MessageBox.Show(uri.OriginalString); // <--- gets displayed when I expected it wouldn't
continue;
}
// *snip*
}
到
但无论如何,这不是全额支票
至于你的问题,答案相对简单。假设格式不正确,您就错了:
mailto:webmaster[@]somehost?webmaster
URI就是这样的
{scheme name}:{hierarchy part}[?{query}][{fragment}]
显然对你的输入有效。您将使用mailto:scheme以资源的URI结束
当您尝试访问主机属性时,假定资源是Http,但默认情况下使用的mailto方案解析器无法解析主机组件的原始字符串,因此引发异常
因此,要正确填写支票,您必须稍微修改代码:
Uri uri;
if (!Uri.TryCreate(item.Value.Uri, href, out uri)) continue;
阅读一些关于
此处根据@Mark注释进行更新
我敢肯定,当我试图获取AbsoluteUri属性时,它也抛出了一个异常。为什么会失败呢 您无法通过方案检查,因为它将被邮寄到。下面是快速测试:
Uri uri;
if (!Uri.TryCreate(item.Value.Uri, href, out uri)) continue;
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) continue;
它以错误的计划结束。也许我没有正确地理解你
当您将href更改为:
var baseUri = new Uri("http://localhost");
const string href = "mailto: webmaster [ @ ] somehost ?webmaster";
Uri uri;
if (!Uri.TryCreate(baseUri,href, out uri))
{
Console.WriteLine("Can't create");
return;
}
if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
{
Console.WriteLine("Wrong scheme");
return;
}
Console.WriteLine("Testing uri: {0}", uri);
它正确地传递,并自动将uri转义到:
此外,您还可以使用所有uri组件
我试图在以下第一部分中解释的主要问题:
在我看来,您错误地将任何统一资源标识符视为基于https的url,但这是错误的。邮寄地址:webmaster@somehost.tst或gopher://gopher.hprc.utoronto.ca/ 或迈尔eshandler://something@还有一个可以成功解析的有效URI。看看
所以
Uri构造函数行为是预期的且正确
它尝试验证以下对象的传入URI:
UriSchemeFile-指定URI是指向文件的指针。
UriSchemeFtp-指定通过文件传输协议FTP访问URI。
UriSchemeGopher-指定通过Gopher协议访问URI。
UriSchemeHttp-指定通过超文本传输协议HTTP访问URI
UriSchemeHttps-指定通过安全超文本传输协议HTTPS访问URI。
UriSchemeMailto-指定URI是电子邮件地址,可通过简单网络邮件协议SNMP访问。
UriSchemeNews-指定URI是Internet新闻组,可通过网络新闻传输协议NNTP访问。
UriSchemeNntp-指定URI是Internet新闻组,可通过网络新闻传输协议NNTP访问
基本URI解析器在方案未知时使用,请参见
例如,基本上Uri.TryCreate和scheme会进行足够的检查,以获取可以传递到.NET HttpWebRequest的链接。你真的不需要检查它们的格式是否正确。如果链接是坏的、格式不正确的或不存在,你只需要在尝试请求它们时得到相应的HttpError
至于你的例子:
噗
它通过我的检查并成为:
您不需要检查它是否格式正确。只需执行基本检查并尝试请求。希望能有帮助
此外,字符串mailto:webmaster[@]somehost?webmaster的格式不正确。我的字面意思是,那根绳子,里面有愚蠢的s和所有的东西
此字符串的格式不正确,因为它包含排除的字符,所以它的格式不正确,但由于URI方案的一致性通用语法,它仍然可以被视为有效。请检查它在使用http:.创建时是如何转义的。根据Nick的回答:
const string href = "http: webmaster [ @ ] somehost ?webmaster";
我敢肯定,当我试图获取AbsoluteUri属性时,它也抛出了一个异常。为什么会失败?另外,字符串mailto:webmaster[@]somehost?webmaster的格式不正确。我的意思是,那个字符串,里面有愚蠢的[]s和所有东西。我想mailtos会有一个绝对的URI。。。我想不是。我会按照你当时的建议检查这个方案的!Uri是基于WebClient.DownloadData的,我基本上希望允许任何可以处理的。。。默认情况下,.NET Framework支持以http:开头的URI,
https:、ftp:、和文件:方案标识符。-我想我也应该包括这些。Uri.iswellFormedUrString根据RFC2396-统一资源标识符Uri:通用语法检查Uri一致性,如2.4.3所述。排除US-ASCII字符。必须在URI中转义空格。我也会更新我的答案。
const string href = "http: webmaster [ @ ] somehost ?webmaster";
private static readonly string[] SupportedSchmes = { Uri.UriSchemeHttp, Uri.UriSchemeHttps, Uri.UriSchemeFtp, Uri.UriSchemeFile };
private static bool TryCreateUri(string uriString, out Uri result)
{
return Uri.TryCreate(uriString, UriKind.Absolute, out result) && SupportedSchmes.Contains(result.Scheme);
}
private static bool TryCreateUri(Uri baseAddress, string relativeAddress, out Uri result)
{
return Uri.TryCreate(baseAddress, relativeAddress, out result) && SupportedSchmes.Contains(result.Scheme);
}