14

I need to return 404 on wrong api call so I can create proper response to user on client side (Angular 5). Currently backend returns status code 200 and index.html, and that results in json parse error on frontend.

I created new web project with ASP.NET Core 2.1 and Angular template project. Here's the link to published version of that template. I didn't change template code at all, I just published that on azure as it is. (In dev mode I get 404 error as expected).

As mentioned here default behaviour should be 404.

Here is the Startup.cs, and here SampleDataController.cs.

I thought of using something like this in Startup.cs:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action}/{id?}");
        });

        app.MapWhen(x => x.Request.Path.Value.Contains("/api"), builder =>
        {
            builder.UseMvc(routes =>
            {
                routes.MapSpaFallbackRoute(
                    name: "spa-fallback",
                    defaults: new { controller = "Home", action = "Error" });
            });
        });

And in HomeController.cs:

    public IActionResult Error()
    {
        return NotFound();
    }

But that seems wrong although it works.

2
  • Ever figure this out? Commented Aug 13, 2019 at 2:56
  • No, I am still using the described "solution". Commented Aug 14, 2019 at 6:31

2 Answers 2

21

Note: Based on your links, I assume you are using the app.UseSpa() middleware.

The route middleware is executed in order, and if the request never finds a controller a 404 status is returned. The UseSpa middlware is a catch-all, and any request that gets to that point will always have the default SPA page returned. This means any request to a route that hasn't yet found a controller will always return the default SPA page, and not throw a 404.

What you will want to do is only call UseSpa() if the route is not prefixed with /api. Which essentially lets any requests that start with/api skip past that point.

Instead of:

app.UseSpa(spa =>
{
    //[Snip]
});

Use:

app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
{
    builder.UseSpa(spa =>
    {
        //[Snip]
    });
});

This will let any request that starts with /api past that point, and if no other middleware or routes are matched, a 404 will be returned.

Sign up to request clarification or add additional context in comments.

Comments

3

Thanks to Douglas for his excellent answer. I improved upon it:

app.UseWhen( c => !c.Request.Path.StartsWithSegments( new PathString( "/api" ) ), app =>
    app.UseSpa( spa => {
        //[Snip]
    } ) );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.