【问题标题】:Serialization and MD5 hashes failing after upgrading from .Net Core 3.1 to .Net 5从 .Net Core 3.1 升级到 .Net 5 后,序列化和 MD5 哈希失败
【发布时间】:2021-05-10 01:38:31
【问题描述】:

在将我的一个应用程序从 .Net Core 3.1 升级到 .Net 5 后,我注意到处理字节数组序列化和 MD5 哈希的代码部分出现了奇怪的故障。

代码在 .Net Core 3.1 中运行良好,但在升级到 .Net 5 后,我在 Linux 上运行时发现运行时出现问题。

具体而言,代码将对象散列为 GUID,如下所示:

        public Guid GenerateKey(string id, DateTime date1, DateTime? date2, string environment, string currencyCode, string ns, Dictionary<string, string> buildVersions)
        {
            var buildVersionString = string.Join(',', buildVersions.OrderBy(bv => bv.Key).Select(bv => $"{bv.Key}:{bv.Value}"));

            var key = new Key(id, date1, date2, environment, currencyCode, ns, buildVersionString); 

            var str = JsonConvert.SerializeObject(key);
            var bytes = Encoding.UTF8.GetBytes(str);

            var hashBytes = ComputeHash(bytes);

            return new Guid(hashBytes);
        }

        private byte[] ComputeHash(byte[] bytes)
        {
           using(var md5Hasher = MD5.Create())
           {
               return md5Hasher.ComputeHash(bytes);
           }     
        }

在 .Net 3.1 中,我能够使用简单的 ToDictionary 调用生成多个 Guid:

            var storedContents = new Content();

            storedContents.Keys = request.Ids.ToDictionary(
                                  k => k,
                                  v => keyProvider.GenerateKey(
                                  v,
                                  request.Date1,
                                  request.Date2,
                                  request.Environment,
                                  request.CurrencyCode,
                                  request.Namespace,
                                  request.BuildVersions)
            );

但在 .Net 5 中,这开始失败并出现以下错误。奇怪的是,它不会一直失败,而是在发出几个请求后相当可靠地失败。

Entry point was not found.
         at System.Collections.Generic.IEnumerable`1.GetEnumerator()
         at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source, Int32& length)
         at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
         at System.Linq.OrderedEnumerable`1.GetEnumerator()+MoveNext()
         at System.Linq.Enumerable.SelectIPartitionIterator`2.MoveNext()
         at System.String.JoinCore[T](Char* separator, Int32 separatorLength, IEnumerable`1 values)
         at POC.KeyProvider.GenerateKey(String id, DateTime date1, Nullable`1 date2, String environment, String currencyCode, String ns, Dictionary`2 buildVersions) in /home/tor/development/bug-repro/Api/POC/KeyProvider.cs:line 27
         at POC.StorageProvider.<>c__DisplayClass2_0.<GetContent>b__1(String v) in /home/tor/development/bug-repro/Api/POC/StorageProvider.cs:line 44
         at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](TSource[] source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
         at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
         at POC.StorageProvider.GetContent(MyRequest request) in /home/tor/development/bug-repro/Api/POC/StorageProvider.cs:line 42
         at Api.Controllers.TestController.Get() in /home/tor/development/bug-repro/Api/Controllers/TestController.cs:line 44
         at lambda_method7(Closure , Object , Object[] )

由于某种原因,我可以通过将 ToDictionary 转换为传统的 foreach 循环来使其工作。

            storedContents.Keys = new Dictionary<string, System.Guid>();

            foreach(var id in request.Ids)
            {
                var key = keyProvider.GenerateKey(
                       id,
                       request.Date1,
                       request.Date2,
                       request.Environment,
                       request.CurrencyCode,
                       request.Namespace,
                       request.BuildVersions
                    );

                storedContents.Keys.Add(id, key);
            }

似乎这两个版本都应该工作,并且在 .Net Core 3.1 中都可以工作,但在 .Net 5 中,字典方法停止工作。关于为什么这会在 Linux 上破坏 .Net 5 有什么想法吗? Windows 看起来不错,至少在我的开发人员机器上是本地的。

我在这里复制了这个问题:https://github.com/thelgevold/Net5-Error

注意:在此示例中,我使用的是 NewtonSoft 的 JsonConvert.SerializeObject。使用 MessagePack 进行序列化时,我看到了同样的问题。

【问题讨论】:

  • 看看Entry point was not found exception,据此确保迁移一切正确。
  • @TGH 我从问题中复制并粘贴了代码,但它无法按原样运行。它还不是minimal reproducible example
  • 您没有对属性进行排序。是什么告诉它在序列化Key 对象时每次都使用相同的顺序?您应该在序列化属性时对其进行排序,以确保每次都获得相同的哈希值。看看this
  • @Andy 我认为这很好,但我不认为这就是它失败的原因,在我的真实情况下,我实际上是在使用 MessagePack 和无合约解析器。我在那里看到了同样的问题,但决定使用 JSON 序列化程序显示示例以避免过多的外部依赖。

标签: c# .net-core .net-5 asp.net-core-5.0


【解决方案1】:

.Net 5.0.6 对此问题进行了修复。

参见 Github 问题https://github.com/dotnet/runtime/issues/52539

【讨论】:

    猜你喜欢
    • 2020-04-22
    • 2021-05-04
    • 2021-10-13
    • 2022-06-13
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 2018-08-03
    • 2021-05-14
    相关资源
    最近更新 更多