Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it wrong to use DelegateHandlers for ApiController Binding Errors? #420

Open
welldtr opened this issue May 24, 2017 · 0 comments
Open

Comments

@welldtr
Copy link

welldtr commented May 24, 2017

I was not able to log type binding errors into Elmah.

My ApiController method was:

        [HttpGet, Route("api/om/{NumOM}")]
        public OM ObterInfoOM(decimal NumOM)
        {
            ....
        }

And the wrong request was:
http//{host}/api/om/notanumberstringthatfailsmymethod

So, the controller was not able to bind the parameters of my method (logically), giving the following error response (not an exception, but 400 response)

{
    "Message": "The request is invalid.",
    "MessageDetail": "The parameters dictionary contains a null entry for parameter 'NumOM' of non-nullable type 'System.Decimal' for method 'selene.scanpack.infrastructure.Pack`1[selene.scanpack.domain.Entity.OM] ObterInfoOM(System.Decimal)' in 'selene.scanpack.WebApp.Controllers.OMController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}

But unfortunatelly elmah's webapi filter (ElmahRequestValidationErrorFilter) just catched "after binding" errors.

So I was using this implementation as workaround:

    /// <summary>
    /// MessageHandler to intercept WebApi calls that results in 400 status code and was not handled
    /// </summary>
    public class APIHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            try
            {
                return base.SendAsync(request, cancellationToken).ContinueWith((task) =>
                {
                    if (task.IsFaulted)
                    {
                        ErrorLog.GetDefault(HttpContext.Current).Log(new Error(task.Exception));
                    }
                    else if (task.Result.StatusCode == HttpStatusCode.BadRequest)
                    {
                        var error = task.Result.Content.ReadAsAsync<object>().Result as HttpError;

                        if (error != null)
                        {
                            HttpException exc = new HttpException((int)task.Result.StatusCode, error.MessageDetail);
                            ErrorLog.GetDefault(HttpContext.Current).Log(new Error(exc));
                        }
                    }

                    return task.Result;
                });

            }
            catch (Exception e)
            {
                TaskCompletionSource<HttpResponseMessage> tsc = new TaskCompletionSource<HttpResponseMessage>();
                ErrorLog.GetDefault(HttpContext.Current).Log(new Error(e));
                return tsc.Task;
            }
        }
    }

Is this implementation right?

@welldtr welldtr changed the title Is it wrong to use DelegateHandlers for ApiController Binding Errors? Is it wrong to use DelegateHandlers for ApiController Binding Errors? :question May 24, 2017
@welldtr welldtr changed the title Is it wrong to use DelegateHandlers for ApiController Binding Errors? :question Is it wrong to use DelegateHandlers for ApiController Binding Errors? May 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant