Custom Selective 404 Page in MVC6

I am looking for help, we can create a custom Error404 page in ASP.NET 5 MVC6.

The closest I came to use

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

in the setup method of Startup.cs.

It works great by invoking the action "/ Error / 404".

I am considering ways how I can send another 404 response if there is no JPG / PNG / GIF request.

Any suggestion in the right direction would be very helpful.

+3
asp.net-core asp.net-core-mvc
Jan 18 '16 at 13:15
source share
3 answers

As an alternative to the individual middleware approach, you can use MapWhen to separate the pipeline and image processing separately:

Add the following setup method for Startup.cs (above your middleware without image):

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

Obviously, you can change the predicate to suit 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 the post I wrote about conditional middleware

0
Jun 02 '17 at 21:16
source share

If you use the current UseStatusCodePages middleware, it will affect every error. To accomplish what you are looking for, you need to create your own Middleware, which should be placed immediately after the default error handling middleware:

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

This should start: Github - StatusCodePage

Here's an example of a simulation middleware, perhaps what you are 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); } } ) ); } } 
+3
Aug 07 '16 at 4:12
source share

To achieve this, you must use one of the overrides of UseStatusCodePages () methods. Use one of the following options:

 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}"); } } 
0
Jan 19 '16 at 14:47
source share



All Articles