Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 6 no exception thrown for undefined routes

I have a very basic asp.net MVC 6 app with basic routing, and I have a custom ErrorController to route errors to certain views.

I am expecting however that when the user types in an URL that does not exist, an exception is thrown (and I can handle it). However, no exception is thrown when I type in some random URL, I just get a blank page. I'm pretty sure this worked in similarly in MVC < 6.

The error handling itself works fine if I just throw an exception in a controller.

Startup.cs (partially)

public void Configure(IApplicationEnvironment appEnv, IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(HandleException);
    }
    app.UseStaticFiles();
    app.UseMvc(routes => MapRoutes(routes, appEnv));
}


private static void MapRoutes(IRouteBuilder routes, IApplicationEnvironment env)
{
    routes.MapRoute(
       name: "default",
       template: "{controller}/{action}/{id?}",
       defaults: new { controller = "main", action = "index" });          
}

private static void HandleException(IApplicationBuilder errorApp)
{
    #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
    errorApp.Run(async context => HandleErrorContext(context));
    #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
}

private static void HandleErrorContext(HttpContext context)
{
    var error = context.Features.Get<IExceptionHandlerFeature>();
    var exception = error.Error;
    if (exception == null)
    {
        context.Response.Redirect("../error/external");
    }
    else if (exception is ExpirationException)
    {
        context.Response.Redirect("../error/expired");
    }
    else if (exception is HttpException)
    {
        var httpException = exception as HttpException;
        int code = httpException.GetHttpCode();
        context.Response.Redirect("../error/external?code=" + code);
    }
    else
    {
        context.Response.Redirect("../error/external");
    }
}
like image 692
user2713516 Avatar asked Apr 13 '16 06:04

user2713516


2 Answers

Not a direct answer to my question, but I've got the workaround from https://stackoverflow.com/a/4833519/2713516 working. I'm still wondering why asp.net is not throwing a 404 though.

           routes.MapRoute(
                "PageNotFound",
                "{*catchall}",
                new { controller = "Home", action = "PageNotFound" }
                );
like image 136
user2713516 Avatar answered Sep 24 '22 15:09

user2713516


You can show user-friendly error pages by adding the StatusCodePages middleware to the pipeine. In Startup.cs

public void Configure(IApplicationEnvironment appEnv, IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseBrowserLink();
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/error/500");
        app.UseStatusCodePagesWithReExecute("/error/{0}");
    }
    app.UseStaticFiles();
    app.UseMvc(routes => MapRoutes(routes, appEnv));
}

The response body should be generated by re-executing the path /error/{0}.

[Route("[controller]")]
public class ErrorController : Controller
{            
     [HttpGet("{statusCode}")]
     public IActionResult Error(int statusCode)
     {     
           //switch (statusCode)
           //{  
           //    return different views...
           //}

           Response.StatusCode = statusCode;
           return View("Error", statusCode);
     }
}

Thats how you can show a 404 error page or any other error page.

like image 24
tmg Avatar answered Sep 25 '22 15:09

tmg