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

posted @ 2012-10-26 23:27  KidYang  阅读(2152)  评论(0编辑  收藏  举报