title: How to throwing 404 on bad .NET Core API route?
body: <p>I have a .NET Core web app which has an API.  I've defined an Middleware class based on <a href="https://stackoverflow.com/questions/38630076/asp-net-core-web-api-exception-handling#answer-38935583">this</a> answer like so:</p>
  
  <pre><code>public class ErrorHandlingMiddleware
  {
      private readonly RequestDelegate next;
      private readonly ILogger logger;
  
      public ErrorHandlingMiddleware(RequestDelegate next,
          ILoggerFactory loggerFactory)
      {
          this.next = next;
          logger = loggerFactory.CreateLogger&lt;ErrorHandlingMiddleware&gt;();
      }
  
      public async Task Invoke(HttpContext context)
      {
          try
          {
              await next(context);
          }
          catch (Exception ex)
          {
              logger.LogError(0, ex, "An unhandled exception has occurred: " + ex.StackTrace);
              await HandleExceptionAsync(context, ex);
          }
      }
  
      private static Task HandleExceptionAsync(HttpContext context, Exception exception)
      {
          var code = HttpStatusCode.InternalServerError;
          var message = exception.Message;
          if (exception is BadRequestException)
          {
              code = HttpStatusCode.BadRequest;
          }
          else if (exception is NotFoundException)
          {
              code = HttpStatusCode.NotFound;
          }
          else if (exception is NotAuthorizedException)
          {
              code = HttpStatusCode.Forbidden;
          }
          else if (exception is NotAuthenticatedException)
          {
              code = HttpStatusCode.Unauthorized;
          }
          else
          {
              message = "An unexpected error occurred.";
          }
  
          var result = JsonConvert.SerializeObject(new { error = message });
          context.Response.ContentType = "application/json";
          context.Response.StatusCode = (int)code;
          return context.Response.WriteAsync(result);
      }
  }
  </code></pre>
  
  <p>The error handling only handles when an exception is thrown in code.  A bad route does not throw an exception.  The problem is that if I try to access a non-existent API route - that is, one that follows the API route convention and starts with "/api/adfasdf" - the API returns HTML (or the error page or the home page, I forget).</p>
  
  <p>I've received some suggestions to check the <code>context.Response.StatusCode</code> after <code>await next(context);</code> executes, but it's <code>200</code>.</p>
  
  <p>How can I configure my web app such that it recognizes a bad API route and returns a 404?</p>
  
  <p><strong>UPDATE</strong>
  Here is where/when I load the middleware in my Startup class:</p>
  
  <pre><code>public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime appLifetime, IOptions&lt;OidcConfig&gt; oidcConfigOptions)
  {
      loggerFactory.AddConsole(Configuration.GetSection("Logging"));
      loggerFactory.AddDebug();
  
      // Add Serilog to the logging pipeline
      loggerFactory.AddSerilog();
  
      app.UseMiddleware&lt;ErrorHandlingMiddleware&gt;();
  
      if (env.IsLocal())
      {
          app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
          {
              HotModuleReplacement = true
          });
      }
  
      var oidcConfig = oidcConfigOptions.Value;
  
      // Configure the app to use Jwt Bearer Authentication
      app.UseJwtBearerAuthentication(new JwtBearerOptions
      {
          AutomaticAuthenticate = true,
          AutomaticChallenge = true,
          Authority = oidcConfig.GetAuthority(),
          Audience = oidcConfig.ResourceAppId,
          TokenValidationParameters = new TokenValidationParameters
          {
              RequireExpirationTime = true,
              RequireSignedTokens = true,
              ValidateAudience = true,
              ValidIssuer = oidcConfig.GetIssuer(),
              ValidateIssuer = true,
              ValidateActor = false,
              ValidateLifetime = true,
              ValidateIssuerSigningKey = true
          },
      });
  
      app.UseSiteIdClaimInjection();
  
      app.UseStaticFiles();
  
      app.UseMvc(routes =&gt;
      {
          routes.MapRoute(
              name: "default",
              template: "{controller=Home}/{action=Index}/{id?}");
  
          routes.MapSpaFallbackRoute(
              name: "spa-fallback",
              defaults: new { controller = "Home", action = "Index" });
      });
  
      appLifetime.ApplicationStopped.Register(() =&gt; this.ApplicationContainer.Dispose());
  }
  </code></pre>