Global exception handling in OWIN middleware

后端 未结 2 1511
陌清茗
陌清茗 2020-12-07 16:50

I\'m trying to create a unified error handling/reporting in ASP.NET Web API 2.1 Project built on top of OWIN middleware (IIS HOST using Owin.Host.SystemWeb). Currently I use

2条回答
  •  -上瘾入骨i
    2020-12-07 17:42

    Ok, so this was easier than anticipated, thanks for @Khalid for the heads up, I have ended up creating an owin middleware named OwinExceptionHandlerMiddleware which is dedicated for handling any exception happening in any Owin Middleware (logging it and manipulating the response before returning it to the client).

    You need to register this middleware as the first one in the Startup class as the below:

    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);
        }
    }
    

    And the code used in the OwinExceptionHandlerMiddleware as the below:

    using AppFunc = Func, 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 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();
        }
    }
    

提交回复
热议问题