MVC6 中的自定义选择性 404 页面
Posted
技术标签:
【中文标题】MVC6 中的自定义选择性 404 页面【英文标题】:Custom Selective 404 Page in MVC6 【发布时间】:2016-04-23 16:20:17 【问题描述】:我正在寻求帮助,我们可以在 ASP.NET 5 MVC6 中创建自定义 Error404 页面。
我最接近的是使用
app.UseStatusCodePagesWithReExecute("/Error/0");
在 Startup.cs 的配置方法中。
通过调用“/Error/404”操作可以正常工作。
我正在研究如何在缺少 JPG/PNG/GIF 请求的情况下发送不同的 404 响应。
任何正确方向的建议都会有很大帮助。
【问题讨论】:
MVC 6 404 Not Found的可能重复 【参考方案1】:如果您使用当前的 UseStatusCodePages 中间件,它将影响每一个错误。为了完成您要查找的内容,您需要创建自己的中间件,该中间件需要放置在您的默认错误处理中间件之后:
//Startup.cs
public void Configure(IApplicationBuilder app)
app.UseStatusCodePagesWithReExecute("/Home/Error/0");
app.UseImageNotFoundMiddlewareWithRedirect("/Home/ImageError");
这应该可以帮助您入门:Github - StatusCodePage
这是一个示例中间件,可以模拟您正在寻找的东西:
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);
)
);
【讨论】:
【参考方案2】:作为自定义中间件方法的替代方案,您可以使用 MapWhen 来拆分管道并分别处理图像:
将以下内容添加到 Startup.cs 的 Configure 方法(在您的非图像中间件之上):
app.MapWhen(context => context.Request.Path.Value.EndsWith(".png"), appBuilder =>
appBuilder.UseStatusCodePagesWithReExecute("/image-error");
appBuilder.UseStaticFiles();
);
显然,您可以更改谓词以满足您的需要。
然后你可以创建一个动作和视图来处理错误:
[Route("image-error")]
public IActionResult ImageError(int code)
return View();
你可以在我写的关于conditional middleware的帖子中找到更多信息
【讨论】:
【参考方案3】:您应该能够使用 UseStatusCodePages() 方法的覆盖之一来实现此目的。使用其中之一:
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");
【讨论】:
您能告诉我您发布的代码是如何解决我的问题的吗?以上是关于MVC6 中的自定义选择性 404 页面的主要内容,如果未能解决你的问题,请参考以下文章
重定向到 DjangoCMS 中的自定义 404 html 页面