ASP.NET Core应用错误处理之StatusCodePagesMiddleware中间(2)

阻止StatusCodePagesMiddleware中间件进行错误处理的机制是借助于一个名为StatusCodePagesFeature的特性来实现的。StatusCodePagesFeature对应如下这个IStatusCodePagesFeature接口,它具有唯一的布尔类型的属性成员Enabled。默认使用的StatusCodePagesFeature类型实现了这个接口,默认情况下这个开关是开启的。

public interface IStatusCodePagesFeature { bool Enabled { get; set; } } public class StatusCodePagesFeature : IStatusCodePagesFeature { public bool Enabled { get; set; } = true ; }

StatusCodePagesMiddleware中间件在将请求交付给后续管道之前,它会创建一个StatusCodePagesFeature特性对象并将其添加到当前HttpContext之中。当最终决定是否执行错误处理操作的时候,它还会通过这个特性检验是否某个后续的中间件不希望自己“画蛇添足”地进行不必要的错误处理,如下的代码片段很好的体现了这一点。

public class StatusCodePagesMiddleware { … public async Task Invoke(HttpContext context) { StatusCodePagesFeature feature = new StatusCodePagesFeature(); context.Features.Set<IStatusCodePagesFeature>(feature); await _next(context); var response = context.Response; if ((response.StatusCode >= 400 && response.StatusCode <= 599) && !response.ContentLength.HasValue &&string.IsNullOrEmpty(response.ContentType) && feature.Enabled) { await _options.HandleAsync(new StatusCodeContext(context, _options, _next)); } } }

我们通过一个简单的实例来演示如果利用这个StatusCodePagesFeature特性来屏蔽StatusCodePagesMiddleware中间件。在下面这个应用中,我们将针对请求的处理定义在Invoke方法中,该方法会返回一个状态码为“401 Unauthorized”的响应。我们通过随机数让这个方法会在50%的情况下利用StatusCodePagesFeature特性来阻止StatusCodePagesMiddleware中间件自身对错误的处理。我们通过调用扩展方法UseStatusCodePages注册的StatusCodePagesMiddleware中间件会直接响应一个内容为“Error occurred!”的字符串。

public class Program { public static void Main() { new WebHostBuilder() .UseKestrel() .Configure(app => app .UseStatusCodePages(async context => await context.HttpContext.Response.WriteAsync("Error occurred!")) .Run(Invoke)) .Build() .Run(); } private static Random _random = new Random(); private static Task Invoke(HttpContext context) { context.Response.StatusCode = 401; if (_random.Next() % 2 == 0) { context.Features.Get<IStatusCodePagesFeature>().Enabled = false; } return Task.CompletedTask; } }

对于针对该应用的请求来说,我们会得到如下两种不同的响应。没有主体内容响应是通过Invoke方法产生的,这种情况下发生在StatusCodePagesMiddleware中间件通过StatusCodePagesFeature特性被屏蔽的时候。具有主体内容的响应则来源于StatusCodePagesMiddleware中间件。

HTTP/1.1 401 Unauthorized Date: Sun, 18 Dec 2016 01:59:37 GMT Server: Kestrel Content-Length: 15 Error occurred! HTTP/1.1 401 Unauthorized Date: Sun, 18 Dec 2016 01:59:38 GMT Content-Length: 0 Server: Kestrel

三、注册StatusCodePagesMiddleware中间件

我们在大部分情况下都会调用ApplicationBuilder相应的扩展方法来注册StatusCodePagesMiddleware中间件。对于StatusCodePagesMiddleware中间件的注册来说,除了我们已经很熟悉的UseStatusCodePages方之外,还具有额外一些扩展方法供我们选择。

UseStatusCodePages

我们可以调用如下三个UseStatusCodePages方法重载来注册StatusCodePagesMiddleware中间件。不论我们调用那个重载,系统最终都会根据提供的StatusCodePagesOptions对象调用构造函数来创建这个中间件对象,而且这个StatusCodePagesOptions必须具有一个作为错误处理器的Func<StatusCodeContext, Task>对象。如果没有指定任何参数,StatusCodePagesOptions对象需要以Options模式的形式注册为服务。

public static class StatusCodePagesExtensions { public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app) { return app.UseMiddleware<StatusCodePagesMiddleware>(); } public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, StatusCodePagesOptions options) { return app.UseMiddleware<StatusCodePagesMiddleware>(Options.Create(options)); } public static IApplicationBuilder UseStatusCodePages(this IApplicationBuilder app, Func<StatusCodeContext, Task> handler) { return app.UseStatusCodePages(new StatusCodePagesOptions { HandleAsync = handler }); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdsdpd.html