1

While using a custom message handler, I keep encountering the following error on the API server side:

API Controller:-

[RoutePrefix("errors")]
public class ErrorController : ApiController
{
    [HttpGet]
    [Route("{id}")]
    public IHttpActionResult GetClientEmailId(int id)
    {
        return this.Ok();
    }
}

Custom Message Handler:-

  public class ApiMessageHandler: DelegatingHandler
     {
    protected override async Task<HttpResponseMessage> 
     SendAsync(HttpRequestMessage request, CancellationToken 
       cancellationToken)
    {
        var logger = LogManager.GetLogger(this.GetType().FullName);
        if (logger.IsDebugEnabled)
        {
            var requestMessage = await 
               request.Content.ReadAsByteArrayAsync();

            var resTask = base.SendAsync(request, 
                           cancellationToken).ContinueWith(
                    t =>
                        {
                            if (t.Exception != null)
                            {
                                throw t.Exception;
                            }

                            return t.Result;
                    },
               cancellationToken);

            byte[] responseMessage;

            if (resTask.Result.IsSuccessStatusCode)
            {
                responseMessage = resTask.Result.Content != null
                                      ? await resTask.Result.Content.ReadAsByteArrayAsync()
                                      : Encoding.UTF8.GetBytes(resTask.Result.ReasonPhrase);
            }
            else
            {
                responseMessage = Encoding.UTF8.GetBytes(resTask.Result.ReasonPhrase);
            }

            await this.Log(request, requestMessage, resTask.Result, 
          responseMessage, logger);
            return resTask.Result;
        }

        var response = await base.SendAsync(request, cancellationToken);

        return response;
    }

when I called action method http://localhos:4200/errors/adf(pass string parameter instead of integer) then I got System.FormatException in Base.SendAsync method. The exception was thrown: 'System.FormatException' in mscorlib.dll Additional information: Input string was not in a correct format.

But this exception is not handled by GlobalException Handler.

It looks like a base.SendAsync method has swallowed this exception. How we can handle this exception and rethrow so GlobalException handler can handle this exception with proper message.

Thank you in advance.

  • When using async methods, you need to handle the error in an async way as the exception will effectively be swallowed by the thread it runs on. Check here; https://stackoverflow.com/questions/12980712/what-is-the-best-way-to-catch-exception-in-task – DiskJunky Oct 10 '17 at 10:31
  • 1
    As far as I can see, there is a mix of async/await and Task/ContinueWith approaches. Do you really need that ContinueWith() here and who is responsible for catching the exception thrown inside it? – Yury Schkatula Oct 10 '17 at 10:35

1 Answers1

2

The problem is that you are swallowing the exception yourself. You are not awaiting the task:

if (resTask.Result.IsSuccessStatusCode)

This is a bad practice in 99% of cases, since you are synchronously blocking the thread instead of asynchronously waiting for the result. Your code should be:

var result = await base.SendAsync(request, cancellationToken));
byte[] responseMessage;

if (result.IsSuccessStatusCode)

Since your method does not have a try-catch surrounding it, any exceptions will be thrown to the global handler as usual.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • Thank you for your response. Previously I was trying same code but it was also not working. it also not calling Global handler. but when we throw an explicitly same exception after base.SendAsync method then Global Handler is working perfectly. – user3352289 Oct 10 '17 at 11:31
  • @user3352289 That might be an issue of how the `DelegatingHandler` is declared then. – Camilo Terevinto Oct 10 '17 at 11:39