question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[API Proposal]: Add SkipStatusCodePages property to ApiBehaviorOptions

See original GitHub issue

Background and Motivation

When mixing MVC Controllers with Api Controllers in an application, there should be a global setting in ApiBehaviorOptions to turn off the IStatusCodePagesFeature for Api Controllers to avoid overriding the raw api response with an MVC view/html based status code page implementation.

Proposed API

namespace Microsoft.AspNetCore.Mvc;

public class ApiBehaviorOptions : IEnumerable<ICompatibilitySwitch>
{
+    public bool SkipStatusCodePages { get; set; }
}

Usage Examples

// Program.cs Minimal API

var builder = WebApplication.CreateBuilder(args);

// Register services

app.AddMvc().ConfigureApiBehaviorOptions(options =>
{
    options.SkipStatusCodePages = true;
});

var app = builder.Build();

// Register middlewares

app.MapControllers();

await app.RunAsync();

Alternative Designs

public static class SkipStatusCodePagesMetadataExtensions
{
    public static IEndpointConventionBuilder SkipStatusCodePagesForApiControllers(this IEndpointConventionBuilder builder)
    {
        builder.Add(endpointBuilder =>
        {
            var apiControllerAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(ApiControllerAttribute)) as ApiControllerAttribute;

            if (apiControllerAttribute == null)
            {
                return;
            }

            endpointBuilder.Metadata.Add(new SkipStatusCodePagesMetadata());

            endpointBuilder.FilterFactories.Add((context, next) =>
            {
                return async context =>
                {
                    var statusCodeFeature = context.HttpContext.Features.Get<IStatusCodePagesFeature>();

                    if (statusCodeFeature != null)
                    {
                        // Turn off the StatusCodePages feature.
                        statusCodeFeature.Enabled = false;
                    }

                    return await next(context);
                };
            });
        });

        return builder;
    }
}

 // Marker metadata class
file class SkipStatusCodePagesMetadata : ISkipStatusCodePagesMetadata
{
}
// Program.cs Minimal API

var builder = WebApplication.CreateBuilder(args);

// Register services

app.AddMvc();

var app = builder.Build();

// Register middlewares

app.MapControllers().SkipStatusCodePagesForApiControllers();

await app.RunAsync();

Risks

There are no risks because the default value for ApiBehaviorOptions.SkipStatusCodePages will be false which is the current behavior.

Issue Analytics

  • State:open
  • Created 10 months ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
alienwareonecommented, Dec 2, 2022

You just have to be careful to call UseStatusCodePages after UseRouting. This is probably a good reason to make writing an analyzer to flag this misordering a higher priority. We already have #38591 tracking this.

@halter73 Thanks for pointing that out! With the correct ordering the need to add a filter is not required.

app.MapControllers().WithMetadata(new SkipStatusCodePagesAttribute());

But this will also skip the StatusCodePagesMiddleware for MVC Controllers which is not desired.

Here is a minimal repo about this issue.

0reactions
halter73commented, Dec 12, 2022

API Review Notes:

  • Why not always skip status pages for API controllers? Shouldn’t problem details be used instead?
    • Would this be too breaking? Could it be too confusing when UseStatusCodePages simply doesn’t work for API controllers without an opt-in?
  • Do we like “Skip”? It doesn’t align with the other ApiBehaviorOptions, but it does align with the attribute name.
  • While .MapControllers().WithMetadata(new SkipStatusCodePagesAttribute()) works to skip status code pages for all controllers, this will be specific to API Controllers.
namespace Microsoft.AspNetCore.Mvc;

public class ApiBehaviorOptions : IEnumerable<ICompatibilitySwitch>
{
+    public bool SkipStatusCodePages { get; set; }
}

API Approved as proposed!

Read more comments on GitHub >

github_iconTop Results From Across the Web

ApiBehaviorOptions Class (Microsoft.AspNetCore.Mvc)
Gets or sets a value that determines if an multipart/form-data consumes action constraint is added to parameters that are bound from form data....
Read more >
How to Use ModelState Validation in ASP.NET Core Web API
When we talk about ModelState , we mean ModelState property of the ControllerBase abstract class in the Microsoft.AspNetCore.Mvc namespace.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found