异常处理和登录asp.net web api

Ope*_*ack 4 c# asp.net asp.net-web-api

我是 ASP.NET web api 的新手,我正在阅读这两篇关于异常处理的文章

  1. 异常处理
  2. 错误处理

虽然我了解异常处理链接,但我不确定是否使用 错误处理。这是我想要做的:

  1. 当发生错误时,我想用原始请求发送的消息、堆栈跟踪和请求对象记录该错误。
  2. 每个传入请求的类型可能不同,我计划将请求对象序列化为 JSON 字符串并将它们存储在数据库中,同时记录错误。

似乎我应该在每个方法上添加 try catch 块,然后执行异常处理和日志记录。这将是一项乏味的任务。有没有办法全局处理错误并且仍然能够捕获异常详细信息(消息、堆栈跟踪)和日志请求对象。

Win*_*Win 5

有没有办法全局处理错误并且仍然能够捕获异常详细信息(消息、堆栈跟踪)和日志请求对象。

是的,ASP.NET Web API 2.1 具有对未处理异常的全局处理的框架支持,而不是在每个方法上添加 try catch 块。

它允许自定义发生未处理的应用程序异常时发送的 HTTP 响应。

网络接口配置

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // ...

        config.Services.Replace(typeof (IExceptionHandler), 
            new GlobalExceptionHandler());
    }
}
Run Code Online (Sandbox Code Playgroud)

全局异常处理程序

public class GlobalExceptionHandler : ExceptionHandler
{
    public override void Handle(ExceptionHandlerContext context)
    {
        var exception = context.Exception;

        var httpException = exception as HttpException;
        if (httpException != null)
        {
            context.Result = new CustomErrorResult(context.Request,
                (HttpStatusCode) httpException.GetHttpCode(), 
                 httpException.Message);
            return;
        }

        // Return HttpStatusCode for other types of exception.

        context.Result = new CustomErrorResult(context.Request, 
            HttpStatusCode.InternalServerError,
            exception.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义错误结果

public class CustomErrorResult : IHttpActionResult
{
    private readonly string _errorMessage;
    private readonly HttpRequestMessage _requestMessage;
    private readonly HttpStatusCode _statusCode;

    public CustomErrorResult(HttpRequestMessage requestMessage, 
       HttpStatusCode statusCode, string errorMessage)
    {
        _requestMessage = requestMessage;
        _statusCode = statusCode;
        _errorMessage = errorMessage;
    }

    public Task<HttpResponseMessage> ExecuteAsync(
       CancellationToken cancellationToken)
    {
        return Task.FromResult(_requestMessage.CreateErrorResponse(
            _statusCode, _errorMessage));
    }
}
Run Code Online (Sandbox Code Playgroud)

归功于ASP.NET Web API 2:从头到尾构建 REST 服务


Cra*_* W. 0

创建一个过滤器来为您处理这些操作,然后全局注册该过滤器。我们做了一些非常相似的事情,这是我们使用的过滤器类。

public class FailedApiRequestLoggerAttribute : ActionFilterAttribute
{
    private readonly bool _removeErrorDetailsFromResponse;

    public FailedApiRequestLoggerAttribute(bool removeErrorDetailsFromResponse)
    { _removeErrorDetailsFromResponse = removeErrorDetailsFromResponse; }

    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnActionExecuted(actionExecutedContext);

        var log = LoggerFactory.GetLogger(actionExecutedContext.ActionContext.ControllerContext.Controller.GetType().Name);

        // If there is no response object then we're probably here because an exception was 
        // thrown and thrown exceptions are handled elsewhere.
        if (actionExecutedContext.Response?.IsSuccessStatusCode == false)
        {
            var error = new StringBuilder();
            error.AppendLine("API Call Returned Non-Success Status");
            error.AppendLine($"{actionExecutedContext.ActionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName}.{actionExecutedContext.ActionContext.ActionDescriptor.ActionName}");

            if (actionExecutedContext.ActionContext.ActionArguments.Any())
            { error.AppendLine($"  Arguments"); }

            foreach (var argument in actionExecutedContext.ActionContext.ActionArguments)
            { error.AppendLine($"    {JsonConvert.SerializeObject(argument)}"); }

            error.AppendLine("  Response");
            error.AppendLine($"    Status Code: {actionExecutedContext.Response.StatusCode}; Reason: {actionExecutedContext.Response.ReasonPhrase}");

            var content = actionExecutedContext.Response.Content as ObjectContent<HttpError>;
            if (content != null)
            {
                error.AppendLine($"    {JsonConvert.SerializeObject(content.Value)}");

                if (_removeErrorDetailsFromResponse)
                { ((HttpError)content.Value).Clear(); }
            }

            log.Warning(error.ToString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后它在全球范围内注册。

config.Filters.Add(new FailedApiRequestLoggerAttribute(true));
Run Code Online (Sandbox Code Playgroud)