• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題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關(guān)鍵字專題關(guān)鍵字專題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
    當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

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

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

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

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

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

    一、基本異常處理策略

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

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

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

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

    如果用戶不曾定義相應(yīng)的異常處理Action,依然采用“錯(cuò)誤頁面重定向”方式進(jìn)行異常處理。

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

    為了讓讀者對(duì)上面介紹的異常處理頁面有一個(gè)深刻的理解,我們來進(jìn)行一個(gè)實(shí)例演示。該實(shí)例用于模擬用戶登錄,我們定義了如下一個(gè)只包含用戶名和密碼兩個(gè)屬性的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; }
     }
     }

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

     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操作方法中的認(rèn)證邏輯是這樣的:如果用戶名不是“Foo”則拋出InvalidUserNameException異常;如果密碼不是“password”則拋出UserNamePasswordNotMatchException異常。下面是SignIn操作對(duì)應(yīng)的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初始化時(shí)指定的異常處理策略“myPolicy”定義在如下的配置中。我們專門針對(duì)SignIn操作方法拋出的InvalidUserNameException和UserNamePasswordNotMatchException進(jìn)行了處理,而ErrorMessageSettingHandler是我們自定義的異常處理器,它僅僅用于設(shè)置錯(cuò)誤消息。如下面的代碼片斷所示,如果上述的這兩種類型的異常被拋出,最終的錯(cuò)誤消息會(huì)被指定為“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設(shè)置為默認(rèn)Controller和Action后,開啟我們的應(yīng)用程序。在輸入錯(cuò)誤的用戶名和錯(cuò)誤明碼的情況下在ValidationSummary中將自動(dòng)得到相應(yīng)的錯(cuò)誤消息。

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

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

     <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>

    按照我們上面的異常處理策略,在這種情況下我們將采用“錯(cuò)誤頁面”的方式來進(jìn)行異常處理。也HandleErrorAttribute的處理方式類似,我們支持異常類型和Error View之間的匹配關(guān)系,而這是通過類似于如下的配置來定義的。值得一提的是,這里的異常類型是經(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”,詳細(xì)定義如下所示:

     @{
     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)在我們按照上面的方式運(yùn)行我們的程序,在分別輸入錯(cuò)誤的用戶名和密碼的情況下會(huì)自動(dòng)顯現(xiàn)相應(yīng)的錯(cuò)誤頁面。

    四、自定義ActionInvoker:ExceptionActionInvoker

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

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

     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方法中,當(dāng)執(zhí)行了ExceptionActionInvoker的InvokeAction之后,我們會(huì)將當(dāng)前ExceptionHandlingContext的ModelError轉(zhuǎn)移到當(dāng)前的ModelState中。這就是為什么我們會(huì)通過ValidationSummary顯示錯(cuò)誤信息的原因。對(duì)于我們的例子來說,錯(cuò)誤消息的指定是通過如下所示的ErrorMessageSettingHandler 實(shí)現(xiàn)的,而它僅僅將指定的錯(cuò)誤消息添加到當(dāng)前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)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

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

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

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产精品久久国产精品99盘 | 曰韩精品无码一区二区三区| 99爱在线精品免费观看| 久久久人妻精品无码一区| 国产欧美久久久精品| 亚洲精品你懂的在线观看| 久草热8精品视频在线观看| 亚洲欧洲国产精品你懂的 | 亚洲精品中文字幕乱码三区| 国产精品成人69XXX免费视频| 国产精品欧美一区二区三区不卡 | 久热精品视频第一页| 粉嫩精品美女国产在线观看| 国产成人精品日本亚洲专| 精品欧洲AV无码一区二区男男| 亚洲av无码国产精品色在线看不卡| 国产精品国产三级国产| 视频二区国产精品职场同事| 国产精品自拍一区| 99爱在线精品免费观看| 精品性影院一区二区三区内射| 中文字幕精品无码一区二区| 欧美精品亚洲精品日韩专区| 精品无码国产污污污免费网站国产 | 国产一在线精品一区在线观看| 无码国产精品一区二区免费式芒果| 精品久人妻去按摩店被黑人按中出| 最新国产精品亚洲| 久久精品国产精品亚洲精品| 久久91精品国产91久久户| 999精品视频| 国产91大片精品一区在线观看| 国产综合色在线精品| 精品日韩亚洲AV无码一区二区三区| 亚洲精品国产精品乱码视色 | 99久久婷婷国产综合精品草原| 久久九九有精品国产23百花影院| 国产2021精品视频免费播放 | 日韩精品无码熟人妻视频| 亚洲国产精品久久电影欧美| 久久这里只有精品18|