简体   繁体   中英

UseStatusCodePagesWithReExecute shows blank page

I've been trying to use the UseStatusCodePagesWithReExecute method to show a page that shows customized messages per status code on the application I'm trying to make with ASP.NET Core 3.0

I've followed the instructions on this website , but right now, if I try to test this by accessing a non-existant webpage, a blank page shows up, and the code doesn't pass through the OnGet method on the Razor Page I want to be shown (I used breakpoints).

However, I am able to get the status page to show by accessing manually the page on my browser using the /Status/404 URI.

On the startup file, I've added the required lines, as shown in the tutorial.

// Startup.cs
public static void Configure(IApplicationBuilder app,
                             IWebHostEnvironment env,
                             IHostApplicationLifetime appLifetime)
    {
        app.UseDeveloperExceptionPage();
        app.UseStatusCodePagesWithReExecute("/Status/{0}");
        app.UseExceptionHandler("/Status");

        // Irrelevant code below        
    }

The status model contains a OnGet method that takes the code number as a parameter

// Status.cshtml.cs

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class StatusModel : PageModel
{
    public void OnGet(string? code = null)
    {
        if (null == code)
            code = HttpContext.Response.StatusCode.ToString();

        PageTitle = $"HTTP status {code}";
        StatusNumber = code;

        if (code.CompareTo("404") == 0)
        {
            StatusName = "Not found";
            StatusDescription = "The requested page was not found.";
        }
        else
        {
            StatusName = "Unknown error";
            StatusDescription = "An unknown error occurred.";
        }
    }
}

The status view is quite simple:

@page "{code?}"
@model StatusModel
@{
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@Model.PageTitle</title>
</head>
<body>
    <div>
        <h1>@Model.StatusNumber</h1>
        <h2>@Model.StatusName</h2>
        <h2>@Model.StatusDescription</h2>
    </div>
    <p>RID: @Model.RequestId</p>
</body>
</html>

On the output console, I can see that indeed the application noticed that it caught the 404, but it doesn't appear to do anything:

info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
      Executed page /Index in 225.4469ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint '/Index'

Is there something that's changed when passing from ASP.NET Core 2.2 to 3.0 that I forgot to edit / add to make this work, or is this already supposed to work?

Is there something that's changed when passing from ASP.NET Core 2.2 to 3.0 that I forgot to edit / add to make this work, or is this already supposed to work?

This is already supposed to work.

Status.cshtml:

@page "{code?}"
@model StatusModel
@{
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@Model.PageTitle</title>
</head>
<body>
    <div>
        <h1>@Model.StatusNumber</h1>
        <h2>@Model.StatusName</h2>
        <h2>@Model.StatusDescription</h2>
    </div>
</body>
</html>

Status.cshtml.cs:

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class StatusModel : PageModel
{
    public string PageTitle { get;  set; }
    public string StatusNumber { get;  set; }
    public string StatusName { get;  set; }
    public string StatusDescription { get;  set; }

    public void OnGet(string? code = null)
    {
        if (null == code)
            code = HttpContext.Response.StatusCode.ToString();

        PageTitle = $"HTTP status {code}";
        StatusNumber = code;

        if (code.CompareTo("404") == 0)
        {
            StatusName = "Not found";
            StatusDescription = "The requested page was not found.";
        }
        else
        {
            StatusName = "Unknown error";
            StatusDescription = "An unknown error occurred.";
        }
    }
}

Result: 在此处输入图片说明

Update:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseStatusCodePagesWithReExecute("/Status/{0}");
        app.UseExceptionHandler("/Status");
    }
    else
    {
        app.UseDeveloperExceptionPage();
        app.UseStatusCodePagesWithReExecute("/Status/{0}");
        app.UseExceptionHandler("/Status");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    app.Use(async (context, next) =>
    {
        await next();

        if (context.Response.StatusCode == 401)
        {

            var newPath = new PathString("/Status/401");
            var originalPath = context.Request.Path;
            var originalQueryString = context.Request.QueryString;
            context.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
            {
                OriginalPathBase = context.Request.PathBase.Value,
                OriginalPath = originalPath.Value,
                OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
            });

            // An endpoint may have already been set. Since we're going to re-invoke the middleware pipeline we need to reset
            // the endpoint and route values to ensure things are re-calculated.
            context.SetEndpoint(endpoint: null);
            var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
            routeValuesFeature?.RouteValues?.Clear();

            context.Request.Path = newPath;
            try
            {
                await next();
            }
            finally
            {
                context.Request.QueryString = originalQueryString;
                context.Request.Path = originalPath;
                context.Features.Set<IStatusCodeReExecuteFeature>(null);
            }

            // which policy failed? need to inform consumer which requirement was not met
            //await next();
        }

    });
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

Result: 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM