zoukankan      html  css  js  c++  java
  • ASP.NET Web API编程——异常捕获

    1 向客户端发送错误消息

    使用throw new HttpResponseException()向客户端抛出错误信息。

    HttpResponseException包含两个重载的构造函数,其中一个是构造函数参数类型为HttpResponseMessage,通过其设置状态码,错误消息短语以及消息体内容来向客户端抛出比较详细的错误信息。另一个参数类型为HttpStatusCode,只能设定状态码。

    2自定义异常过滤器

    扩展IExceptionFilter来定义异常过滤器。异常过滤器不会捕获类型为HttpResponseException的异常,下面的异常也无法被异常过滤器捕获:

    1)controller构造器抛出的异常

    2)消息处理器抛出的异常

    3)路由过程中抛出的异常

    4)响应内容序列化与反序列化过程中抛出的异常

    代码示例:

     

    public class CustomExceptionFilterAttribute : ExceptionFilterAttribute 
        {
            public override void OnException(HttpActionExecutedContext context)
            {
                if (context.Exception!=null)
                {
                    LogHelper.LogError(context.Exception);
                }
            }
        }

     

    3 扩展ExceptionHandler和ExceptionLogger

    扩展ExceptionHandler可以捕获大部分异常,包括一些无法被异常过滤器捕获的异常。但是HttpResponseException类型的异常不会被捕获。

    示例代码:

     

    /// <summary>
        /// 自定义的异常处理程序
        /// </summary>
        public class GlobalExceptionHandler : ExceptionHandler
        {
            /// <summary>
            /// 处理异常
            /// </summary>
            /// <param name="context"></param>
            /// <param name="cancellationToken"></param>
            /// <returns></returns>
            public override Task HandleAsync(ExceptionHandlerContext context,CancellationToken cancellationToken)
            {
                if (!ShouldHandle(context))
                {
                    return Task.FromResult(0);
                }
                context.Result = new ErrorResult
                {
                    Request = context.ExceptionContext.Request,
                    Content = "呀! 有异常,请联系管理员"
                };
                return Task.FromResult(0);
            }
            /// <summary>
            /// 判断是否应该处理
            /// 后期扩展,重写方法可过滤掉不需处理的异常
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public override bool ShouldHandle(ExceptionHandlerContext context)
            {
                return true;
            }
            private class ErrorResult : IHttpActionResult
            {
                public HttpRequestMessage Request { get; set; }
                public string Content { get; set; }
                public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
                {
                    HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                    response.Content = new StringContent(Content);
                    response.RequestMessage = Request;
                    return Task.FromResult(response);
                }
            }
        }
    public class GlobalExceptionLogger : ExceptionLogger
        {
            public override Task LogAsync(ExceptionLoggerContext context,CancellationToken cancellationToken)
            {
                if (!ShouldLog(context))
                {
                    return Task.FromResult(0);
                }
                if (context.Exception != null)
                {
                    string msg = ClientInfoAnalysis.GetClientInfo();
                    LogHelper.LogError(context.Exception, msg);
                }
                return Task.FromResult(0);
            }
            /// <summary>
            /// 判断是否应记录异常
            /// 后期重写此方法,可过滤掉不需要记录的异常信息
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            public override bool ShouldLog(ExceptionLoggerContext context)
            {
                if ((context.Exception is System.Web.HttpException))
                {
                    return false;
                }
                return true;
            }
    }
    public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // 加载log4net配置文件
                LogConfigLoading.Load(AppSettings.Log4netPathForWeb);
    
                // 加载Web API服务
                config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(AppSettings.ServicesLocation));
    
                // 全局异常信息处理
                config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
    
                // 全局异常记录
                config.Services.Add(typeof(IExceptionLogger), new GlobalExceptionLogger());
    }
    }

     

    4某些异常无法被捕获的异常

    问题描述

    对于在服务加载过程中的异常,无法通过异常过滤器,即实现了System.Web.Http.Filters.IExceptionFilter接口的过滤器来捕获,也不能通过注册ExceptionLogger来达到目的。解决方法如下:

    public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                try
                {
                    config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(SysSettings.ServicesLocation));
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
    
    //其他代码
    }
    }

    其中ServiceAssembliesResolver为:

    public class ServiceAssembliesResolver : DefaultAssembliesResolver
        {
            //服务插件路径
            private string path;
            public ServiceAssembliesResolver(string path):base()
            {
                this.path = path;
            }
            public override ICollection<Assembly> GetAssemblies()
            {
                //获得已有的服务
                ICollection<Assembly> baseAssemblies = base.GetAssemblies();
                //初始化
                List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
                //加载每一个服务插件
                foreach (string file in Directory.GetFiles(path, "*.dll"))
                {
                    var controllersAssembly = Assembly.LoadFrom(file);
                    assemblies.Add(controllersAssembly);
                }
    
                return assemblies;
            }
        }

    但上述方法很可能不起作用,根本原因在于将config.Services.Replace(typeof(IAssembliesResolver), new ServiceAssembliesResolver(SysSettings.ServicesLocation));放入try-catch块中ServiceAssembliesResolver在实例化的时候不抛出异常,而是当调用GetAssemblies时抛出异常(例如服务插件存储文件夹被删除),此时无法记录异常。那么问题就在于GetAssemblies方法何时被调用,通过跟踪代码发现Register中的所有代码都执行完成才会加载服务解决办法ServiceAssembliesResolver.GetAssemblies中捕获异常并记录下来。

     

     

  • 相关阅读:
    uva 11294 Wedding
    uvalive 4452 The Ministers’ Major Mess
    uvalive 3211 Now Or Later
    uvalive 3713 Astronauts
    uvalive 4288 Cat Vs. Dog
    uvalive 3276 The Great Wall Game
    uva 1411 Ants
    uva 11383 Golden Tiger Claw
    uva 11419 SAM I AM
    uvalive 3415 Guardian Of Decency
  • 原文地址:https://www.cnblogs.com/hdwgxz/p/7856429.html
Copyright © 2011-2022 走看看