4

So apparently HttpClient only allows for Asnyc calls?

Of course you can call ".Result" like so:

public ActionResult Index()
{


            var someImportantData = httpClient.ReadAsStringAsync().Result;  // Aparently I shouldn't do this according to the article.
            // or    
            var someImportantData = Task.Run(() => Client.PostAsync()).Result;

            Return View( new MyViewModel(someImportantData));
}

to make it synchronous but this is apparently very dangerous and should be avoided because it causes deadlocking as described here.

So what are my options for Synchronous requests? I'm I going to be force to use the older HttpWebRequest? In my specific MVC action I want the call to be synchronous as I don't want to return the page until I collect data from a restful api call.

RayLoveless
  • 19,880
  • 21
  • 76
  • 94
  • 3
    `I don't want to return the page until I collect data from a restful api.` How do async calls prevent you to do it? – L.B Aug 16 '17 at 22:23
  • @L.B I want my current thread to not proceed ( i.e: be synchronous ) and wait for the api call to return, then I can re-direct to the new page. – RayLoveless Aug 16 '17 at 22:32
  • `.Result` and `.Wait` do exactly this. What is your question now? (BTW: async fucntions can also be used like this. Goto first_comment;) – L.B Aug 16 '17 at 22:34
  • @L.B .Result causes deadlocks as described in the article. – RayLoveless Aug 16 '17 at 22:38
  • It *may* cause. Can you please post a real sample showing your problem? In this form, we are just discussing your *understanding* on this topic. It may be right or wrong. (For example you have an option *ConfigureAwait*) – L.B Aug 16 '17 at 22:40
  • @RayLoveless why dont you use Webclient or Webrequest instead of HttpClient because it seems that it is designed for asynchronous operations – hasan Aug 16 '17 at 22:45
  • 2
    There is no problem in using async/await in MVC. Can you show your case which doesn't work? – EZI Aug 16 '17 at 22:46
  • 3
    "...I don't want to return the page until" you will not return back to the page even with aysnc/await can you post your sample code? – Ankit Vijay Aug 16 '17 at 22:54
  • 2
    `Task.Run()` should also be avoided in ASP.Net. – Crowcoder Aug 16 '17 at 23:06

2 Answers2

3

If using async APIs then you should make your code async all the way. You can just as easily await the async members.

public async Task<ActionResult> Index() {
    var someImportantData = await httpClient.ReadAsStringAsync(...);
    return View(new MyViewModel(someImportantData));
}

I want my current thread to not proceed ( i.e: be synchronous ) and wait for the API call to return, then I can redirect to the new page.

The above call won't return the page until you collect data from the restful API call. Everything after the await will be back on the original thread.

.Result causes deadlocks as described in the article.

Yes. You sould avoid mixing async and blocking calls.

Brandon Minnick
  • 13,342
  • 15
  • 65
  • 123
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • RayLoveless, After reading the answer read my first comment again. @Nkosi +1 – L.B Aug 16 '17 at 23:09
  • @L.B. Yeah, my original code example wasn't very helpful. Thanks. This helps a bunch. Under the covers, i imagine the first thread must be listening for an interrupt so it can continue after the call returns( and not block) – RayLoveless Aug 17 '17 at 16:01
  • What if I have an interface where I get my data from and I want to change the implementation of that interface to get the data from a rest end point(the whole reason why to use an interface!!) ...without the support of a synchronous http calls I would have to change my interface signatures as well.. and all the signatures that depend on that interface. – RayLoveless Sep 22 '17 at 17:03
0

You do not really need to use .Result here. You can simply await for the result:

For example:

public async Task<ActionResult> Index()
{
      var someImportantData = await httpClient.ReadAsStringAsync().ConfigureAwait(false); 
      return View( new MyViewModel(someImportantData)); // This line will not be called until previous line is completed.
}

Use of ConfigureAwait(false) optional. If you are not using ASP.NET Core, then it can help a bit since you do not need to capture the context for server side code. Refer this link.

Ankit Vijay
  • 3,752
  • 4
  • 30
  • 53
  • Since OP wants to continue in a thread/context he lelt, `.ConfigureAwait(false);` is not an option. If we remove that code, what is different than other answer? – L.B Aug 16 '17 at 23:22
  • Do not see anything specific on that in the question now. May be the question edited. I have also mentioned it optional. But, do you think it could be an issue if context is changed for any scenario? – Ankit Vijay Aug 16 '17 at 23:35
  • `Do not see anything specific on that in the question now` Comments are also part of this question. – L.B Aug 16 '17 at 23:59