<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
        

      MVC系列——一個異常消息傳遞引發的思考

      前言:最近在某個項目里面遇到一個有點糾結的小問題,經過半天時間的思索和嘗試,問題得到解決。在此記錄一下解決的過程,以及解決問題的過程中對.net里面MVC異常處理的思考。都是些老生常談的問題,不多說,直接上“主菜”。

      本文原創地址:http://www.rzrgm.cn/landeanfen/p/8135844.html

      一、問題重現

      項目是一個傳統.net framework的MVC項目,為了簡便,項目里面定義了一個自定義異常類用于向客戶端傳遞錯誤消息,客戶端接收到異常的消息時在瀏覽器里面彈出提示。先來看看這個自定義異常類CustormerException的定義

          public class CustomerException : System.Exception
          {
              public CustomerException()
              {
      
              }
              public CustomerException(string message) : base(message)
              {
      
              }
              public CustomerException(string message, params object[] args) : base(string.Format(message, args))
              {
      
              }
          }

      為了模擬重現問題,我盡量將代碼簡化再簡化。

        [BaseException]
          public class DefaultController : Controller
          {
              // GET: Default
              public ActionResult Index()
              {
                  return View();
              }
      
              public JsonResult Login(string userName, string password)
              {
                  if (userName == "admin" && password == "admin")
                  {
                      return Json(true, JsonRequestBehavior.AllowGet);
                  }
                  else
                  {
                      throw new CustomerException("用戶名或者密碼錯誤");
                  }
              }
          }
      
          public class BaseExceptionAttribute : HandleErrorAttribute
          {
              public override void OnException(ExceptionContext filterContext)
              {
                  if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception is CustomerException)
                  {
                      filterContext.ExceptionHandled = true;
                      filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                      var result = new ContentResult() { Content = filterContext.Exception.Message, ContentType = MediaTypeNames.Text.Plain };
                      filterContext.Result = result;
                  }
                  else
                  {
                      //記錄日志
                  }
      
                  base.OnException(filterContext);
      
              }
          }

      代碼不復雜,就是一個通用的異常過濾器,用于記錄日志和傳遞消息到客戶端。

      然后我們看看客戶端的測試代碼:

      @{
          ViewBag.Title = "Index";
      }
      
      用戶名:<input type="text" id="username"/>
      密碼  :<input type="text" id="password"/>
      <button id="btnAjaxError" type="button">登陸</button>
      @section Script
      {
        <script type="text/javascript">
      
          $(function () {
              $("#btnAjaxError").click(function () {
                  $.ajax({
                      url:"/Default/Login",
                      data: { userName: $('#username').val(), password: $('#password').val() },
                      type: 'post'
                  }).done(function (data) {
                      console.log("successful:"+data);
                  }).fail(function (a, b, c) {
                      debugger;
                      console.log("fail:"+a.responseText);
                  });
              });
          });
      </script>  
      }

      本地調試、運行得到正常結果

       發布到IIS,本地訪問仍然正常。可是當我們遠程訪問的時候問題出現了。

       

      所有的遠程訪問機器上面都出現了系統默認的錯誤消息,而不是我們返回的業務異常消息。

      二、初次嘗試

      對于這種本地能看到詳細異常,而遠程看不到詳細異常的問題,相信有一定經驗的朋友肯定想到了一個配置,那就是Web.config里面的CustomErrors節點,我們配置下默認開啟自定義異常不就行了嗎。嘿嘿!就是這么簡單!博主當初也是這么樂呵呵的去嘗試的。我們在Web.config的System.web節點下面加入這個節點

      <customErrors mode="On"></customErrors>

      可是很遺憾,問題依舊!后來想是不是自己對于On、Off、RemoteOnly的理解有誤?于是乎三個項逐個嘗試,結果均已失敗告終!

      于是乎開始有點郁悶了,這種問題原來怎么沒遇到過了,代碼“貌似”沒什么大問題啊,如果有問題,本地應該也不能得到才對啊。于是乎分析,這可能不是我們代碼的問題,而是IIS給我做了一層統一的異常處理,我們只需要將這層統一的異常處理去掉就行了啊。道理是這么個道理,可是如何去實現呢。于是乎把IIS的各個功能都試了個遍,最后的谷歌的一篇帖子里面找到了一些幫助。解決方案如下。

      三、解決方案

      1、“不是代碼的問題”的解決方案

      上文說到這個問題或許不是代碼的問題,而是IIS配置的問題。于是乎真的讓博主找到了解決方案。解決步驟如下:

       

       

       

      原來,IIS默認是不讓遠程用戶查看異常的詳細錯誤的,如果是遠程用戶,IIS會默認給你返回一個各種狀態碼對應的默認消息,我們自定義的消息將會被此覆蓋。如果改成選中第二項,就表示不管是本地用戶還是遠程用戶均可以看到詳細異常。

      這樣配置之后不用更改任何代碼,不用理會是否配置了CustomErrors節點,遠程用戶均可以正常獲取到程序返回的異常消息:

      2、“是代碼的問題”的解決方案

      有了上面的解決方案,為何還會有“是代碼的問題”的解決方案呢?這才是本文想要表達的中心思想。既然我們通過配置IIS的錯誤頁可以解決這個問題,那么我們為什么不能在程序的范疇內去解決呢?博主是一個有點喜歡刨根問題的人,不斷分析代碼后發現,既然系統的默認錯誤消息可以覆蓋我們的自定義異常消息,那么反過來,我們自定義的異常消息為什么就不能覆蓋系統默認的異常消息呢?于是乎發現在重寫父類的OnException方法的時候,上面的代碼我們是先執行的我們自定義的異常消息,然后再調用 base.OnException(filterContext); 去執行系統默認的異常消息處理的,那么我們將這個順序倒置一下,反過來是不是可行呢?于是代碼就變成了這樣:

        public class BaseExceptionAttribute : HandleErrorAttribute
          {
              public override void OnException(ExceptionContext filterContext)
              {
                  base.OnException(filterContext);
                  if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception is CustomerException)
                  {
                      filterContext.ExceptionHandled = true;
                      filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
                      var result = new ContentResult() { Content = filterContext.Exception.Message, ContentType = MediaTypeNames.Text.Plain };
                      filterContext.Result = result;
                  }
                  else
                  {
                      //記錄日志
                  }
              }
          }

       我們將上面通過配置IIS錯誤頁的解決方案還原,改成默認的配置。去掉CustomErrors節點,重新發布之后,問題完美解決:

      問題能解決,說明博主上面的推想或許是正確的,自定義異常和默認異常是存在一個先后順序的,我們如果要覆蓋系統的異常,需要將我們自定義異常的代碼放在后面執行。這個論斷是通過上述解決問題的思路推理得來的,并不一定正確,有興趣的可以反編譯下dll看下是否真是這樣!

      很有趣的一點就是,這樣改了代碼之后,我們如果在web.config里面加入customErrors節點,并且將mode設置為Off,遠程訪問的時候得到的異常消息又變成了“錯誤的請求”。其實這不難理解,當你禁用自定義錯誤信息,那么系統肯定會給你返回默認的異常信息了。

      四、總結

      由上述的兩種解決方案可以看出這里其實有三道防線:

      第一道防線是最外層的防線,就是IIS的錯誤頁配置,如果這層配置選擇的是詳細錯誤,那么不管你其他的配置是什么樣,都會返回用戶自定義的錯誤信息;

      第二道防線是中間的那層,就是web.config里面的CustomErrors節點,如果第一道防線是默認配置,這層防線才會生效;

      第三道防線才是代碼的范疇,這個受限于CustomErrors節點的配置。

      本文原創出處:http://www.rzrgm.cn/landeanfen/

      歡迎各位轉載,但是未經作者本人同意,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利

      posted @ 2017-12-28 17:37  懶得安分  閱讀(2737)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 白山市| 激情综合网激情五月我去也| 99久久无码私人网站| 四虎在线成人免费观看| 中文字幕有码日韩精品| 国产亚洲精品一区二区无| 97人人超碰国产精品最新| 猫咪社区免费资源在线观看| 最新偷拍一区二区三区| 日韩精品毛片一区到三区| 国产亚洲精品2021自在线| 久久婷婷成人综合色综合| 亚洲一区二区三区激情视频| 亚洲国产精品一区二区久久| 成av人片一区二区久久| 性欧美老妇另类xxxx| 国产午夜成人久久无码一区二区| 中文字幕久久波多野结衣av| 福利一区二区在线观看| 沙湾县| 国产成人精品无码专区| 91精品国产福利尤物免费| 久久蜜臀av一区三区| 熟妇人妻久久精品一区二区| 最新亚洲av日韩av二区| 微拍福利一区二区三区| av高清无码 在线播放| 国产做a爱片久久毛片a片| 武装少女在线观看高清完整版免费 | 国产精品成人午夜福利| 欧美中文字幕在线看| 日本福利一区二区精品| 92久久精品一区二区| 国产午夜亚洲精品国产成人| 99久久婷婷国产综合精品青草漫画 | 孕交videos小孕妇xx| 成人无码区在线观看| 精品国产中文字幕懂色| 狠狠色噜噜狠狠狠狠777米奇| 国产精品永久免费无遮挡| 国产精品一在线观看|