我有一个方法,尝试创建一个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);
}
Run Code Online (Sandbox Code Playgroud)
这种方法已经好几个月了.但是昨晚失败了.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)
Run Code Online (Sandbox Code Playgroud)
文档Uri.TryCreate(Uri, String, out Uri)说明返回值True是否成功,False否则,但是它对异常没有提及.但是,文档Uri.TryCreate(Uri, Uri, out Uri)说:
此方法构造URI,将其置于规范形式,并对其进行验证.如果发生未处理的异常,则此方法捕获它.如果要创建Uri并获取异常,请使用其中一个Uri构造函数.
堆栈跟踪显示异常被抛出Uri.TryCreate(Uri, Uri, out Uri),根据文档,这不应该发生.
这种情况非常罕见.几个月来我一直在使用该代码,通过它运行数十亿个URL,直到现在才遇到问题.不幸的是我不知道是什么组合导致了这个问题.我希望构建一个显示错误的测试用例.
这是一个已知的错误Uri.TryCreate,还是我错过了什么?
Jim*_*hel 20
我不愿意等待几个月的时间让我的代码再次遇到这种情况,我花了一些时间与ILDASM一起弄清楚TryCreate正在做什么,然后又花了一点时间来重现错误.
崩溃的原因Uri.TryCreate(Uri baseUri, Uri relativeUri, out Uri result)似乎是格式错误baseUri.例如,Uri构造函数允许以下内容:
Uri badUri = new Uri("mailto:test1@mischel.comtest2@mischel.com");
Run Code Online (Sandbox Code Playgroud)
根据RFC for mailto:URIs,不应该允许.虽然构造函数创建并返回一个Uri对象,但尝试访问(某些)其属性会抛出UriFormatException.例如,给定上面的代码,此行将抛出异常:
string badUriString = badUri.AbsoluteUri;
Run Code Online (Sandbox Code Playgroud)
我觉得很有趣的是,Uri该类似乎使用了两种不同的解析算法:一种在构造过程中使用,另一种在内部用于获取各个组件.
通过这个无效Uri,以TryCreate将导致我在原来的问题中描述的异常.该TryCreate方法检查baseUri参数null,但不是(不能,我会想象)否则验证它.必须假设,如果参数为非null,则传递的对象是完全初始化且有效的Uri实例.但是在构造结果的某些时候,会TryCreate尝试获取组件baseUri和异常.
我不能说我的程序实际上遇到了mailto:这种格式化的URL.我可以肯定地说,Uri在我的程序中,无效对象是导致崩溃的原因,因为我的程序中的异常堆栈跟踪与测试程序中的堆栈跟踪相匹配.简单地说,错误在Uri构造函数(以及TryCreate方法中)中,允许Uri创建无效.
您可以按照Microsoft Connect上的错误报告进行操作.