c# - Uri.TryCreate 抛出 UriFormatException?

标签 c# .net

我有一个尝试创建 Uri 然后清理它的方法(删除片段、排除某些域和查询字符串模式等)。该方法如下所示:

static public bool TryCreateCleanUri(Uri baseUri, string relstr, out Uri result)
{
    if (!Uri.TryCreate(baseUri, relstr, out result))
    {
        return false;
    }
    return CleanupUri(result, out result);
}

此方法几个月来一直运行良好。但是昨晚失败了。 Uri.TryCreate() 抛出异常!这是堆栈跟踪:

ERROR: Unhandled exception caught.  Program terminating.
System.UriFormatException: Invalid URI: The hostname could not be parsed.
   at System.Uri.CreateHostStringHelper(String str, UInt16 idx, UInt16 end, Flags& flags, String& scopeId)
   at System.Uri.CreateHostString()
   at System.Uri.GetComponentsHelper(UriComponents uriComponents, UriFormat uriFormat)
   at System.Uri.CombineUri(Uri basePart, String relativePart, UriFormat uriFormat)
   at System.Uri.GetCombinedString(Uri baseUri, String relativeStr, Boolean dontEscape, String& result)
   at System.Uri.ResolveHelper(Uri baseUri, Uri relativeUri, String& newUriString, Boolean& userEscaped, UriFormatException& e)
   at System.Uri.TryCreate(Uri baseUri, Uri relativeUri, Uri& result)
   at System.Uri.TryCreate(Uri baseUri, String relativeUri, Uri& result)

Uri.TryCreate(Uri, String, out Uri) 的文档说,如果成功,返回值为 True,否则为 False,但它对异常(exception)情况保持沉默。但是,Uri.TryCreate(Uri, Uri, out Uri) 的文档说:

This method constructs the URI, puts it in canonical form, and validates it. If an unhandled exception occurs, this method catches it. If you want to create a Uri and get exceptions use one of the Uri constructors.

堆栈跟踪显示异常是在 Uri.TryCreate(Uri, Uri, out Uri) 中抛出的,根据文档,这不应该发生。

这种情况非常罕见。几个月来我一直在使用该代码,通过它运行了数十亿个 url,直到现在才遇到问题。不幸的是,我不知道是什么因素组合导致了这个问题。我希望构建一个显示错误的测试用例。

这是 Uri.TryCreate 中的已知错误,还是我遗漏了什么?

最佳答案

不愿意等待几个月让我的代码再次遇到这种情况,我花了一些时间使用 ILDASM 来弄清楚 TryCreate 在做什么,然后再花一点时间想出一个方法重现错误。

Uri.TryCreate(Uri baseUri, Uri relativeUri, out Uri result) 崩溃的原因似乎是格式错误的 baseUri。例如,Uri 构造函数允许以下内容:

Uri badUri = new Uri("mailto:test1@mischel.comtest2@mischel.com");

根据 mailto: URI 的 RFC,这是不允许的。尽管构造函数创建并返回一个 Uri 对象,但尝试访问(某些)它的属性会抛出 UriFormatException。例如,给定上面的代码,这一行将抛出一个异常:

string badUriString = badUri.AbsoluteUri;

我觉得很有趣的是,Uri 类似乎使用了两种不同的解析算法:一种在构造期间使用,另一种在内部用于获取各个组件。

将这个无效的 Uri 传递给 TryCreate 将导致我在原始问题中描述的异常。 TryCreate 方法检查 baseUri 参数是否为 null,但不会(我认为不能)以其他方式验证它。它必须假设,如果参数不为空,则传递的对象是一个完全初始化且有效的 Uri 实例。但是在构造结果的某个时刻,TryCreate 尝试获取 baseUri 的组件并抛出异常。

我不能说我的程序实际上遇到了这样格式化的 mailto: URL。不过,我可以肯定地说,无效的 Uri 对象是导致我的程序崩溃的原因,这仅仅是因为我程序的异常堆栈跟踪与测试程序的堆栈跟踪相匹配.简而言之,错误存在于允许创建无效的 UriUri 构造函数(以及 TryCreate 方法)中。

可以关注bug report在 Microsoft Connect 上。

关于c# - Uri.TryCreate 抛出 UriFormatException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1120283/

相关文章:

c# - 适用于 .NET 或 Delphi 的 ODETTE FTP (OFTP)

javascript - 将 C# 模型从 View 传递到 Javascript

c# - 如何将物体从碰撞点移动到物体末端 |统一

c# - ADO.Net DataTables 有索引吗?

c# - 如何将选择列表项添加到选择列表

.net - 在 dotnet 中查找缓慢/低效的方法调用

c# - Windows Mobile (C#) 的应用程序退出

c# - 调整控件大小时调整图像大小 C#

c# - Linq group by property 表现

.NET Visual Studio 生成错误 "another partial declaration of this type exists"