I have added a few classes to send requests and handle responses from an external GraphQL web API, which use the GraphQL package from NuGet as well as HttpClient to connect to the API. The classes live in one project of my solution ("providers"). I have also added Test classes and methods to test the functionality of the service classes. The Tests all work as expected - results come back and they match the same queries made in Postman. Having success with the tests, I added references to the service classes to the main project which is an MVC web application in order to supplement user search capabilities - so calling a method from the same project as the Api helper classes within a controller in the MVC application. This is when I started having issues.
As an aside I did not have to add any of the GraphQL packages to the Test project, and it was able to work fine by just referencing the provider project that contains the api helper class. So it seems a bit like overkill in the first place that I had to add all that to the MVC project.
Initially, I was getting errors such as "ReadAsAsync doesn't exist" (this is a method of the System.Net.Http.HttpContent class I think?). This method was used in other classes that consume other external web services using HttpClient in the same project. In fact the method that was failing was nearly identical to ones in other classes that had been working for years at this point. So I thought it was strange it stopped working at this time. I eventually concluded it had something to do with all the dependencies added by adding the GraphQL nuget packages to the "providers" project.
I then added those same GraphQL packages to the MVC project to see if that resolved the issue. This added some issues where it couldn't find some System.IO libraries. I had seen this before in another project where I had to update the .NET version and the solution in that case was to remove the offending dependentAssembly entries in the web.config file. I did that here. Now, I load the web application in debug mode, and can click through to the page where the controller action to search using the new API class is located. The original search actions still work - I am able to get results using them. But the new API method does not. It does not throw an exception. It does not return results. The execution simply stops or seems to stop after the call to the API happens. The GraphQLHttpClient.SendQueryAsync just never comes back. It could just be that I'm not waiting long enough, but I gave it 10 minutes at one point for a query that runs in seconds in the test project, and also in seconds in postman. The application remains operational, though. I can still use other functions of the site after clicking on this.
I guess the question is - how can I find out what the problem is here? Or correct it in some way? I'm currently trying removing different dependentAssembly entries in the MVC project but that isn't really working out very well so far. Some of those entries are needed by the application. But not all of them.
** UPDATE ** I was able to work with some people on another site to resolve the issue. Basically I was calling:
public static GqlResponse GetGqlResponse(string name){
var gqlResponse = client.SendQueryAsync<GqlData>(gqlRequest).Result;
return gqlResponse;
}
In a method in a class in one project, from an MVC controller action in a different project. Because of this, it caused a deadlock.
public ActionResult Index (){
var gql = myotherproject.myclass.GetGqlResponse("moo");
return View(gql);
}
CodePudding user response:
The solution to this issue was to not try to make an asynchronous process completely synchronous. I changed the whole code pathway to be asynchronous.
public class MyGplClass{
public static async Task<GplResponse> GetGplResponse(string name){
// build the request, client, etc...
var gqlResponse = await client.SendQueryAsync<GqlData>(gqlRequest).ConfigureAwait(false);
// process response...
return gplResponse;
}
}
And in the MVC project:
public class MyController : BaseController{
public async Task<ActionResult> Index(){
var gqlr = await project2.MyGplClass.GetGplResponse("moo");
return View(gplr);
}
}
To reference for the future, hopefully this link stays alive: Don't Block on Async Code. But the gist of it is that because I was using the .Result property of the Task object created by calling the Async method, this was causing a deadlock within my Web Application (ASP.NET, .NET Framework), because of the way these sorts of web applications work. Because normally this problem had not happened for me, I was unprepared for it and I did not know what was happening when it happened this time. Hopefully this solution helps some people who have a similar problem as I stated in my question.