asp.net mvc3异常处理和身份验证

发布时间:2019-08-08编辑:脚本学堂
asp.net mvc3 异常处理 身份验证

    本文介绍 asp.net mvc3异常处理和身份验证 的相关内容,正在学习asp.net mvc3的兄弟们,可以参考下。现在项目是这样处理的,如果兄弟们更好的方法,分享给我哦。

    异常处理
    这里我写的是全局捕获异常,捕获一些我们漏掉的异常。一般我们都会自定义500和400。

在web.config中这样写

复制代码 代码如下:
<customErrors mode="RemoteOnly" defaultRedirect="500">
  <error statusCode="500" redirect="500"/>
  <error statusCode="404" redirect="404"/>
</customErrors>

这里的500和400是路由过去的,在Global中添加

复制代码 代码如下:

 // 500 错误
 routes.MapRoute("500", "500", new { controller = "SiteStatus", action = "_500" });

// 404
routes.MapRoute("404", "404", new { controller = "SiteStatus", action = "_404" });

对应的,有一个 SiteStatusController,其中包含_500 action和_404 action

在Global中,可以看到默认的异常处理机制

复制代码 代码如下:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}

在mvc项目新建一文件夹Common放我们公用的类,新建一类AppHandleErrorAttribute继承HandleErrorAttribute,重写OnException方法
 

复制代码 代码如下:
public class AppHandleErrorAttribute : HandleErrorAttribute
 {
    public override void OnException(ExceptionContext filterContext)
    {
        // 记日志
        ILogger log = LogManager.GetCurrentClassLogger();
        Exception ex = filterContext.Exception;
        if (ex is WebException)
        {
           log.Error("自定义异常(WebException):", ex);
      // 表示异常已处理,直接跳到500显示错误消息
            filterContext.ExceptionHandled = true;
            filterContext.Result = new RedirectToRouteResult("500", new RouteValueDictionary(new
             {
                 message = ex.Message
                }));
            }
            else
            {
                log.Error("系统异常:", ex);
            }
        }
 }

WebAppexception的定义

复制代码 代码如下:

   /// <summary>
    /// 此异常是后端和前端交互使用,后端可以抛出异常,包含异常的信息,前端捕获WebException,并将错误信息显示给用户
    /// 未捕获的异常可以在Global中处理(记日志)
    /// </summary>
    [Serializable]
    public class WebException : ApplicationException
    {
        public WebException() { }

        public WebException(string message)
            : base(message)
        {

        }

        public WebException(string message, Exception innerException)
            : base(message, innerException)
        {

        }
        protected WebException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
    }

现在我们把 filters.Add(newHandleErrorAttribute()); 换成 filters.Add(new AppHandleErrorAttribute());

AppHandleErrorAttribute 处理之后还是会跳转到500页面,500方法的定义

复制代码 代码如下:
 /// <summary>
 /// 500
 /// </summary>
 public ActionResult _500(string message = "处理您的请求时出错,请联系管理员或稍后重试。")
 {
    // 如果是ajax请求我们返回-1024,前台有捕获
       if (Request.IsAjaxRequest())
       {
           return Json(new { Code = -1024 }, JsonRequestBehavior.AllowGet);
       }
       else
       {
          ViewBag.Message = message;
          return View();
       }
}

如果是ajax请求我们return View()不行,那么我们返回一个json给前端的ajax请求

前端的ajax请求也要处理一下

复制代码 代码如下:

    // 重写jquery.ajax使能处理服务端异常,以及处理ModelBase
    var ajax = jQuery.ajax;
    jQuery.ajax = function (settings) {
        // 自定义异常消息
        var exceptionMsg = settings["exceptionMsg"] || "处理您的请求时出错,请联系管理员或稍后重试。";
        // 异常跳转方式 1:弹框, 2:跳转到错误页面
        var redirectType = settings["type"] || 1;

        // 开启自动处理Model,默认关闭
        var enableModelHandle = settings["enableModelError"] || false;

        var successCallback = settings["success"];
        // 在success中处理,jquery.ajax的error函数好像不能写,频繁报错
        settings["success"] = function (model) {
            // 这里处理异常(在服务器,ajax 未捕获的异常,会返回 -1024)
            if (model.Code === -1024) {
                if (redirectType === 1) {
                    alert(exceptionMsg);
                }
                else {
                    location.href = "/500";
                }
            }
            // 不是异常,处理ModelBase
            else {
                // 开启了自动处理Model
                if (enableModelHandle) {
                    // 现在是直接弹框显示后端定义的Message
                    alert(model.Message);
                }
                // 如果定义了success函数,则调用它,并传入model
                libra.isFunction(successCallback) && successCallback.call(null, model);
            }
        }
        // 调用jquery.ajax函数,把我们已经写好的settings传过去。
        ajax(settings);
    }

好了,这样前后台结合一下就基本可以了。

身份验证
新建一个默认的mvc项目的时候可以看到模版中有的action添加了Authorize特性

复制代码 代码如下:
 [Authorize]
 public ActionResult ChangePassword()
  {
      return View();
 }

这个也可以添加在controller上,嫌麻烦的话,可以新建一个BaseController,然后所有的Controller继承它就可以了。

这里我们还是在Common中添加一类AppAuthorizeAttribute,继承AuthorizeAttribute,重写它的OnAuthorization方法

复制代码 代码如下:

public class AppAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            // 过滤不需要验证的页面   allowGuestPages.Add("controllerName", "|actionName1|actionName2|");
            // 过滤整个控制器用 allowGuestPages.Add("controllerName", "all");
            Dictionary<string, string> allowGuestPages = new Dictionary<string, string>();
            allowGuestPages.Add("home", "all");
            allowGuestPages.Add("onlineuser", "all");

            string currentControllerName = MvcUtil.GetControllerName(filterContext.RouteData).ToLower();
            string currentActionName = MvcUtil.GetActionName(filterContext.RouteData).ToLower();

            string allowActions = string.Empty;
            if (allowGuestPages.TryGetValue(currentControllerName, out allowActions))
            {
                allowActions = allowActions.ToLower();
                if (allowActions == "all" || allowActions.Contains("|" + currentActionName + "|"))
                {
                    return;
                }
            }

            // 没有登录,跳到登录页面
            if (!OnlineUser.Instantce.IsLogin())
            {
                filterContext.Result = new RedirectToRouteResult("login", routeValues);
            }
        }
    }

在Global文件中RegisterGlobalFilters方法再添加一筛选器,如下

复制代码 代码如下:
 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new AppHandleErrorAttribute());
            filters.Add(new AppAuthorizeAttribute());
        }

好了,大功告成,不用在每个controller加Authorize了。

原文链接:http://www.cnblogs.com/baobeiyu/archive/2012/10/26/2740931.html