您的位置:首页 > 编程语言 > ASP

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

2017-08-31 11:27 489 查看
前两天刚写过一篇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 请求当出现错误时都有友好提示功能了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: