After upgrading one of my applications from .Net Core 3.1 to .Net 5 I am noticing weird failures in the parts of my code dealing with byte array serialization and MD5 hashes.
The code worked just fine in .Net Core 3.1, but after the upgrade to .Net 5 I am seeing issues at runtime when running on Linux.
Specifically the code hashes an object to a GUID as seen below:
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);
}
}
In .Net 3.1 I was able to generate multiple Guids using a simple ToDictionary call:
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)
);
But in .Net 5 this started failing with the error below. The weird part is that it doesn't fail all the time, but fails pretty reliably after making a few requests.
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[] )
For some reason I am able to get it to work by converting the ToDictionary to a traditional foreach loop.
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);
}
It seems like both versions should work, and did in .Net Core 3.1, but in .Net 5 the dictionary approach stopped working. Any thoughts on why this would break in .Net 5 on Linux? Windows seems fine, at least locally on my developer machine.
I have a reproduction of the issue here: https://github.com/thelgevold/Net5-Error
Note: In this example I am using NewtonSoft's JsonConvert.SerializeObject. I am seeing the same exact issue when using MessagePack for the serialization.