Foreground: I was investigating a bug in an ASP.NET Core project (targeting .NET 4.6.1, using assemblies from .Net Standard 1.4), that threw a MissingMethodException, although this in no way could be possible. Isolating the faulting method, I took the core of the code out to a separate unit test which also targets .NET 4.6.1.
The exception I receive, ThreadAbortException
, from the unit test is more or less this (it sometime various):
at System.Net.Http.WinHttpHandler.SetRequestHandleDecompressionOptions(SafeWinHttpHandle requestHandle)
at System.Net.Http.WinHttpHandler.SetRequestHandleOptions(WinHttpRequestState state)
at System.Net.Http.WinHttpHandler.<StartRequest>d__103.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.<FinishSendAsync>d__58.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Hub.Test.UnitTest1.<FetchUrlAsync>d__2.MoveNext()
The code in question for the abolve exception:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
//FetchUrl(); // works
var task = FetchUrlAsync(); // does not work
}
private void FetchUrl()
{
var handler = new HttpClientHandler();
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (var client = new HttpClient(handler, true))
{
var response = client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("https://github.com/dotnet/core"))).Result;
Trace.WriteLine("FetchUrl:" + response.StatusCode);
}
}
private async Task FetchUrlAsync()
{
try
{
var handler = new HttpClientHandler();
handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (var client = new HttpClient(handler, true))
{
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new Uri("https://github.com/dotnet/core")));
Trace.WriteLine("FetchUrlAsync: " + response.StatusCode);
}
}
catch (Exception e)
{
Trace.WriteLine(e);
throw;
}
}
}
Notice, that if I call FetchUrl() the code works. Yes, I know this became a sync method the moment i invoked result, but it is for demonstration purpose only.
However, the faulting method, FetchUrlAsync(), keeps throwing a ThreadAbortException.
Reason for SendAsync is, that the original implementation is a generic one using this one method for all the Http* work. The same error can be triggered with GetAsync and so forth.
I cannot figure out what I am doing wrong here, but I suspect this error to be a bug somewhere in the .NET CLR.
UPDATE
Although the unit test problem was solved (thank you), I still experienced issue in the ASP.NET Core web-api. From my understanding, .NET Standard 1.4 and .NET Framework 4.6.1 should be 1-1 compatible. This is why i believe there is a rare bug in the framework, although it seems unlikely.
The common denominator is System.Net.Http; and this varies bitwise from .NET Standard 1.4 and .NET Framework 4.6.1; and I tend to find out what the problem is and post the answer to others that might struggle with a similar problem.
Okay, to solve the original issue which was a
MissingMethodException
reported by one of the controllers.This error was ONLY triggered when using the async/await combination, which make sense because of the compiler generated code behind the scene.
Turns out, that one of the Nuget assemblies was using
System.Net.Http
from.NET Standard Library 1.6.1
and this assembly package targeted .NET Standard 1.4 (which, on paper, is 1-1 compatible with.NET Framework 4.6.1
).I then mingled with the solution, and was able to produce a
FileNotFoundException: Could not load file or assembly 'System.Net.Http, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
So far so good.
The problem became apparent when looking the bin/debug folder. There was no System.Net.Http.dll to be found, as it was using the built-in Framework assembly.
Aha.
VISUAL STUDIO 2015
Looking through the solution, only reference to the built-in Framework assembly was in the project.lock.json:
This reference came from
Microsoft.AspNetCore.Authentication/1.1.0
andMicrosoft.IdentityModel.Protocols/2.1.0
.Removing these two
frameworkAssemblies
entries made the solution work, as the "real" System.Net.Http.dll was now copied to the bin/debug folder.VISUAL STUDIO 2017
Almost the same problem; but since Microsoft has deprecated the use of project.json, the solution here is to modify (or add) an app.config file with the following content:
I am sorry guys for this long post; but there is a bug - and it might not be in the framework .. evidence might point to msbuild and/or different IDE's. I am just happy i found the error and was able to correct it.
I hope this rather long entry can help others with similar issues.
Happy coding!
The test method doesn't await for the asynchronous method to finish, so the test ends before
SendAsync
has a chance to return.You don't specify which testing framework you use but I assume it supports asynchronous tests. In this case change your test method to :
If it doesn't, you'll have to use
Wait()
: