.NET Core combat development (Lesson 22: Exception processing middleware: logic to distinguish true anomaly and anomaly) - Study Notes (lower)

Next comes the way of using the proxy method, which means that the ErrorController the whole logic defined directly in the place of registration, use an anonymous delegate to handle the logic and the logic here is the same as before the

app.UseExceptionHandler(errApp =>
{
    errApp.Run(async context =>
    {
        // 在 Features 里面获取异常
        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
        // 识别异常是否为 IKnownException
        IKnownException knownException = exceptionHandlerPathFeature.Error as IKnownException;
        if (knownException == null)
        {
            // 如果不是则记录并且把错误的响应码响应成 Http 500
            var logger = context.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
            logger.LogError(exceptionHandlerPathFeature.Error, exceptionHandlerPathFeature.Error.Message);
            knownException = KnownException.Unknown;
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
        }
        else
        {
            // 如果捕获到的是一个业务逻辑的异常,Http 响应码应该给是 200
            knownException = KnownException.FromKnownException(knownException);
            context.Response.StatusCode = StatusCodes.Status200OK;
        }
        // 然后再把响应信息通过 json 的方式输出出去
        var jsonOptions = context.RequestServices.GetService<IOptions<JsonOptions>>();
        context.Response.ContentType = "application/json; charset=utf-8";
        await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(knownException, jsonOptions.Value.JsonSerializerOptions));
    });
});

For unknown why the exception is to be output Http 500, and for the business logic exceptions, the proposed output Http 200?

Because the monitoring system will actually Http response code identification, when the monitoring system to identify the proportion of 500 Http response is relatively high, the availability of the system will think there is a problem, this time warning system will warn

For this normal identify known business logic, then, to deal with the normal 200 Http is a normal behavior, so you can make the system work better monitor and correct identified some unknown system error messages, false alarms, so that the alarm system is more sensitive, but also to avoid the business logic exception interference warning system

Next, look at the third, by way of exception filter

This is actually a way of action, it is not, it is the role of the entire system occurs in the following frame of MVC earliest occurrence of the role of middleware in the MVC in which the entire life cycle, which means it can only work in request cycle MVC Web API inside

First, a custom MyExceptionFilter

namespace ExceptionDemo.Exceptions
{
    public class MyExceptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext context)
        {
            IKnownException knownException = context.Exception as IKnownException;
            if (knownException == null)
            {
                var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
                logger.LogError(context.Exception, context.Exception.Message);
                knownException = KnownException.Unknown;
                context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
            }
            else
            {
                knownException = KnownException.FromKnownException(knownException);
                context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
            }
            context.Result = new JsonResult(knownException)
            {
                ContentType = "application/json; charset=utf-8"
            };
        }
    }
}

Processing logic is the same as the previous

Then Registration Filters

services.AddMvc(mvcOptions =>
{
    mvcOptions.Filters.Add<MyExceptionFilter>();
}).AddJsonOptions(jsonoptions =>
{
    jsonoptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
});

Start the program, the output is as follows:

{"message":"未知错误","errorCode":9999,"errorData":null}

Consistent with previous output, because it is inside the Controller output error

If the output errors before MVC middleware, then it is no way to deal with the

Under normal circumstances this scenario implies the need for special exception handling Controller, but in terms of overall middleware then have to be treated with another specific logic, you can handle a manner ExceptionFilter

This way you can also by way of Attribute

Customizing a MyExceptionFilterAttribute

namespace ExceptionDemo.Exceptions
{
    public class MyExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(ExceptionContext context)
        {
            IKnownException knownException = context.Exception as IKnownException;
            if (knownException == null)
            {
                var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
                logger.LogError(context.Exception, context.Exception.Message);
                knownException = KnownException.Unknown;
                context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
            }
            else
            {
                knownException = KnownException.FromKnownException(knownException);
                context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
            }
            context.Result = new JsonResult(knownException)
            {
                ContentType = "application/json; charset=utf-8"
            };
        }
    }
}

In the Controller marked above MyExceptionFilter

[MyExceptionFilter]
public class WeatherForecastController : ControllerBase

After you start running the same effect

The effect of these two methods are equivalent, except that you can say more fine-grained control of exception handling, may Controller or a designated portion of the Exception to determine our exception handling, or globally registered in ExceptionFilter

Of course, because ExceptionFilterAttribute also achieved IExceptionFilter, so it can also sign up to a global, you can also use it as a global exception handler filters to use, Controller of the above will not require labeling

Registration Filters

services.AddMvc(mvcOptions =>
{
    //mvcOptions.Filters.Add<MyExceptionFilter>();
    mvcOptions.Filters.Add<MyExceptionFilterAttribute>();
}).AddJsonOptions(jsonoptions =>
{
    jsonoptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
});

Cancel the above label MyExceptionFilter in Controller

//[MyExceptionFilter]
public class WeatherForecastController : ControllerBase

Start the program, consistent output

For this scenario we define some of the API, and the API defined exception handling our convention is helpful

in conclusion

First we need to define the specific exception class or interface, we can define an abstract class, interface means may be used, the example shows, by way of exception business logic interface

For business logic exception, in fact, we need to define a global error code

For unknown anomaly, the output should be a specific output and error code, and then record the complete log, we should not take some of the internal systems such as exception stack information output to the user

For known business logic exception with the way Http 200, for an unknown anomaly, by the way Http 500, which would allow the monitoring system to work better

Another suggestion is to try to record all the details of the exception to the log for subsequent analysis, but also for the surveillance system to do some specific monitoring warning

Creative Commons License

This work is Creative Commons Attribution - NonCommercial - ShareAlike 4.0 International License Agreement for licensing.

Welcome to reprint, use, repost, but be sure to keep the article signed by Zheng Ziming (containing links: http://www.cnblogs.com/MingsonZheng/), shall not be used for commercial purposes, be sure to publish the same work based on the paper license modification .

If you have any questions, please contact me ([email protected]).

Guess you like

Origin www.cnblogs.com/MingsonZheng/p/12483923.html