<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        ASP.NET MVC下基于異常處理的完整解決方案總結

        來源:懂視網(wǎng) 責編:小采 時間:2020-11-27 22:36:07
        文檔

        ASP.NET MVC下基于異常處理的完整解決方案總結

        ASP.NET MVC下基于異常處理的完整解決方案總結:EntLib的異常處理應用塊(Exception Handling Application Block)是一個不錯的異常處理框架,它使我們可以采用配置的方式來定義異常處理策略。而ASP.NET MVC是一個極具可擴展開發(fā)框架,在這篇文章中我將通過它的擴展實現(xiàn)與EntLib的集成,并提供一個完
        推薦度:
        導讀ASP.NET MVC下基于異常處理的完整解決方案總結:EntLib的異常處理應用塊(Exception Handling Application Block)是一個不錯的異常處理框架,它使我們可以采用配置的方式來定義異常處理策略。而ASP.NET MVC是一個極具可擴展開發(fā)框架,在這篇文章中我將通過它的擴展實現(xiàn)與EntLib的集成,并提供一個完

        EntLib的異常處理應用塊(Exception Handling Application Block)是一個不錯的異常處理框架,它使我們可以采用配置的方式來定義異常處理策略。而ASP.NET MVC是一個極具可擴展開發(fā)框架,在這篇文章中我將通過它的擴展實現(xiàn)與EntLib的集成,并提供一個完整的解決異常處理解決方案。

        一、基本異常處理策略

        我們首先來討論我們的解決方案具體采用的異常處理策略:

        對于執(zhí)行Controller的某個Action方法拋出的異常,我們會按照指定配置策略進行處理。我們可以采取日志記錄、異常替換和封裝這些常用的異常處理方式;

        對于處理后的異常,如果異常處理策略規(guī)定需要將其拋出,則會自動重定向到與異常類型匹配的出錯頁面。我們會維護一個異常類型和Error View的匹配關系;

        對于處理后的異常,如果異常處理策略規(guī)定不需要將其拋出,則會執(zhí)行與當前Action操作相匹配的錯誤處理Action進行處理。異常處理Action方法默認采用“On{Action}Error”這樣的命名規(guī)則,而當前上下文會與異常處理操作方法的參數(shù)進行綁定。除次之外,我們會設置當前ModelState的錯誤信息;

        如果用戶不曾定義相應的異常處理Action,依然采用“錯誤頁面重定向”方式進行異常處理。

        二、通過自定義Action處理異常

        為了讓讀者對上面介紹的異常處理頁面有一個深刻的理解,我們來進行一個實例演示。該實例用于模擬用戶登錄,我們定義了如下一個只包含用戶名和密碼兩個屬性的Model:LoginInfoModel。

         namespace Artech.Mvc.ExceptionHandling.Models
         {
         public class LoginInfo
         {
         [Display(Name ="User Name")]
         [Required(ErrorMessage = "User Name is manadatory!")]
         public string UserName { get; set; }
         
         [Display(Name = "Password")]
         [DataType(DataType.Password)]
         [Required(ErrorMessage = "Password is manadatory!")]
         public string Password { get; set; }
         }
         }

        我們定義了如下一個AccountController,它是我們自定義的BaseController的子類。AccountController在構造的時候調(diào)用基類構造函數(shù)指定的參數(shù)代表異常處理策略的配置名稱。SignIn方法代表用于進行“登錄”的操作,而OnSignInError就表示該操作對應的異常處理操作。如果在SignIn操作中拋出的異常經(jīng)過處理后無需再拋出,則會通過調(diào)用OnSignInError,而此時ModelState已經(jīng)被設置了相應的錯誤消息。

         public class AccountController BaseController
         {
         public AccountController()
         base("myPolicy")
         { }
         
         public ActionResult SignIn()
         {
         return View(new LoginInfo());
         }
         [HttpPost]
         public ActionResult SignIn(LoginInfo loginInfo)
         {
         if (!ModelState.IsValid)
         {
         return this.View(new LoginInfo { UserName = loginInfo.UserName });
         }
         
         if (loginInfo.UserName != "Foo")
         {
         throw new InvalidUserNameException();
         }
         
         if (loginInfo.Password != "password")
         {
         throw new UserNamePasswordNotMatchException();
         }
         
         ViewBag.Message = "Authentication Succeeds!";
         return this.View(new LoginInfo { UserName = loginInfo.UserName });
         }
         
         public ActionResult OnSignInError(string userName)
         {
         return this.View(new LoginInfo { UserName = userName });
         }
         }
        
        

        具體定義在SignIn操作方法中的認證邏輯是這樣的:如果用戶名不是“Foo”則拋出InvalidUserNameException異常;如果密碼不是“password”則拋出UserNamePasswordNotMatchException異常。下面是SignIn操作對應的View的定義:

         @model Artech.Mvc.ExceptionHandling.Models.LoginInfo
         @{
         ViewBag.Title = "SignIn";
         }
         @Html.ValidationSummary()
         @if (ViewBag.Messages != null)
         { 
         @ViewBag.Messages
         }
         @using (Html.BeginForm())
         { 
         @Html.EditorForModel()
         <input type="submit" value="SignIn" />
         }
        
        

        在AccountController初始化時指定的異常處理策略“myPolicy”定義在如下的配置中。我們專門針對SignIn操作方法拋出的InvalidUserNameException和UserNamePasswordNotMatchException進行了處理,而ErrorMessageSettingHandler是我們自定義的異常處理器,它僅僅用于設置錯誤消息。如下面的代碼片斷所示,如果上述的這兩種類型的異常被拋出,最終的錯誤消息會被指定為“User name does not exist!”和“User name does not match password!”。

         <exceptionHandling>
         <exceptionPolicies>
         <add name="myPolicy">
         <exceptionTypes>
         <add name="InvalidUserNameException" 
         type="Artech.Mvc.ExceptionHandling.Models.InvalidUserNameException, Artech.Mvc.ExceptionHandling"
         postHandlingAction="None">
         <exceptionHandlers>
         <add name="ErrorMessageSettingHandler"
         type="Artech.Mvc.ExceptionHandling.ErrorMessageSettingHandler, Artech.Mvc.ExceptionHandling"
         errorMessage="User name does not exist!"/>
         </exceptionHandlers>
         </add>
         <add name="UserNamePasswordNotMatchException" 
         type="Artech.Mvc.ExceptionHandling.Models.UserNamePasswordNotMatchException, Artech.Mvc.ExceptionHandling"
         postHandlingAction="None">
         <exceptionHandlers>
         <add name="ErrorMessageSettingHandler"
         type="Artech.Mvc.ExceptionHandling.ErrorMessageSettingHandler, Artech.Mvc.ExceptionHandling"
         errorMessage="User name does not match password!"/>
         </exceptionHandlers>
         </add> 
         </exceptionTypes>
         </add>
         </exceptionPolicies>
         </exceptionHandling>
        
        

        現(xiàn)在我們通過路由映射將AccountController和Sign設置為默認Controller和Action后,開啟我們的應用程序。在輸入錯誤的用戶名和錯誤明碼的情況下在ValidationSummary中將自動得到相應的錯誤消息。

        三、通過配置的Error View處理異常

        在上面的配置中,針對InvalidUserNameException和UserNamePasswordNotMatchException這兩種異常類型的配置策略都將PostHandlingAction屬性設置為“None”,意味著不會將原來的異常和處理后的異常進行重新拋出。現(xiàn)在我們將該屬性設置為“ThrowNewException”,意味著我們會將處理后的異常重新拋出來。

         <exceptionHandling>
         <exceptionPolicies>
         <add name="myPolicy">
         <exceptionTypes>
         <add name="InvalidUserNameException" type="Artech.Mvc.ExceptionHandling.Models.InvalidUserNameException, Artech.Mvc.ExceptionHandling"
         postHandlingAction="ThrowNewException">
         ...
         <add name="UserNamePasswordNotMatchException" type="Artech.Mvc.ExceptionHandling.Models.UserNamePasswordNotMatchException, Artech.Mvc.ExceptionHandling"
         postHandlingAction="ThrowNewException">
         ...
         </add> 
         </exceptionTypes>
         </add>
         </exceptionPolicies>
         </exceptionHandling>

        按照我們上面的異常處理策略,在這種情況下我們將采用“錯誤頁面”的方式來進行異常處理。也HandleErrorAttribute的處理方式類似,我們支持異常類型和Error View之間的匹配關系,而這是通過類似于如下的配置來定義的。值得一提的是,這里的異常類型是經(jīng)過處理后重新拋出的異常。

         <artech.exceptionHandling>
         <add exceptionType="Artech.Mvc.ExceptionHandling.Models.InvalidUserNameException, Artech.Mvc.ExceptionHandling"
         errorView="InvalideUserNameError"/>
         <add exceptionType="Artech.Mvc.ExceptionHandling.Models.UserNamePasswordNotMatchException, Artech.Mvc.ExceptionHandling"
         errorView="UserNamePasswordNotMatchError"/>
         </artech.exceptionHandling>

        如上面的配置所示,我們?yōu)镮nvalidUserNameException和UserNamePasswordNotMatchException這兩種異常類型定義了不同的Error View,分別是“InvalideUserNameError”和“UserNamePasswordNotMatchError”,詳細定義如下所示:

         @{
         Layout = null;
         }
         <!DOCTYPE html>
         <html>
         <head>
         <title>Error</title>
         </head>
         <body>
         <p style="colorRed; font-weightbold">Sorry,the user name you specify does not exist!</p>
         </body>
         </html>
         
         @{
         Layout = null;
         }
         <!DOCTYPE html>
         <html>
         <head>
         <title>Error</title>
         </head>
         <body>
         <p style="colorRed; font-weightbold">Sorry, The password does not match the given user name!</p>
         </body>
         </html>
        
        

        現(xiàn)在我們按照上面的方式運行我們的程序,在分別輸入錯誤的用戶名和密碼的情況下會自動顯現(xiàn)相應的錯誤頁面。

        四、自定義ActionInvoker:ExceptionActionInvoker

        對于上述的兩種不同的異常處理方式最終是通過自定義的ActionInvoker來實現(xiàn)的,我們將其命名為ExceptionActionInvoker。如下面的代碼片斷所式,ExceptionActionInvoker直接繼承自ControllerActionInvoker。屬性ExceptionPolicy是一個基于指定的異常策略名稱創(chuàng)建的ExceptionPolicyImpl 對象,用于針對EntLib進行的異常處理。而屬性GetErrorView是一個用于獲得作為錯誤頁面的ViewResult對象的委托。整個異常處理的核心定義在InvokeAction方法中,該方法中指定的handleErrorActionName參數(shù)代表的是“異常處理操作名稱”,整個方法就是按照上述的異常處理策略實現(xiàn)的。

         using System;
         using System.Collections.Generic;
         using System.Linq;
         using System.Web;
         using System.Web.Mvc;
         using Artech.Mvc.ExceptionHandling.Configuration;
         using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
         using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
         namespace Artech.Mvc.ExceptionHandling
         {
         public class ExceptionActionInvoker ControllerActionInvoker
         {
         protected ExceptionHandlingSettings ExceptionHandlingSettings{get; private set;}
         protected virtual Func<string, HandleErrorInfo, ViewResult> GetErrorView { get; private set; }
         public ExceptionPolicyImpl ExceptionPolicy { get; private set; }
         public ExceptionActionInvoker(string exceptionPolicy,Func<string, HandleErrorInfo, ViewResult> getErrorView)
         {
         this.ExceptionPolicy = EnterpriseLibraryContainer.Current.GetInstance<ExceptionPolicyImpl>(exceptionPolicy);
         this.GetErrorView = getErrorView;
         this.ExceptionHandlingSettings = ExceptionHandlingSettings.GetSection();
         }
         
         public override bool InvokeAction(ControllerContext controllerContext, string handleErrorActionName)
         {
         ExceptionContext exceptionContext = controllerContext as ExceptionContext;
         if (null == exceptionContext)
         {
         throw new ArgumentException("The controllerContext must be ExceptionContext!", "controllerContext");
         }
         try
         {
         exceptionContext.ExceptionHandled = true;
         if (this.ExceptionPolicy.HandleException(exceptionContext.Exception))
         {
         HandleRethrownException(exceptionContext);
         }
         else
         {
         if (ExceptionHandlingContext.Current.Errors.Count == 0)
         {
         ExceptionHandlingContext.Current.Errors.Add(exceptionContext.Exception.Message);
         }
         ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(exceptionContext);
         ActionDescriptor handleErrorAction = FindAction(exceptionContext, controllerDescriptor, handleErrorActionName);
         if (null != handleErrorAction)
         {
         IDictionary<string, object> parameters = GetParameterValues(controllerContext, handleErrorAction);
         exceptionContext.Result = this.InvokeActionMethod(exceptionContext, handleErrorAction, parameters);
         }
         else
         {
         HandleRethrownException(exceptionContext);
         }
         }
         return true;
         }
         catch (Exception ex)
         {
         exceptionContext.Exception = ex;
         HandleRethrownException(exceptionContext);
         return true;
         }
         }
         protected virtual void HandleRethrownException(ExceptionContext exceptionContext)
         {
         string errorViewName = this.GetErrorViewName(exceptionContext.Exception.GetType());
         string controllerName = (string)exceptionContext.RouteData.GetRequiredString("controller");
         string action = (string)exceptionContext.RouteData.GetRequiredString("action");
         HandleErrorInfo handleErrorInfo = new HandleErrorInfo(exceptionContext.Exception, controllerName, action);
         exceptionContext.Result = this.GetErrorView(errorViewName, handleErrorInfo);
         }
         protected string GetErrorViewName(Type exceptionType)
         {
         ExceptionErrorViewElement element = ExceptionHandlingSettings.ExceptionErrorViews
         .Cast<ExceptionErrorViewElement>().FirstOrDefault(el=>el.ExceptionType == exceptionType);
         if(null != element)
         {
         return element.ErrorView;
         }
         if(null== element && null != exceptionType.BaseType!= null)
         {
         return GetErrorViewName(exceptionType.BaseType);
         }
         else
         {
         return "Error";
         }
         }
         }
         }
        
        

        五、自定義Controller:BaseController

        ExceptionActionInvoker最終在我們自定義的Controller基類BaseController中被調(diào)用的。ExceptionActionInvoker對象在構造函數(shù)中被初始化,并在重寫的OnException方法中被調(diào)用。

         using System;
         using System.Web.Mvc;
         namespace Artech.Mvc.ExceptionHandling
         {
         public abstract class BaseController Controller
         {
         public BaseController(string exceptionPolicy)
         {
         Func<string, HandleErrorInfo, ViewResult> getErrorView = (viewName, handleErrorInfo) => this.View(viewName, handleErrorInfo);
         this.ExceptionActionInvoker = new ExceptionActionInvoker(exceptionPolicy,getErrorView);
         }
         public BaseController(ExceptionActionInvoker actionInvoker)
         {
         this.ExceptionActionInvoker = actionInvoker;
         }
         
         public virtual ExceptionActionInvoker ExceptionActionInvoker { get; private set; }
         
         protected virtual string GetHandleErrorActionName(string actionName)
         {
         return string.Format("On{0}Error", actionName);
         }
         
         protected override void OnException(ExceptionContext filterContext)
         {
         using (ExceptionHandlingContextScope contextScope = new ExceptionHandlingContextScope(filterContext))
         {
         string actionName = RouteData.GetRequiredString("action");
         string handleErrorActionName = this.GetHandleErrorActionName(actionName);
         this.ExceptionActionInvoker.InvokeAction(filterContext, handleErrorActionName);
         foreach (var error in ExceptionHandlingContext.Current.Errors)
         {
         ModelState.AddModelError(Guid.NewGuid().ToString() ,error.ErrorMessage);
         }
         }
         }
         }
         }
        
        

        值得一提的是:整個OnException方法中的操作都在一個ExceptionHandlingContextScope中進行的。顧名思義, 我們通過ExceptionHandlingContextScope為ExceptionHandlingContext創(chuàng)建了一個范圍。ExceptionHandlingContext定義如下,我們可以通過它獲得當前的ExceptionContext和ModelErrorCollection,而靜態(tài)屬性Current返回當前的ExceptionHandlingContext對象。

         public class ExceptionHandlingContext
         {
         [ThreadStatic]
         private static ExceptionHandlingContext current;
         
         public ExceptionContext ExceptionContext { get; private set; }
         public ModelErrorCollection Errors { get; private set; }
         
         public ExceptionHandlingContext(ExceptionContext exceptionContext)
         {
         this.ExceptionContext = exceptionContext;
         this.Errors = new ModelErrorCollection();
         }
         public static ExceptionHandlingContext Current
         {
         get { return current; }
         set { current = value; }
         }
         }
        
        

        在BaseController的OnException方法中,當執(zhí)行了ExceptionActionInvoker的InvokeAction之后,我們會將當前ExceptionHandlingContext的ModelError轉(zhuǎn)移到當前的ModelState中。這就是為什么我們會通過ValidationSummary顯示錯誤信息的原因。對于我們的例子來說,錯誤消息的指定是通過如下所示的ErrorMessageSettingHandler 實現(xiàn)的,而它僅僅將指定的錯誤消息添加到當前ExceptionHandlingContext的Errors屬性集合中而已。

         [ConfigurationElementType(typeof(ErrorMessageSettingHandlerData))]
         public class ErrorMessageSettingHandler IExceptionHandler
         {
         public string ErrorMessage { get; private set; }
         public ErrorMessageSettingHandler(string errorMessage)
         {
         thisErrorMessage = errorMessage;
         }
         public Exception HandleException(Exception exception, Guid handlingInstanceId)
         {
         if (null == ExceptionHandlingContextCurrent)
         {
         throw new InvalidOperationException("");
         }
         
         if (stringIsNullOrEmpty(thisErrorMessage))
         {
         ExceptionHandlingContextCurrentErrorsAdd(exceptionMessage);
         }
         else
         {
         ExceptionHandlingContextCurrentErrorsAdd(thisErrorMessage);
         }
         return exception;
         }
         } 
        

        源代碼從這里下載:http://xiazai.jb51.net/201701/yuanma/ExceptionHandling_jb51.rar

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        ASP.NET MVC下基于異常處理的完整解決方案總結

        ASP.NET MVC下基于異常處理的完整解決方案總結:EntLib的異常處理應用塊(Exception Handling Application Block)是一個不錯的異常處理框架,它使我們可以采用配置的方式來定義異常處理策略。而ASP.NET MVC是一個極具可擴展開發(fā)框架,在這篇文章中我將通過它的擴展實現(xiàn)與EntLib的集成,并提供一個完
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲色在线无码国产精品不卡| 免费中文字幕一级毛片| 日韩成人精品日本亚洲| 亚洲成色WWW久久网站| 一本大道一卡二大卡三卡免费| 免费在线观看污网站| 特级毛片爽www免费版| 亚洲AV无码久久精品成人| 久久国产乱子伦精品免费强| 亚洲国产精品无码久久久秋霞2 | 青青草国产免费久久久下载| 亚洲天堂一区二区三区四区| 无码人妻精品一二三区免费| 亚洲国产精品无码久久九九大片 | 亚洲成a人片7777| 噼里啪啦电影在线观看免费高清 | 国产视频精品免费视频| 亚洲国产AV无码专区亚洲AV| 无码国产精品一区二区免费3p| 亚洲va无码va在线va天堂| 亚洲精品欧洲精品| 中文字幕无码免费久久| 国产av无码专区亚洲av果冻传媒| 91视频免费观看| 亚洲欧洲精品视频在线观看| 成人男女网18免费视频| 免费视频成人国产精品网站| 亚洲精品午夜无码电影网| 最近免费中文字幕mv电影| 亚洲人成网站999久久久综合| 免费一区二区视频| 国产99视频精品免费专区| 亚洲毛片基地4455ww| 国产精品亚洲玖玖玖在线观看| 成人网站免费看黄A站视频| 亚洲伊人久久大香线蕉啊| 免费成人av电影| 久久国产乱子伦免费精品| 无码一区二区三区亚洲人妻| 亚洲AV无码不卡在线播放| 国产精品视频免费一区二区三区|