GUI Junkie
GUI Junkie

Reputation: 559

NotFound() doesn't seem to work as expected

I'm new to ASP.NET core, so I hope you bear with me on this one. This is similar to this unanswered question.

When I'm testing a brand new C# MVC project, and I enter a wrong URL, there's no info. Just a blank page.

To solve this, I have adapted startup.cs adding a UseStatusCodePagesWithReExecute() to return a static 404.html page. This works.

So far, so good.

Now, I am coding a basic login logic. For testing purposes, I'm calling return NotFound(); when the post parameters are missing. This doesn't return anything. I'm aware that 404 is not the correct response, but I have seen NotFound(); in the generated code and I think that's what's returning blank pages, so I want to solve that before moving on.

The app.UseDeveloperException(); doesn't seem to be called for this. I'm not sure how to test that.

Is there a way to override the NotFound(); behavior to get a 404.html somehow?

This is the Tutorial I have used to set up my project.

Edit: Based on the comments of Alexander Powolozki, I have replaced NotFound(); with Redirect("~/404.html");. This works.

// Wherever you want to return your standard 404 page
return Redirect("Home/StatusCode?code=404");


public class HomeController : Controller
{
    // This method allows for other status codes as well
    public IActionResult StatusCode(int? code)
    {
        // This method is invoked by Startup.cs >>> app.UseStatusCodePagesWithReExecute("/Home/StatusCode", "?code={0}");
        if (code.HasValue)
        {
            // here is the trick
            this.HttpContext.Response.StatusCode = code.Value;
        }

        //return a static file.
        try
        {
            return File("~/" + code + ".html", "text/html");
        }
        catch (FileNotFoundException)
        {
            return Redirect("Home/StatusCode?code=404");
        }
    }
}

Upvotes: 0

Views: 1507

Answers (2)

GUI Junkie
GUI Junkie

Reputation: 559

After working a little more on the question, I have found a way to do it without using Redirect as suggested by Alexander Powolozki.

I have created a Utilities class to return the 404 code and 404.html.

In the HomeController, I have the StatusCode IActionResult.

// This method is invoked by Startup.cs >>> app.UseStatusCodePagesWithReExecute("/Home/StatusCode", "?code={0}");
public IActionResult StatusCode(int? code)
{
    // Call the static method
    return Utilities.StatusCode(code: code.Value, this.HttpContext);
}

In Models, I've added a Utilities.cs.

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using System.IO;

namespace MediaMgt.Models
{
    public static class Utilities
    {
        public static IActionResult StatusCode(int code, HttpContext httpContext)
        {
            // here is the trick
            httpContext.Response.StatusCode = code;

            //return a static file.
            try
            {
                return new VirtualFileResult("~/" + code + ".html", "text/html");
            }
            catch (FileNotFoundException)
            {
                httpContext.Response.StatusCode = 404;
                return new VirtualFileResult("~/404.html", "text/html");
            }
        }
    }
}

The reason to do it like this instead of using the Redirect method is to avoid a round-trip to the client with a 302. This method returns both the 404 error code and a standard 404.html.

You can easily add more functionality from here on.

Upvotes: 1

Alexander Powolozki
Alexander Powolozki

Reputation: 675

The first option with the 404.html is invoked when a request can't be processed because of missed routes to ressources like static content or controllers, in this case the preconfigured 404.html is returned. In the second case a routing was successfull and all the remaining processing is done by the logic e.g. the determined and invoked controller, so it's up to you to redirect to your created 404.html.

Upvotes: 1

Related Questions