gpt4 book ai didi

asp.net-web-api - OWIN 中间件中的全局异常处理

转载 作者:行者123 更新时间:2023-12-03 08:40:06 25 4
gpt4 key购买 nike

我正在尝试在 ASP.NET Web API 2.1 项目中创建统一的错误处理/报告,该项目构建在 OWIN 中间件(使用 Owin.Host.SystemWeb 的 IIS 主机)之上。
目前我使用了一个自定义异常记录器,它继承自 System.Web.Http.ExceptionHandling.ExceptionLogger并使用 NLog 记录所有异常,如下代码:

public class NLogExceptionLogger : ExceptionLogger
{

private static readonly Logger Nlog = LogManager.GetCurrentClassLogger();
public override void Log(ExceptionLoggerContext context)
{
//Log using NLog
}
}

我想将所有 API 异常的响应正文更改为友好的统一响应,该响应使用 System.Web.Http.ExceptionHandling.ExceptionHandler 隐藏所有异常详细信息如以下代码:

public class ContentNegotiatedExceptionHandler : ExceptionHandler
{
public override void Handle(ExceptionHandlerContext context)
{
var errorDataModel = new ErrorDataModel
{
Message = "Internal server error occurred, error has been reported!",
Details = context.Exception.Message,
ErrorReference = context.Exception.Data["ErrorReference"] != null ? context.Exception.Data["ErrorReference"].ToString() : string.Empty,
DateTime = DateTime.UtcNow
};

var response = context.Request.CreateResponse(HttpStatusCode.InternalServerError, errorDataModel);
context.Result = new ResponseMessageResult(response);
}
}

这将在发生异常时为客户端返回以下响应:

{
"Message": "Internal server error occurred, error has been reported!",
"Details": "Ooops!",
"ErrorReference": "56627a45d23732d2",
"DateTime": "2015-12-27T09:42:40.2982314Z"
}

现在,如果发生任何异常,这一切都很好 在 Api Controller 请求管道中 .

但在我的情况下,我使用的是中间件 Microsoft.Owin.Security.OAuth用于生成不记名 token ,并且此中间件对 Web API 异常处理一无所知,例如,如果在方法 ValidateClientAuthentication 中抛出了异常我的 NLogExceptionLogger不是 ContentNegotiatedExceptionHandler将了解有关此异常的任何信息,也不会尝试处理它,这是我在 AuthorizationServerProvider 中使用的示例代码如下:

public class AuthorizationServerProvider : OAuthAuthorizationServerProvider
{
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
//Expcetion occurred here
int x = int.Parse("");

context.Validated();
return Task.FromResult<object>(null);
}

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (context.UserName != context.Password)
{
context.SetError("invalid_credentials", "The user name or password is incorrect.");
return;
}

var identity = new ClaimsIdentity(context.Options.AuthenticationType);

identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));

context.Validated(identity);
}
}

因此,我将不胜感激在实现以下两个问题方面的任何指导:

1 - 创建一个全局异常处理程序 仅处理 OWIN 中间件生成的异常 ?我关注了 this answer并创建了一个用于异常处理目的的中间件并将其注册为第一个,我能够记录源自“OAuthAuthorizationServerProvider”的异常,但我不确定这是否是最佳方法。

2 - 现在,当我在上一步中实现日志记录时,我真的不知道如何更改异常的响应,因为我需要向客户端返回一个标准的 JSON 模型,以处理“OAuthAuthorizationServerProvider”中发生的任何异常。有相关 answer here我试图依赖,但没有奏效。

这是我的 Startup 类和自定义 GlobalExceptionMiddleware我为异常捕获/记录而创建。缺少的和平是为任何异常返回统一的 JSON 响应。任何想法将不胜感激。

public class Startup
{
public void Configuration(IAppBuilder app)
{
var httpConfig = new HttpConfiguration();

httpConfig.MapHttpAttributeRoutes();

httpConfig.Services.Replace(typeof(IExceptionHandler), new ContentNegotiatedExceptionHandler());

httpConfig.Services.Add(typeof(IExceptionLogger), new NLogExceptionLogger());

OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new AuthorizationServerProvider()
};

app.Use<GlobalExceptionMiddleware>();

app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

app.UseWebApi(httpConfig);
}
}

public class GlobalExceptionMiddleware : OwinMiddleware
{
public GlobalExceptionMiddleware(OwinMiddleware next)
: base(next)
{ }

public override async Task Invoke(IOwinContext context)
{
try
{
await Next.Invoke(context);
}
catch (Exception ex)
{
NLogLogger.LogError(ex, context);
}
}
}

最佳答案

好的,所以这比预期的要容易,感谢@Khalid 的提醒,我最终创建了一个名为 OwinExceptionHandlerMiddleware 的 owin 中间件它专门用于处理任何 Owin 中间件中发生的任何异常(在将其返回给客户端之前记录它并处理响应)。

您需要将此中间件注册为 第一个 Startup类如下:

public class Startup
{
public void Configuration(IAppBuilder app)
{
var httpConfig = new HttpConfiguration();

httpConfig.MapHttpAttributeRoutes();

httpConfig.Services.Replace(typeof(IExceptionHandler), new ContentNegotiatedExceptionHandler());

httpConfig.Services.Add(typeof(IExceptionLogger), new NLogExceptionLogger());

OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new AuthorizationServerProvider()
};

//Should be the first handler to handle any exception happening in OWIN middlewares
app.UseOwinExceptionHandler();

// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

app.UseWebApi(httpConfig);
}
}

以及 OwinExceptionHandlerMiddleware中使用的代码如下:

using AppFunc = Func<IDictionary<string, object>, Task>;

public class OwinExceptionHandlerMiddleware
{
private readonly AppFunc _next;

public OwinExceptionHandlerMiddleware(AppFunc next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}

_next = next;
}

public async Task Invoke(IDictionary<string, object> environment)
{
try
{
await _next(environment);
}
catch (Exception ex)
{
try
{

var owinContext = new OwinContext(environment);

NLogLogger.LogError(ex, owinContext);

HandleException(ex, owinContext);

return;
}
catch (Exception)
{
// If there's a Exception while generating the error page, re-throw the original exception.
}
throw;
}
}
private void HandleException(Exception ex, IOwinContext context)
{
var request = context.Request;

//Build a model to represet the error for the client
var errorDataModel = NLogLogger.BuildErrorDataModel(ex);

context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ReasonPhrase = "Internal Server Error";
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(errorDataModel));

}

}

public static class OwinExceptionHandlerMiddlewareAppBuilderExtensions
{
public static void UseOwinExceptionHandler(this IAppBuilder app)
{
app.Use<OwinExceptionHandlerMiddleware>();
}
}

关于asp.net-web-api - OWIN 中间件中的全局异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34479465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com