Allan Xu
Allan Xu

Reputation: 9298

How to return HTTP 404

I am building an asp.net core Web API and I need to be able to hide some of the actions in a controller.

I use the following code to return HTTP 404 (Not Found):

[HttpGet]
public IActionResult Index()
{
    if(!_isEnabled)
    {
        return NotFound();
    }

However, in my browser I get this result:

{
    "type": "https://tools.ietf.org/html/rfc7231#section-6.5.4",
    "title": "Not Found",
    "status": 404,
    "traceId": "00-502319d62a6027718d2ee2cb3c9f263f-28de7bfdfb48f2d8-00"
}

I need to make the call as if the controller does not exists and the browser shows this:

enter image description here

How can a Controller returns a "real" HTTP 404 experience as if the controller dos not exists at that route?

Update 1

The answers return a JSON data and response code 404.

I am trying to do something different.

I am trying to hide the controller as if it doesn't exist for security reasons. I like the end user browser see above screenshot (Edge in my example)

Update 2

I changed to the following code:

[HttpGet]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult Index()
{
    if(!_isEnabled)
    {
        return StatusCode(StatusCodes.Status404NotFound); 
    }

and the controller returns the following result:

{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.4","title":"Not Found","status":404,"traceId":"00-3275026575270e11a4b1a5ab0817776a-a4777e626460faeb-00"}

The behavior is strange. Is it a new feature in aspnet code 6 ?

Update 3

Here is my middleware setup in the Program.c. It is plain oob setup:

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);

    builder.Logging.ClearProviders();
    builder.Logging.AddConsole();
    builder.Logging.AddAzureWebAppDiagnostics();

    // Add services to the container.
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

    builder.Services.AddControllers();
    // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();

    builder.Services.AddApplicationInsightsTelemetry();
        

    var app = builder.Build();

    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.UseSwagger();
        app.UseSwaggerUI();
    }

    app.UseHttpsRedirection();

    app.UseAuthentication();
    app.UseAuthorization();


    app.MapControllers();

    app.Run();
}

Upvotes: 0

Views: 1529

Answers (2)

Asky McAskface
Asky McAskface

Reputation: 176

Old question, but for future visitors, this will set the response body to null (and the browser will treat it as a 404):

return NotFound(null);

Upvotes: 0

Md Farid Uddin Kiron
Md Farid Uddin Kiron

Reputation: 22429

Solution For Update 1:

Middleware could be your savior here thus can be achived what you are trying to implement.

Controller:

        [ProducesResponseType(StatusCodes.Status404NotFound)]
        public IActionResult GetById(int id)
        {
         
           // return Ok(NotFound());
            return StatusCode(StatusCodes.Status404NotFound);
        }

Note: You can choose either of the status pattern.

Middleware:

public class CustomResponseMiddleware
    {
        private readonly RequestDelegate _next;
       
        public CustomResponseMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            if (httpContext.Response.StatusCode == 404)
            {
                httpContext.Response.Redirect("/WrongControllerName/WrongAction");
            }
            await _next(httpContext);
        }

    }

Note: As you can see, we are checking the controller status code and checking if any 404 decteced. Once the desired status code we will redirect a controller which doesn't exist at all that eventually generate the expected output.

Register Middleware In Program.cs:

app.UseMiddleware<CustomResponseMiddleware>();

Output:

enter image description here

Upvotes: 1

Related Questions