locked
Making a request synchronously RRS feed

  • Question

  • User-593456013 posted

    Hi everyone,

      Just started using Web API during preview 6 then my world got flipped upside when things shifted to the ASP.NET Web API!

      I wanted to get some opinions on some code I wrote usign Web API and if there were any ways I could improve it.  Basically, I don't think that I need any of the async stuff right now, and don't want to upgrade and wait for .NET 4.5 to be released.  I just want the code to run like it did during preview 6.

      So how does this code look to you guys/gals?  All it does is attempt to read a concrete type from the response stream.  For some reason, this code didn't work with the built in ReadAsAsync<T> code handling the serialization, so I instead used the Newtonsoft JSON library:

    public T GetDataFromService<T>()
    {
        using (var httpClient = new HttpClient())
        {
            T result = default(T);
            Task<HttpResponseMessage> responseTask = null;
    
            httpClient.GetAsync(_endpoint).ContinueWith((requestTask) =>
            {
                responseTask = requestTask;
                HttpResponseMessage response = requestTask.Result;
    
                response.EnsureSuccessStatusCode();
    
                response.Content.ReadAsStringAsync().ContinueWith((readTask) =>
                {
                    result = JsonConvert.DeserializeObject<T>(readTask.Result);
                });
            });
    
            // HACK: My version of the await keyword
            while (responseTask == null || !responseTask.IsCompleted || result == null) { }
    
            return result;
        }
    }
    Wednesday, February 22, 2012 8:30 AM

Answers

  • User1616639336 posted

    You can call .Result on a Task to wait for the result.

        using (var httpClient = new HttpClient())
        {
            var response = httpClient.GetAsync(_endpoint).Result;
            var result = response.Content.ReadAsStringAsync().Result;
    
            /*ToDo: Parse Json*/
    
            return result;
        }
    
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 22, 2012 8:48 AM

All replies

  • User1616639336 posted

    You can call .Result on a Task to wait for the result.

        using (var httpClient = new HttpClient())
        {
            var response = httpClient.GetAsync(_endpoint).Result;
            var result = response.Content.ReadAsStringAsync().Result;
    
            /*ToDo: Parse Json*/
    
            return result;
        }
    
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 22, 2012 8:48 AM
  • User-593456013 posted

    Nice!  I didn't realize you could get the Result immediately like that, which I assumes just blocks the current thread while waiting.  Awesome!

    This is the simple code that I've been looking for!

    Wednesday, February 22, 2012 9:10 AM
  • User-593456013 posted

    I shortened it up a little further, here is the complete generic method for a Get request:

    public T GetDataFromService<T>()
    {
        using (var httpClient = new HttpClient())
        {
            var response = httpClient.GetAsync(_endpoint).Result;
    
            return JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result);
        }
    }
    Wednesday, February 22, 2012 10:26 AM
  • User-797310475 posted
    While .Result works note that by using it you are losing all the perf benefits that Task provides. When you block a thread your server will not be able to use it to serve other requests meaning you lose scalability. I'd recommend returning Task<T> instead.
    Wednesday, February 22, 2012 10:54 AM
  • User-593456013 posted

    Yeah, thanks for the heads up.  That thought definitely crossed my mind, but this is for an internal business app, so there will never be the need to scale (I hope).  So for now I'll do it the hacky way, but then I'll definitely switch back to async when the .NET 4.5 comes out.

    Wednesday, February 22, 2012 4:40 PM
  • User-1598060341 posted

    if you like RX, (which I like), the following code fragment sample using Async as follows:

       GetData(myuri).ObserveOnDispatcher().Subscribe((o) =>
          {
            XmlSerializer xs = new XmlSerializer(typeof(List<T>));
            var data = xs.Deserialize(o.GetResponseStream()) as List<T>;
          });
    
        public static IObservable<WebResponse> GetData(Uri uri)
        {
            var request = (HttpWebRequest)WebRequestCreator.BrowserHttp.Create(uri);
            request.Method = "GET";
            request.Accept = "text/xml";
            var observer = Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse);
            return observer();
        }
    
    
    Thursday, February 23, 2012 1:10 AM
  • User1745037820 posted

    Marcind,

    Unless the complete pipeline (that is from Page or Handler onwards) is async, you won't get the perf benefits you're talking about as regards the Web Server using I/O completetion ports and being able to serve other requests because threads are freed up.

    From the OP's example, it looks like the method doing the service call it a synchronous call. So at some point during the Request-Response cycle, things are not async all the way. So you're point is moot.

    Tuesday, March 13, 2012 2:53 PM