Anil D
Anil D

Reputation: 2009

Asp.net Core UseExceptionHandler not working POST request

In my .Net Core 2.0 application i have implemented UseExceptionHandler to handle exceptions globally. But redirection only works for GET method and POST method always return Status Code: 404; Not Found

Here is my Startup.cs Configure method

public void Configure(IApplicationBuilder app, IHostingEnvironment env, 
ILoggerFactory loggerFactory)
{
        app.UseCors(builder => builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials());
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseStatusCodePages();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
            app.UseExceptionHandler("/api/v1/Error");
        }
        else
        {
            app.UseExceptionHandler("/api/v1/Error");
        }

        app.UseMvc();
        app.UseSwagger();

        app.UseSwaggerUI(c =>
        {
            c.RoutePrefix = "docs";
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs");
            c.SwaggerEndpoint("/[]virtualDir]/swagger/v1/swagger.json", "V1 Docs");
        });
    }

And Error controller is

[Route("api/v1/[controller]")]
public class ErrorController : Controller
{
    private readonly IErrorLoggerService _errorLoggerService;

    public ErrorController(IErrorLoggerService errorLoggerService)
    {
        _errorLoggerService= errorLoggerService;
    }
    [HttpGet]
    public IActionResult Get()
    {
        // Get the details of the exception that occurred
        var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        var errorLog = new ErrorLog();

        if (exceptionFeature != null)
        {
            // Get which route the exception occurred at
            var routeWhereExceptionOccurred = exceptionFeature.Path;

            // Get the exception that occurred
            var exceptionThatOccurred = exceptionFeature.Error;

            // TODO: save exception in db
            errorLog = new ErrorLog
            {
                Application = routeWhereExceptionOccurred,
                Source = exceptionThatOccurred.Source,
                CreatedDate = DateTime.Now,
                Host = exceptionThatOccurred.InnerException?.ToString(),
                Type = exceptionThatOccurred.Message,
                Detail = exceptionThatOccurred.StackTrace
            };
            _errorLoggerService.Save(errorLog);
            return Json(errorLog);
        }

        return Json(errorLog);
    }
}

How to fix it?

Upvotes: 8

Views: 6216

Answers (3)

Brugner
Brugner

Reputation: 747

For those using Minimal APIs, you should use the Map method instead of MapGet. Here's an example.

public override void AddRoutes(IEndpointRouteBuilder app)
{
   app.Map(Routes.V1.Errors.Dev, (HttpContext context) =>
   {  
      var ex = context.Features.Get<IExceptionHandlerFeature>()!;

      return Results.Problem(detail: ex.Error.StackTrace, title: ex.Error.Message, statusCode: StatusCodes.Status500InternalServerError);

   }).ExcludeFromDescription();
}

Find more info here and here.

Upvotes: 0

AminRostami
AminRostami

Reputation: 2772

You should be able to remove the [HttpGet] from the Error method because it is what's causing the unnecessary restriction.

//[HttpGet]
public IActionResult Get()
{
    ....
}

Upvotes: 0

stukselbax
stukselbax

Reputation: 5935

According to the documentation:

In an MVC app, don't decorate the error handler action method with HTTP method attributes, such as HttpGet. Explicit verbs prevent some requests from reaching the method. Allow anonymous access to the method so that unauthenticated users are able to receive the error view.

So, your mistake is probably in HttpGet attribute. Don't use it, instead follow the documentation:

[Route("")]
[AllowAnonymous]
public IActionResult Get()
{
    ....
}

Upvotes: 6

Related Questions