0

I'm working on an ASP.NET MVC application which has an external reference like this:

public class AuthorizationApi : BaseApi
{
    public AuthorizationApi()
    {
        
    }
    public Configuration LogIn(string username, string password)
    {
        return LogIn(new Credentials(username, password));
    }   

    public Configuration LogIn(Credentials credentials)
    {
        AuthLoginWithHttpInfo(credentials);
        //missing code
        return configuration;
    }   
    
    protected ApiResponse<object> AuthLoginWithHttpInfo(Credentials credentials)
    {
        string path = "/auth/login";
        RestResponse response = (RestResponse)base.Configuration.ApiClient.CallApiAsync(path, Method.Post, ComposeEmptyQueryParams(), ComposeBody(credentials), ComposeAcceptHeaders(HeaderContentType.None), ComposeEmptyFormParams(), ComposeEmptyFileParams(), ComposeEmptyPathParams(), ComposeContentHeaders(HeaderContentType.Json | HeaderContentType.Xml | HeaderContentType.WwwForm)).Result;
        VerifyResponse(response, "AuthLogin");
        return GetResponseHeaders(response);
    }
}

Calling this code from the web application like so, hangs at LogIn and never returns:

AuthorizationApi api = new AuthorizationApi();
var config = api.LogIn(); //hangs, never returns

The specific line where it hangs is in the external library, where the .RESULT is added to the obvious async method. I have no control over it, and cannot change it:

RestResponse response = (RestResponse)base.Configuration.ApiClient.CallApiAsync(path, Method.Post, ComposeEmptyQueryParams(), ComposeBody(credentials), ComposeAcceptHeaders(HeaderContentType.None), ComposeEmptyFormParams(), ComposeEmptyFileParams(), ComposeEmptyPathParams(), ComposeContentHeaders(HeaderContentType.Json | HeaderContentType.Xml | HeaderContentType.WwwForm)).Result;

Calling from a new Task, sometimes works, sometimes doesn't:

AuthorizationApi api = new AuthorizationApi();
System.Threading.Tasks.Task loginTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
      configuration = authApi.LogIn();
});
loginTask.Wait(); //hangs here

How to properly call the LogIn() method from an ASP.NET MVC app?

mb14
  • 460
  • 4
  • 15
  • *How do I call mixed code (async and sync)?* You shouldn't, period ... you should chain async/await up to Controller – Selvin Jun 24 '22 at 13:24
  • I would consider that a bug in the external library. If you have the code for it, why can't you change it? If it's vendor supported, contact the vendor? If it's open source, submit a PR correcting the issue and/or fork it and correct the issue for your own needs? (Or contact the project and ask why it is the way it is and how to properly use it?) – David Jun 24 '22 at 13:26
  • Since it's a RESTClient lib, the repository is riddled with calls to the async method CallApiAsync() and then slapped a .Result at the end all inside a synchronous method. It would mean all code should be rewritten. I can fork and update but I doubt they will merge and if it's not maintained by the creator I am left with the forked correct version but without any updates. – mb14 Jun 24 '22 at 13:31
  • Make it all async! and await that call to `CallApiAsync` and remove the `.Result()`. You'll need to make all methods async returning `Task<>` – phuzi Jun 24 '22 at 13:32
  • 2
    @mb14: If the PR isn't accepted then *in most cases* that means either (1) there's a reason it's like this and the maintainer/community around the project can explain why and how to properly use it, or (2) the project isn't very actively maintained. (Or both.) If updates are few and far between then, if you even *need* updates, you can merge the master branch into your branch and re-build. But if the library is broken and/or unsupported then those are pretty strong cases to not use it, or to fork it and maintain your own version. – David Jun 24 '22 at 14:05
  • Perhaps start it on a new completely thread, that should remove the deadlock. Then await the continuation of that thread. Something like this method https://stackoverflow.com/questions/13741694/construct-task-from-waithandle-wait – Charlieface Jun 26 '22 at 15:37

0 Answers0