2

First i think i need to declare im a C# novice. I'm a JS and CSS dev with a fair bit of C so this is relatively new territory.

So what i have is an ASP.NET page where i'm making an AJAX request to the code behind, this is then making a request to a WebAPI service to download a zip file to the code-behind, the client does not need to receive the zip.

When i stick the code below into the Page_Load it all works fine and i get a byte array of the zip file. However when used in the method with [webmethod] attribute it hits the webAPI service but hangs. When the service returns nothing happens.

It locks up on line var res = client.GetAsync("/someURl").Result.

I have control over the WebAPI but as its returning fine and everything works fine when the attribute is not used i don't believe the issue is on that end. However i can post related code from there too if needed.

So i have two questions, firstly what on earth could be going on cause this behavior?

Second i've got a good handle on garbage collection is JS when working with closures etc but not here. Ive heard conflicting advice that i should and shouldn't use the using keyword on the HttpClient object. I'm not using a single client object throughout but creating a new one every time the ajax method is hit. So having using is right here isn't it?

EDIT: The delegate handler is adding some headers to the request to deal with authentication that's all.

[WebMethod]
public static bool SyncApplicant(int id)
{
  var serviceOne = DIFactory.Resolve<IServiceOne>();
  var settings= serviceOne .GetCompanySettings();

  try
  {
    var delegatingHandler = new WebApiDelegatingHandler((Guid)settings.AppId, settings.ApiKey);

    using (var client = HttpClientFactory.Create(delegatingHandler))
    {
      client.BaseAddress = new Uri(settings.ApiUrl);

      using (var res = client.GetAsync("/someURl").Result)
      {
        var d = res.Content.ReadAsByteArrayAsync().Result;
      }
    }
  }
  catch (Exception ex)
  {
    var x = ex;
    return false;
  }
  return true;
}

Thanks for any advice.

ste2425
  • 4,656
  • 2
  • 22
  • 37
  • You said it hits the method but it hangs. At which line does it hang? – Mikayil Abdullayev Jun 25 '16 at 21:15
  • @MikayilAbdullayev Sorry yes, don't know how i managed to forget that. Just updating now. – ste2425 Jun 25 '16 at 21:16
  • 1
    Calling `Task.Result` can cause deadlocks when synchronous and asynchronous methods are mixed. If going async you have to go async all the way. – Nkosi Jun 25 '16 at 21:23
  • @Nkosi But when using .Result it runs sync right? There is nothing async here is there? Also if that's the issue why would using `[WebMethod]` cause issues? Also for reasons to big to explain here im stuck using `.net 4` so can't go async with await etc? – ste2425 Jun 25 '16 at 21:26
  • It could be higher up in the pipeline. You may be aiming to be sync but what ever may be calling the method may be async. You say you cant use async/await but you are using `Task`. Am I missing something – Nkosi Jun 25 '16 at 21:27
  • @Nkosi I don't think your missing something but i certainly don't understand something. I'm using .net 4. It was my understanding that all this is .net 4 compliant and as such can't be async so i have to use `.Result`. I believed that to be async i has ti use .net 4.5 which would allow me to use `await` etc. I gather from your comment I'm way of there? Does the fact I'm using `Task` mean something im not grasping? – ste2425 Jun 25 '16 at 21:34
  • 2
    Doing some searches and finding that calling `.Result` or `.Wait` etc will cause `WebMethod` to block, but not finding out why as yet. Still looking – Nkosi Jun 25 '16 at 21:52
  • In the mean time, does the version of `HttpClient` you are using in that .Net4 service have non-async methods like `Get` and `ReadAsByteArray`? If they do then I suggest you use them instead. – Nkosi Jun 25 '16 at 22:01
  • @Nkosi Nope everything is `Get...Async`. I appreciate you taking the time to look into this. Am i wrong about not being able to use `async/await`? Could i make the `[webmethod]` async with my version of `.net` then i could just use async through and through right? – ste2425 Jun 25 '16 at 22:14
  • According to [this](http://stackoverflow.com/a/18623705/5233410) there is a possibility. But the outcome isn't too promising. – Nkosi Jun 25 '16 at 22:17
  • You should avoid using `.Result` whenever you can. Look [here](http://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c) for some alternatives. – DavidG Jun 25 '16 at 22:39

2 Answers2

1

Most probably, that deadlock is being cause by the ASP.NET synchronisation context (see details here]. You can try using ConfigureAwait(false); on the async call to avoid the async continuation trying to acquire the synchronisation context.

Pedro Felix
  • 1,056
  • 1
  • 8
  • 12
0

I don't know how you would use AJAX to let a user download a file in a browser. You can use a standard HTML link to a new .aspx page and put your Web API-calling code in Page_Load of the new page you're linking to.

Trey Mack
  • 4,215
  • 2
  • 25
  • 31
  • I'm making an assumption here. You want the user to receive the ZIP? Or is the web page going to use the data? – Trey Mack Jun 25 '16 at 22:26
  • thanks for your answer. Reading my question again it does sound like I'm attempting to download to the client. However I'm not ill update my question. I have found a solution thanks to everyone's input. Ill add it soon. – ste2425 Jun 27 '16 at 06:58