MJBZA
MJBZA

Reputation: 5018

How can I exclude some routes from UseStatusCodePagesWithReExecute?

I have a full-stack app in ASP.NET Core 5. The front-end is React and the back-end is OData.

I need to use app.UseStatusCodePagesWithReExecute("/"); in my Configure() method to redirect any unknown requests to index.html, as routing is handled by the client-side code.

The problem is that in OData standard, when a key in a GET request is invalid, it returns a 404 error. This error will cause a redirect to index.html as well.

My Question: How can I exclude any request that starts with /odata.svc from UseStatusCodePagesWithReExecute()?

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }            

    // generated swagger json and swagger ui middleware
    // You can access the swagger ui at /swagger/index.html 
    app.UseSwagger();
    app.UseSwaggerUI(x => x.SwaggerEndpoint("/swagger/v1/swagger.json", "ASP.NET Core Sign-up and Verification API"));

    //app.UseCors("CorsPolicy");
    // global cors policy
    app.UseCors(x => x
        .SetIsOriginAllowed(origin => true)
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials());

    app.UseForwardedHeaders(new ForwardedHeadersOptions
    {
        ForwardedHeaders = ForwardedHeaders.All
    });

    app.UseRouting();

    // global error handler
    app.UseMiddleware<ErrorHandlerMiddleware>();

    // custom jwt auth middleware
    app.UseMiddleware<JwtMiddleware>();

    app.UseEndpoints(endpoints =>
    {
        endpoints.Select().Expand().Filter().OrderBy().Count().MaxTop(30);
        // add an endpoint for an actual domain model
        // registered this endpoint with name odata (first parameter) 
        // and also with the same prefix (second parameter)
        // in this route, we are returning an EDM Data Model
        endpoints.MapODataRoute("odata.svc", "odata.svc", GetEdmModel(app.ApplicationServices));
        endpoints.EnableDependencyInjection();
        endpoints.MapControllers();
        // enable serving static files
        endpoints.MapDefaultControllerRoute();
    });

    // Redirects any unknown requests to index.html
    app.UseStatusCodePagesWithReExecute("/");

    app.UseHttpsRedirection();

    // Serve default documents (i.e. index.html)
    app.UseDefaultFiles();

    //Set HTTP response headers
    const string cacheMaxAge = "1";
    // Serve static files
    app.UseStaticFiles(new StaticFileOptions
    {
        OnPrepareResponse = ctx =>
        {
            // using Microsoft.AspNetCore.Http;
            ctx.Context.Response.Headers.Append(
                    "Cache-Control", $"public, max-age={cacheMaxAge}");
        }
    });
}

Upvotes: 4

Views: 1117

Answers (1)

Jeremy Caney
Jeremy Caney

Reputation: 7622

This seems like an ideal use case for the UseWhen() extension method. This functionality is (under)documented by Microsoft, though @Paul Hiles has a more comprehensive write-up about it on his DevTrends blog. Basically, this allows you to conditionally inject middleware into your execution pipeline.

So, to conditionally exclude UseStatusCodePagesWithReExecute() if your request path starts with /odata.svc, you would simply wrap your UseStatusCodePagesWithReExecute() call with a UseWhen() condition, as follows:

app.UseWhen(
    context => context.Request.Path.StartsWithSegments("/odata.svc"), 
    appBuilder =>
    {
        appBuilder.UseStatusCodePagesWithReExecute("/");
    }
);

Upvotes: 3

Related Questions