0

I have an application where I need to apply logic only badly formed requests before returning the response (status code:400).

To do so I have researched about error handling in ASP.NET Core, and based on this solution I tried the following:

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context /* other dependencies */)
    {
        try
        {
            await next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        if (context.Response.StatusCode == StatusCodes.Status400BadRequest)
        {
            //apply logic
        }
        var result = JsonConvert.SerializeObject(new { error = exception.Message });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)StatusCodes.Status400BadRequest;
        return context.Response.WriteAsync(result);
    }
}

and in Startup:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseMiddleware(typeof(ErrorHandlingMiddleware));
        app.UseMvc();
    }

Unfortunately the above solution did not work, when I debug I see that context.Response.StatusCode is always 200 even if the request is badly formed.

What am I missing here? any insights would be appreciated.

Community
  • 1
  • 1
Yahya Hussein
  • 8,767
  • 15
  • 58
  • 114
  • remove log options in your `appsettings.json` – Rudresha Parameshappa Aug 15 '18 at 14:52
  • What do you mean by a *badly formed request*? Are you sure an exception is being thrown? – Kirk Larkin Aug 15 '18 at 16:58
  • I mean the default response returned by ASP.Net when the request does not match the action parameter – Yahya Hussein Aug 15 '18 at 17:18
  • 1
    Then this is the wrong behavior. This will make every request that ends up in any exception return a 400 (bad-request) while it might be as well a 500 (internal server-error). Use exceptionfilter instead and define proper exceptions. You can use ModelState-Validation or FluentValidation. https://github.com/alsami/exception-filter-aspnet-core https://learn.microsoft.com/en-us/aspnet/core/mvc/models/validation?view=aspnetcore-2.1 https://github.com/JeremySkinner/FluentValidation – alsami Aug 16 '18 at 05:16
  • yes you are right, there is a defect in the logic but currently the main issue is that execution is never going to HandleExceptionAsync – Yahya Hussein Aug 16 '18 at 05:23
  • I am not so sure why this is happening I'd need to try. You will want to look for a proper solution anyway. – alsami Aug 16 '18 at 05:28
  • thanks, I have added a filter but again I am not going to OnActionExecuting in case of bad request, it only goes if the request is valid – Yahya Hussein Aug 16 '18 at 05:52
  • What do you want to do with `Status400BadRequest`? For `Status400BadRequest`, it will not throw exception. Otherwise, it will be captured by `ExceptionHandler`, try `Middleware` to check `Request code`. – Edward Aug 16 '18 at 06:42

1 Answers1

0

Try to check Response Status

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
        app.Use(async (context,next) => {
            await next();
            if (context.Response.StatusCode == StatusCodes.Status400BadRequest)
            {
                    var result = JsonConvert.SerializeObject(new { error = "Not Support" });
                    context.Response.ContentType = "application/json";
                    context.Response.StatusCode = (int)StatusCodes.Status400BadRequest;
                    await context.Response.WriteAsync(result);
            }
        });
Edward
  • 28,296
  • 11
  • 76
  • 121