asp.net webapi 404/405/或无效控制器/或无效请求 截取处理统一输出格式 捕获全局异常截取统一处理 修改默认输入格式xml为json

1.截取处理404操作:

WebApiConfig类的Register方法中添加代码:
            config.Routes.MapHttpRoute(
                name: "Error404",
                routeTemplate: "{*url}",
                defaults: new { controller = "Error", action = "Handle404" }
            );

新建base文件夹,新建ErrorController类,继承 System.Web.Http.ApiController,代码如下:

public class ErrorController : ApiController
    {
        [HttpGet, HttpPost, HttpPut, HttpDelete, HttpHead, HttpOptions, AcceptVerbs("PATCH")]
        public RespModel Handle404()
        {
            return new RespModel  //RespModel是本人创建的标准返回结果实体
            {
                issuccess = false,
                code = (int)FF.ApiCommon.FFApiErrorCode.NotFound,
                msg = "404 资源未找到"
            };
        }
    }

2.截取处理405等其他异常操作:

WebApiConfig类的Register方法中添加代码:
config.Services.Replace(typeof(IHttpControllerSelector), new FFNotFoundControllerSelector(config));
config.Services.Replace(typeof(IHttpActionSelector), new FFApiControllerActionSelector());

在base文件夹中新建FFNotFoundControllerSelector类,继承 System.Web.Http.Dispatcher.DefaultHttpControllerSelector,重写父类SelectController方法,代码如下:

public class FFNotFoundControllerSelector : DefaultHttpControllerSelector
    {
        public FFNotFoundControllerSelector(HttpConfiguration configuration)
            : base(configuration)
        {
        }

        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            HttpControllerDescriptor decriptor = null;
            try
            {
                decriptor = base.SelectController(request);
            }
            catch (HttpResponseException ex)
            {
                var code = ex.Response.StatusCode;
                if (code != HttpStatusCode.NotFound)
                    throw;
                var routeValues = request.GetRouteData().Values;
                routeValues["controller"] = "Error";
                routeValues["action"] = "Handle404";
                decriptor = base.SelectController(request);
            }
            return decriptor;
        }
    }

在base文件夹中新建FFApiControllerActionSelector类,继承 System.Web.Http.Controllers.ApiControllerActionSelector,重写父类SelectAction方法,代码如下:

public class FFApiControllerActionSelector : ApiControllerActionSelector
    {
        JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
        public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)
        {
            HttpActionDescriptor decriptor = null;
            try
            {
                decriptor = base.SelectAction(controllerContext);
            }
            catch (HttpResponseException ex)
            {
                RespModel respModel = null;
                var code = ex.Response.StatusCode;
                switch (code)
                {
                    //case HttpStatusCode.NotFound:
                    //    respModel = new RespModel() { code = (int)FF.ApiCommon.FFApiErrorCode.NotFound, issuccess = false, msg = Common.Tools.EnumHelper.GetEnumDescription(ApiCommon.FFApiErrorCode.NotFound) };
                    //    break;
                    case HttpStatusCode.MethodNotAllowed:
                        respModel = new RespModel() { code = (int)FF.ApiCommon.FFApiErrorCode.MethodNotAllowed, issuccess = false, msg = Common.Tools.EnumHelper.GetEnumDescription(ApiCommon.FFApiErrorCode.MethodNotAllowed) };
                        break;
                }
                ex.Response.Content = new ObjectContent(typeof(RespModel), respModel, formatter);
                ex.Response.StatusCode = HttpStatusCode.OK;
                throw;
            }
            return decriptor;
        }
    }

3.捕获全局异常截取统一处理

WebApiConfig类的Register方法中添加Filter过滤器代码:

config.Filters.Add(new WebApiExceptionFilterAttribute());

在base文件夹中新建WebApiExceptionFilterAttribute类,继承System.Web.Http.Filters.ExceptionFilterAttribute,代码如下:

public class WebApiExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            ////1.异常日志记录(正式项目里面一般是用log4net记录异常日志)
            //Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "——" +
            //    actionExecutedContext.Exception.GetType().ToString() + ":" + actionExecutedContext.Exception.Message + "——堆栈信息:" +
            //    actionExecutedContext.Exception.StackTrace);

            //2.返回调用方具体的异常信息
            RespModel respModel = new RespModel { issuccess = false };
            if (actionExecutedContext.Exception is Newtonsoft.Json.JsonSerializationException)
            {
                respModel.msg = "参数有误";
                respModel.code = (int)FF.ApiCommon.FFApiErrorCode.JsonSerializationException;
                //actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
            else if (actionExecutedContext.Exception is NotImplementedException)
            {
                respModel.msg = "此方法未实现";
                respModel.code = (int)FF.ApiCommon.FFApiErrorCode.NotImplementedException;
                //actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
            else if (actionExecutedContext.Exception is TimeoutException)
            {
                respModel.msg = "请求超时";
                respModel.code = (int)FF.ApiCommon.FFApiErrorCode.TimeoutException;
                //actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout);
            }
            else if (actionExecutedContext.Exception is EntityNotFoundException)
            {
                var enfex = (actionExecutedContext.Exception as EntityNotFoundException);
                respModel.msg = enfex.msg;
                respModel.code = enfex.code;
                //actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.RequestTimeout);
            }
            else if (actionExecutedContext.Exception is System.Web.Http.HttpResponseException)
            {
                var enfex = (actionExecutedContext.Exception as System.Web.Http.HttpResponseException);
                respModel.msg = enfex.Message;
                respModel.code = (int)enfex.Response.StatusCode;
            }
            //.....这里可以根据项目需要返回到客户端特定的状态码。如果找不到相应的异常,统一返回服务端错误500
            else
            {

                respModel.msg = actionExecutedContext.Exception.Message + actionExecutedContext.Exception.StackTrace;
                respModel.code = (int)FF.ApiCommon.FFApiErrorCode.OtherException;
                //actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
            var respmessage = new HttpResponseMessage(HttpStatusCode.OK);
            respmessage.Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(respModel));
            actionExecutedContext.Response = respmessage;

            base.OnException(actionExecutedContext);
        }
    }

其中FFApiErrorCode是个异常状态码枚举,代码如下:

public enum FFApiErrorCode
    {
        /// <summary>
        /// 成功 0
        /// </summary>
        [Description("成功")]
        Success = 0,
        /// <summary>
        /// 参数有误 -11
        /// </summary>
        [Description("参数有误")]
        JsonSerializationException = -11,
        /// <summary>
        /// 此方法未实现 -12
        /// </summary>
        [Description("此方法未实现")]
        NotImplementedException = -12,
        /// <summary>
        /// 请求超时 -13
        /// </summary>
        [Description("请求超时")]
        TimeoutException = -13,
        /// <summary>
        /// 数据实体未找到 -14
        /// </summary>
        [Description("数据实体未找到")]
        EntityNotFoundException = -14,
        /// <summary>
        /// 其他异常 -99
        /// </summary>
        [Description("其他异常")]
        OtherException = -99,
        /// <summary>
        /// 未找到 404
        /// </summary>
        [Description("404 资源未找到")]
        NotFound = 404,
        /// <summary>
        /// 405请求的资源不支持 405
        /// </summary>
        [Description("405 请求的资源不支持")]
        MethodNotAllowed = 405
    }

4.修改默认输入格式xml为json

WebApiConfig类的Register方法中添加代码:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
            GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("datatype", "json", "application/json"));
            GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(
                new Newtonsoft.Json.Converters.IsoDateTimeConverter()
                {
                    DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
                }
            );

转载请说明出处:第六感博客 原文链接:

标签: C# Asp.Net

相关阅读:

C#使用RSA非对称加密字符串 附Helper帮助类

asp.net WebPage WebMvc 压缩输出html

asp.net 内置委托 Action 和 Func 和 Predicate

vs生成成功但发布时报错 未能将文件...复制到... 未能找到文件...

FluentData 报错 Error:Could not map ...字段名