简体   繁体   English

MVC6中的自定义选择性404页面

[英]Custom Selective 404 Page in MVC6

I am looking for help we can have a custom Error404 page in ASP.NET 5 MVC6. 我正在寻找帮助,我们可以在ASP.NET 5 MVC6中有一个自定义的Error404页面。

The closest I have come is to use 我最接近的是使用

app.UseStatusCodePagesWithReExecute("/Error/{0}");

in the Startup.cs Configure method. 在Startup.cs Configure方法中。

It works fine by calling the "/Error/404" action. 通过调用“/ Error / 404”动作它可以正常工作。

I am looking on ways on how I can send a different 404 response in the event it is a missing JPG/PNG/GIF request. 我正在研究如何在缺少JPG / PNG / GIF请求的情况下发送不同的404响应。

Any suggestion in the right direction would be of great help. 任何正确方向的建议都会有很大帮助。

If you use the current UseStatusCodePages middleware, it's going to affect every single error. 如果使用当前的UseStatusCodePages中间件,则会影响每个错误。 In order to accomplish what you're looking for, you need to create your own Middleware, that needs to be placed right after your default error handling middleware: 为了实现您的目标,您需要创建自己的中间件,需要在您的默认错误处理中间件之后立即放置:

//Startup.cs
public void Configure(IApplicationBuilder app)
{
    app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");
    app.UseImageNotFoundMiddlewareWithRedirect("/Home/ImageError");
}

This should get you started: Github - StatusCodePage 这应该让你开始: Github - StatusCodePage

Here's an example middleware to simulate maybe what you're looking for: 这是一个示例中间件,可以模拟您正在寻找的内容:

public class ImageNotFoundMiddleware
{
    private readonly RequestDelegate _next;
    private readonly StatusCodePagesOptions _options;

    public ImageNotFoundMiddleware(RequestDelegate next, IOptions<StatusCodePagesOptions> options)
    {
        _next = next;
        _options = options.Value;
        if (_options.HandleAsync == null)
        {
            throw new ArgumentException("Missing options.HandleAsync implementation.");
        }
    }

    public async Task Invoke(HttpContext context)
    {
        var statusCodeFeature = new StatusCodePagesFeature();
        context.Features.Set<IStatusCodePagesFeature>(statusCodeFeature);

        await _next(context);

        if (!statusCodeFeature.Enabled)
        {
            // Check if the feature is still available because other middleware (such as a web API written in MVC) could
            // have disabled the feature to prevent HTML status code responses from showing up to an API client.
            return;
        }

        // Do nothing if a response body has already been provided or not 404 response
        if (context.Response.HasStarted
            || context.Response.StatusCode != 404
            || context.Response.ContentLength.HasValue
            || !string.IsNullOrEmpty(context.Response.ContentType))
        {
            return;
        }

        // todo => Here is where you'd also add your logic to check for the image 404...
        if (context.Request.Path.Value.EndsWith(".JPG", StringComparison.OrdinalIgnoreCase)
            || context.Request.Path.Value.EndsWith(".PNG", StringComparison.OrdinalIgnoreCase)
            || context.Request.Path.Value.EndsWith(".GIF", StringComparison.OrdinalIgnoreCase)
            )
        {
            var statusCodeContext = new StatusCodeContext(context, _options, _next);
            await _options.HandleAsync(statusCodeContext);
        }
    }
}

// Extension method used to add the middleware to the HTTP request pipeline.
public static class ImageNotFoundMiddlewareExtensions
{
    public static IApplicationBuilder UseImageNotFoundMiddlewareWithRedirect(this IApplicationBuilder app,
        string locationFormat)
    {
        if (app == null)
        {
            throw new ArgumentNullException(nameof(app));
        }

        return app.UseMiddleware<ImageNotFoundMiddleware>(
            Options.Create(
                new StatusCodePagesOptions
                {
                    HandleAsync = context =>
                    {
                        var location = string.Format(
                            CultureInfo.InvariantCulture,
                            locationFormat.StartsWith("~") ? locationFormat.Substring(1) : locationFormat,
                            context.HttpContext.Response.StatusCode);
                        context.HttpContext.Response.Redirect(
                            locationFormat.StartsWith("~")
                                ? context.HttpContext.Request.PathBase + location
                                : location);
                        return Task.FromResult(0);
                    }
                }
            )
        );
    }
}

You should be able to use one of the overrides of UseStatusCodePages() methods to achieve this. 您应该能够使用UseStatusCodePages()方法的一个覆盖来实现此目的。 Use one of these: 使用以下其中一个:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        // app.UseErrorPage(ErrorPageOptions.ShowAll);
        // app.UseStatusCodePages();
        // app.UseStatusCodePages(context => context.HttpContext.Response.SendAsync("Handler, status code: " + context.HttpContext.Response.StatusCode, "text/plain"));
        // app.UseStatusCodePages("text/plain", "Response, status code: {0}");
        // app.UseStatusCodePagesWithRedirects("~/errors/{0}");
        // app.UseStatusCodePagesWithRedirects("/base/errors/{0}");
        // app.UseStatusCodePages(builder => builder.UseWelcomePage());
        // app.UseStatusCodePagesWithReExecute("/errors/{0}");
    }
} 

As an alternative to the custom middleware approach, you can use MapWhen to split the pipeline and handle images separately: 作为自定义中间件方法的替代方法,您可以使用MapWhen分割管道并分别处理图像:

Add the following to the Configure method of Startup.cs (above your non-image middleware): 将以下内容添加到Startup.cs的Configure方法(在非图像中间件上方):

app.MapWhen(context => context.Request.Path.Value.EndsWith(".png"), appBuilder =>
{
    appBuilder.UseStatusCodePagesWithReExecute("/image-error");
    appBuilder.UseStaticFiles();
});

Obviously, you can change the predicate to match your needs. 显然,您可以更改谓词以满足您的需求。

Then you can create an action and view to handle the error: 然后,您可以创建一个操作和视图来处理错误:

[Route("image-error")]
public IActionResult ImageError(int code)
{
    return View();
}

You can find more information in a post I wrote about conditional middleware 您可以在我撰写的有关条件中间件的帖子中找到更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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