asp.net mvc当出现错误时如何实现友好错误提示

前两天刚写过一篇asp.net mvc实现 错误异常记录功能的实现。考虑到在我以前的 webform 项目中是有当出现500 错误时有友好提示功能的,也打算在 MVC 中实现此功能。在我的 LogExceptionAttribute 类的 OnException 方法中增加以下代码:

 //通知MVC框架,现在这个异常已经被我处理掉,你不需要将黄页显示给用户
 filterContext.ExceptionHandled = true;
 /跳转到错误提醒页面               
 filterContext.Result = new ViewResult { ViewName = "error" };

跳转的页面是error.cshtml , error.cshtml 在网站根目录的 views/shared 下,代码如下:


@model System.Web.Mvc.HandleErrorInfo
@{
    Layout = null;
    ViewBag.Title = "错误";
}
<html>
<body>
    <h3 style="color:#6699cc;border-bottom:1px solid #8cb2d9;padding-left:20px;">【 错误提示 】</h3>
    <div style="padding-left:45px;line-height:35px;color:#666">

        很抱歉,您要访问的页面无法正确显示,可能是因为如下原因:<br />
        1 . 系统过于繁忙,请点击浏览器的“刷新”按钮,或稍后再试。<br />
        2 . 您输入的网址有误,请重新检查您输入的网址。 <br />
        3 . 此页面已经删除,请访问其他页面。 <br />
        4 . <a href="/">返回首页</a> <br />

    </div>
</body>
</html>

这里的Layout 要设置为等于 null ,否则 error.cshtml 页面会继承默认的视图模板。这就大致实现了,当有500错误时,自动跳转到 error 页面显示友好提示信息。但还有瑕疵。第一个,在本地测试时,自然是不需要 友好提示的。因此需要增加如果是本地,则不显示友好提示。

if (!Utility.IsLocal())  //非本地,并且需要自定义错误时执行
{
     //通知MVC框架,现在这个异常已经被我处理掉,你不需要将黄页显示给用户
     filterContext.ExceptionHandled = true;
     //跳转到错误提醒页面               
     filterContext.Result = new ViewResult { ViewName = "error" };
}

IsLocal 方法的代码:

/// <summary>
        /// 是否本地服务器
        /// </summary>
        /// <returns></returns>
        public static bool IsLocal()
        {
            string address = RequestHelper.GetServerIp();
            //本地不作处理
            if (address.Contains("192.168."))
            {
                return true;
            }
            return false;
        }

第二个瑕疵,如果是json 请求,而出现的错误,这个跳转就无能为力了。因此需要为json 异常单独处理。创建json 异常过滤器,代码如下:

 /// <summary>
    /// json异常处理,只能使用在action上。调用方法
    /// 在json的action上直接使用[JsonException]
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class JsonExceptionAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                //返回异常JSON
                //filterContext.Result = new JsonResult
                //{
                //    Data = new { Success = false, Message = filterContext.Exception.Message }
                //};

                //{"Message":"尝试除以零。"}
                //filterContext.Result = new JsonResult { Data=new { filterContext.Exception.Message } };

                //{"str":"尝试除以零。"}
                //var str = filterContext.Exception.Message;
                //filterContext.Result = new JsonResult { Data = new { str } };

                var json = new JsonResult();
                json.Data = filterContext.Exception.Message;
                filterContext.Result = json;
            }
        }
    }

这里有个坑,由于我的json 异常信息习惯使用的是 return Json("删除成功");这样的方式返回给客户端 ,客户端通常使用 alert或者其他弹出插件直接获取返回的信息。因此在写代码时首先使用的filterContext.Result = new JsonResult { Data=new { filterContext.Exception.Message } }; 这代码在测试中发现没有弹出提示。用 fiddler 查看json 返回的值却发现是{"Message":"尝试除以零。"} 这种形式,这并不是我想要的。又尝试如下代码:

var str = filterContext.Exception.Message;
filterContext.Result = new JsonResult { Data = new { str } };

通过 fiddler 查看,返回值变成了:{"str":"尝试除以零。"} ,好不郁闷。最终多次尝试后使用

var json = new JsonResult();
json.Data = filterContext.Exception.Message;
filterContext.Result = json;
可以得到我想要的结果。调用就是在返回Jsonresult 结果的 action上增加 [JsonException] ,代码如下:

 /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="oldPassword"></param>
        /// <param name="newPassword"></param>
        /// <returns></returns>
        [HttpPost]
        [JsonException]
        public async Task<JsonResult> ChangePassword(string oldPassword, string newPassword)

实现这个功能后,还需要对  LogExceptionAttribute 类进行修改,当 判断为json 请求时不做处理。修改好的代码如下:

 /// <summary>
    /// 错误日志记录
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public class LogExceptionAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            if (!filterContext.ExceptionHandled)
            {
                #region 记录错误日志
                string controllerName = (string)filterContext.RouteData.Values["controller"];
                string actionName = (string)filterContext.RouteData.Values["action"];
                string msgTemplate = string.Format("在执行 controller[{0}] 的 action[{1}] 时产生异常", controllerName, actionName);
                EventLog.LogItem item = new EventLog.LogItem();
                item.Title = msgTemplate;
                LogManage.WriteException(filterContext.Exception, item);
                #endregion
                if (!(filterContext.Result is JsonResult))  //当非JsonResult并且需要自定义错误页面时
                {
                    if (!Utility.IsLocal())  //非本地,并且需要自定义错误时执行
                    {
                        //通知MVC框架,现在这个异常已经被我处理掉,你不需要将黄页显示给用户
                        filterContext.ExceptionHandled = true;
                        //跳转到错误提醒页面               
                        filterContext.Result = new ViewResult { ViewName = "error" };
                    }

                }

            }


            if (filterContext.Result is JsonResult)
            {
                //当结果为json时,设置异常已处理,此时要在action上调用JsonException属性
                filterContext.ExceptionHandled = true;
            }
            else
            {
                //否则调用原始设置
                base.OnException(filterContext);
            }
        }
    }


这样就完整的实现了 MVC 中无论是页面,还是 json 请求当出现错误时都有友好提示功能了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值