ASP.NET Core2.2 IExceptionFilter

用vs2017创建一个ASP.NET Core Web应用程序并选择MVC框架,自动生成了 Startup的类,并配置了错误处理方式:html

if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            app.UseHsts();
        }

简单讲:ajax

  1. 开发环境,直接在当前页面显示错误
  2. 生产环境:跳转到 /Home/Error页面

而在实际开发和生产过程当中,咱们须要:app

  1. 开发环境,咱们有时候会用到ajax调用,须要快速定位错误(好比alert(....))
  2. 生产环境:咱们须要把错误信息保存起来,固然ajax调用的时候不能直接alert一个/Home/Error的html给用户

以下面的代码:框架

Action:

        public IActionResult Edit(int id = 0)
        {
            if (id == 0)  //模拟用户不能修改该Id的内容
                return NotFound("没有操做权限");
            if (id == 1)  //模拟发生异常了
                throw new Exception("错误:error desc");
            return View();
        }
        /// <summary>
        /// ajax调用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Save(int id = 0)
        {
            if (id == 0) //模拟用户不能修改该Id的内容
                return NotFound("没有操做权限");
            if (id == 1) //模拟发生异常了
                throw new Exception("错误:error desc");
            return Content(id + DateTime.Now.ToString());
        }

View(Edit.cshtml)

<div class="text-center">
    id:
    <input type="text" id="TId" />
    <input type="button" value="Save" id="BSave" />
    <span id="SResult"></span>
</div>
@section scripts
    {
    <script>
        $(function () {
            $("#BSave").click(function () {
                $.ajax({
                    type: "post",
                    url: "@Url.Action("Save")",
                    data: { id: $("#TId").val() },
                    success: function (ret) {
                        $("#SResult").html(ret);
                    },
                    error: function (XMLHttpRequest) {
                        if (XMLHttpRequest.responseText != "") {
                            alert(XMLHttpRequest.responseText);
                        }
                        else
                            alert(XMLHttpRequest.status );

                    }
                });
            });
        });
    </script>
}

Ctrl+F5##运行:

好,咱们须要保存错误信息,并更友好的提示ajax调用错误。post

1.添加一个类url

public class FilterException :  IExceptionFilter
    {
        private readonly YKDbContext db;
        private readonly IHostingEnvironment _Env;
        public FilterException(YKDbContext dbContext, IHostingEnvironment env)
        {
            db = dbContext;
            _Env = env;
        }
        public void OnException(ExceptionContext context)
        {
            if (_Env.IsDevelopment())
            {
                if (context.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest")
                {
                    context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    string msg = context.Exception.Message;
                    Exception ex = context.Exception;
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                        msg += ex.Message;
                    }
                    context.Result = new JsonResult(msg);
                    context.ExceptionHandled = true; // 代表异常已处理,客户端可获得正常返回
                }
            }
            else
            {
                string msg = context.Exception.Message;
                Exception ex = context.Exception;
                while (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                    msg += ex.Message;
                }
                //存入db

                if (context.HttpContext.Request.Headers["x-requested-with"] == "XMLHttpRequest")
                {
                    context.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    context.Result = new JsonResult("出错了!已经将错误信息发送给开发人员,开发人员将尽快处理。");
                    context.ExceptionHandled = true; 
                }

            }

        }
    }

2.配置服务
在类Startup的方法ConfigureServices中修改spa

services.AddMvc(options =>
            {
                options.Filters.Add<FilterException>();
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

依然按##Ctrl+F5##运行:
3d

是咱们想要的结果吧?!code

附:Filter里面如何判断Controller是否有ApiController属性htm

bool isApi = context.Filters.Any(ii => ii.GetType().Name == "ApiControllerAttribute");