1

Background

Currently creating a web api which will need to talk to another web api which I have created. This problematic web api is out the box and the only changed I have mad is to enable cores and added two classes to it.

Problem

Currently this web api is executing all the way to my integration point however when it hits HttpResponseMessage hrm = await hc.GetAsync(requestUrl); it stops and does not give me an error. I tried putting a try catch on that function however it ignores that try catch aswell. The following code will show how I am building this web api.

Code

Controller

    [Route("api/WorkingPaperServices/CreateWorkingPaper")]
    public IHttpActionResult CreateWorkingPaper()
    {
        try
        {
            log4net.Config.XmlConfigurator.Configure();
            bool complete = WorkingPaperCreator.StartWPCreation().Result; 
            return Ok("Finished");
        }
        catch(Exception ex)
        {
            log4net.LogManager.GetLogger("EmailLogger").Error(JsonConvert.SerializeObject(ex));
            return ResponseMessage(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Not Laoded"));
        }              
    }

WorkingPaperCreator - class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace CWAppServices.Services
{
    public class WorkingPaperCreator
    {
        public static async Task<bool> StartWPCreation()
        {
            try
            {
                var testing = await IntergrationPoints.GetClientInformation();
                return true;
            }
            catch(Exception ex)
            {
                return false;
            }
        } 
    }
}

IntergrationPoints - class (Where my problem is)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;

namespace CWAppServices.Services
{
    public class IntergrationPoints
    {
        public static async Task<bool> GetClientInformation()
        {
            List<string> uniqueID = new List<string>();
            try
            {              
                string requestUrl = "http://appdev.tenant.com/caseware32/api/DataServices/GetAllClients";

                var action = new HttpMethod("GET");

                HttpClient hc = new HttpClient();

                HttpResponseMessage hrm = await hc.GetAsync(requestUrl);

                if (hrm.IsSuccessStatusCode)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                // TODO Log 
                return false;
            }
        }
    }
}
EasyE
  • 560
  • 5
  • 26
  • 1
    http://stackoverflow.com/questions/14526377/why-does-this-async-action-hang – ProgrammingLlama Mar 30 '17 at 12:54
  • 1
    `catch(Exception ex){return false;}` is *very* dangerous code. It guarantees that you'll never see the errors. Such code has a tendency to make it into production too. If you intend to add logging later, remove the `try/catch` block entirely or at least use `catch{throw;}` – Panagiotis Kanavos Mar 30 '17 at 13:03
  • 1
    Your problem is not in the HTTP call; it's where you [block on asynchronous code](http://nitoprograms.blogspot.com/2012/07/dont-block-on-async-code.html). – Stephen Cleary Mar 30 '17 at 13:04
  • 1
    Instead of calling `.Result` in the controller, use ` bool complete = await WorkingPaperCreator.StartWPCreation();`. You are *blocking* the synchronization context which means that the other `await` statements can't return to it. – Panagiotis Kanavos Mar 30 '17 at 13:05
  • PS - notice how you *forgot* to check the result in your controller? Even if the REST call fails, you'll still return a 200. You don't need the catch blocks, even for logging. The single log statement in the controller action is enough to log all the relevant information – Panagiotis Kanavos Mar 30 '17 at 13:07
  • @PanagiotisKanavos yes you are correct I added those try catch blocks just for debugging. – EasyE Mar 30 '17 at 13:17

1 Answers1

4

This blocking call leads to the problems: bool complete = WorkingPaperCreator.StartWPCreation().Result;. You get dead lock. To avoid it use aync\await everywhere (make your controller async as well) or add .ConfigureAwait(false) to all await calls.

  • Blocking in the controller action will waste the thread the OP was trying to save with `await`. `ConfigureAwait(false)` will remove the block but still waste the tread. It could also cause log4net to lose any attributes stored in the synchronization context – Panagiotis Kanavos Mar 30 '17 at 13:08