代码之家  ›  专栏  ›  技术社区  ›  Jim Mischel

uri.trycreate throws UriFormatException?

  •  11
  • Jim Mischel  · 技术社区  · 15 年前

    我有一个方法尝试创建一个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 否则,但它对异常保持沉默。但是,文件 Uri.TryCreate(Uri, Uri, out Uri) 说:

    此方法构造uri,puts 以规范的形式,并验证 它。如果发生未处理的异常, 这个方法捕捉到它。如果你想 创建一个URI并获取异常使用 一个URI构造函数。

    堆栈跟踪显示引发了异常 uri.trycreate(uri,uri,out-uri) 根据文件,这是不应该发生的。

    这是非常罕见的情况。我已经用了几个月的代码,通过它运行了几十亿个URL,直到现在还没有遇到问题。不幸的是,我不知道是什么组合导致了这个问题。我希望构建一个显示错误的测试用例。

    这是已知的错误吗 Uri.TryCreate 或者我错过了什么?

    3 回复  |  直到 8 年前
        1
  •  18
  •   Jim Mischel    15 年前

    我不愿意再等几个月让我的代码再次遇到这种情况,所以我花了一些时间与ildasm一起研究 TryCreate 正在做,然后再花点时间想出一种重现错误的方法。

    撞车的原因 Uri.TryCreate(Uri baseUri, Uri relativeUri, out Uri result) 似乎格式不正确 baseUri . 例如, Uri 构造函数允许以下内容:

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

    根据mailto:uris的RFC,不应该允许这样做。尽管构造函数创建并返回 尿嘧啶尿路感染 对象,尝试访问(某些)其属性引发 UriFormatException .例如,给定上述代码,此行将引发异常:

    string badUriString = badUri.AbsoluteUri;
    

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

    传递这个无效 尿嘧啶尿路感染 三造 将导致我在原始问题中描述的异常。这个 三造 方法检查 巴苏里 参数用于 null ,但不能(我想不能)验证它。必须假定,如果参数为非空,则传递的对象是完全初始化的有效对象。 尿嘧啶尿路感染 实例。但在构建结果的某个时刻, 三造 尝试获取的组件 巴苏里 并抛出异常。

    我不能说我的程序实际上遇到了这样格式化的mailto:url。不过,我可以肯定地说,一个病人 尿嘧啶尿路感染 对象是导致程序崩溃的原因,这仅仅是因为我的程序中的异常堆栈跟踪与测试程序中的堆栈跟踪匹配。简单地说,bug在 尿嘧啶尿路感染 建造商(以及 三造 方法)允许无效的 尿嘧啶尿路感染 待创建。

    你可以跟着 bug report 在Microsoft Connect上。

        2
  •  3
  •   John Saunders    15 年前

    现在您知道它可能会失败,让我们了解更多信息:

    static public bool TryCreateCleanUri(Uri baseUri, string relstr, out Uri result)
    {
        try {
            if (!Uri.TryCreate(baseUri, relstr, out result))
            {
                return false;
            }
        }
        catch (UriFormatException ex) {
            throw new InalidOperationException(
                String.Format("Can create URI for base={0}, rel={1}", baseUri.ToString(), relstr),
                ex);
        }        
        return CleanupUri(result, out result);
    }
    
        3
  •  -1
  •   Seven    8 年前
     public static bool CheckUrlValid(string url)
        {
            Uri uriResult;
            bool result = Uri.TryCreate(url, UriKind.Absolute, out uriResult);
            if(result)
            {
                uriResult = new Uri(url);
                if (uriResult.Scheme == Uri.UriSchemeHttps || uriResult.Scheme == Uri.UriSchemeHttp)
                    return true;
            }
    
            return false;
        }