1. 程式人生 > >ASP.NET MVC涉及到的5個同步與非同步二

ASP.NET MVC涉及到的5個同步與非同步二

Action方法的執行具有兩種基本的形式,即同步執行和非同步執行,而在ASP.NETMVC的整個體系中涉及到很多同步/非同步的執行方式,雖然在前面相應的文章中已經對此作了相應的介紹,為了讓讀者對此有一個整體的瞭解,我們來做一個總結性的論述。[本文已經同步到《How ASP.NET MVC Works?》中]

目錄 
一、MvcHandler的同步於非同步 
二、Controller的同步與非同步 
三、ActionInvoker的同步與非同步 
四、ControllerDescriptor的同步與非同步 
五、ActionDescriptor的同步與非同步

一、MvcHandler的同步與非同步

對於ASP.NET MVC應用來說,MvcHandler是最終用於處理請求的HttpHandler,它是通過UrlRoutingModule這個實現了URL路由的HttpModule被動態對映到相應的請求的。MvcHandler藉助於ControllerFactory啟用並執行目標Controller,並在執行結束後負責對啟用的Controller進行釋放,相關的內容請參與本書的第3章“Controller的啟用”。如下面的程式碼片斷所示,MvcHandler同時實現了IHttpHandler和IHttpAsyncHandler介面,所以它總是呼叫BeginProcessRequest/EndProcessRequest方法以非同步的方式來處理請求

   1: public class MvcHandler : IHttpAsyncHandler, IHttpHandler, ...
   2: {
   3:     //其他成員   
   4:     IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
   5:     void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result);
   6:
void IHttpHandler.ProcessRequest(HttpContext httpContext);
   7: }

二、Controller的同步與非同步

Controller也具有同步與非同步兩個版本,它們分別實現了具有如下定義的兩個介面IController和IAsyncController。當啟用的Controller物件在MvcHandler的BeginProcessRequest方法中是按照這樣的方式執行的:如果Controller的型別實現了IAsyncController介面,則呼叫BeginExecute/EndExecute方法以非同步的方式執行Controller;否則Controller的執行通過呼叫Execute方法以同步方式執行

   1: public interface IController
   2: {    
   3:     void Execute(RequestContext requestContext);
   4: }
   5: public interface IAsyncController : IController
   6: {    
   7:     IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state);
   8:     void EndExecute(IAsyncResult asyncResult);
   9: }

預設情況下通過Visual Studio的嚮導建立的Controller型別是抽象型別Controller的子類。如下面的程式碼片斷所示,Controller同時實現了IController和IAsyncController這兩個介面,所以當MvcHandler進行請求處理時總是以非同步的方式來執行Controller。

   1: public abstract class Controller : ControllerBase, IController, IAsyncController, ...
   2: {
   3:     //其他成員
   4:     protected virtual bool DisableAsyncSupport
   5:     {
   6:         get{return false;}
   7:     }
   8: }

但是Controller型別具有一個受保護的只讀屬性DisableAsyncSupport用於表示是否禁用對非同步執行的支援。在預設情況下,該屬性值為False,所以預設情況下是支援Controller的非同步執行的。如果我們通過重寫該屬性將值設定為True,那麼Controller將只能以同步的方式執行。具體的實現邏輯體現在如下的程式碼片斷中:BeginExecute方法在DisableAsyncSupport屬性為True的情況下通過呼叫Execute方法(該方法會呼叫一個受保護的虛方法ExecuteCore最終對Controller進行同步執行);否則通過呼叫BeginExecuteCore/EndExecuteCore以非同步方式執行Controller。

   1: public abstract class Controller: ...
   2: {
   3:     //其他成員
   4:     protected virtual IAsyncResult BeginExecute(RequestContext requestContext, 
   5:     AsyncCallback callback, object state)
   6:     {
   7:         if (this.DisableAsyncSupport)
   8:         {
   9:             //通過呼叫Execute方法同步執行Controller
  10:         }
  11:         else
  12:         {
  13:             //通過呼叫BeginExecuteCore/EndExecuteCore方法非同步執行Controller
  14:         }
  15: }
  16:     protected override void ExecuteCore();
  17:     protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state);
  18:     protected virtual void EndExecuteCore(IAsyncResult asyncResult);
  19: }

三、 ActionInvoker的同步與非同步

包括Model繫結與驗證的整個Action的執行通過一個名為ActionInvoker的元件來完成,而它同樣具有同步和非同步兩個版本,分別實現了介面IActionInvoker和IAsyncActionInvoker。如下面的程式碼片斷所示,這兩個介面分別通過InvokeAction和BeginInvokeAction/EndInvokeAction方法以同步和非同步的方式執行Action。抽象類Controller中具有一個ActionInvoker屬性用於設定和返回用於執行自身Action的ActionInvoker物件,而該物件最終是通過受保護需方法CreateActionInvoker建立的。

   1: public interface IActionInvoker
   2: {
   3:     bool InvokeAction(ControllerContext controllerContext, string actionName);
   4: }
   5:  
   6: public interface IAsyncActionInvoker : IActionInvoker
   7: {
   8:     IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state);
   9:     bool EndInvokeAction(IAsyncResult asyncResult);
  10: }
  11:  
  12: public abstract class Controller
  13: {   
  14:     //其它成員
  15:     public IActionInvoker ActionInvoker { get; set; }
  16:     protected virtual IActionInvoker CreateActionInvoker()
  17: }

ASP.NET MVC真正用於Action方法同步和非同步執行的ActionInvoker分別是ControllerActionInvoker和AsyncControllerActionInvoker。如下面的程式碼片斷所示,ControllerActionInvoker定義了一個受保護的方法GetControllerDescriptor用於根據指定的Controller上下文獲取相應的ControllerDescriptor,它的子類AsyncControllerActionInvoker對這個方法進行了重寫。

   1: public class ControllerActionInvoker : IActionInvoker
   2: {
   3:     //其它成員
   4:     protected virtual ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext);
   5: }
   6:  
   7: public class AsyncControllerActionInvoker : ControllerActionInvoker,IAsyncActionInvoker, IActionInvoker
   8: {
   9:     //其它成員
  10:    protected override ControllerDescriptor GetControllerDescriptor(ControllerContext controllerContext);
  11: }

我們所有要了解的是在預設情況下(沒有對Controller型別的ActionInvoker屬性進行顯式設定)採用的ActionInvoker型別是哪個。ASP.NET MVC對Conroller採用的ActionInvoker型別的選擇機制是這樣的:

  • 通過當前的DependencyResolver以IAsyncActionInvoker介面去獲取註冊的ActionInvoker,如果返回物件不為Null,則將其作為預設的ActionInvoker。
  • ·通過當前的DependencyResolver以IActionInvoker介面去獲取註冊的ActionInvoker,如果返回物件不為Null,則將其作為預設的ActionInvoker。
  • 建立AsyncControllerActionInvoker物件作為預設的ActionInvoker。

在預設的情況下,當前的DependencyResolver直接通過對指定的型別進行反射來提供對應的例項物件,所以對於前面兩個步驟返回的物件均為Null,所以預設創建出來的ActionInvoker型別為AsyncControllerActionInvoker。我們可以通過如下一個簡單的例項來驗證這一點。在通過Visual Studio的ASP.NET MVC專案模板建立的空Web應用中,我們建立瞭如下一個預設的HomeController,在Action方法Index中直接通過ContentResult將ActionInvoker屬性的型別名稱呈現出來。

   1: public class HomeController : Controller
   2: {  
   3:     public ActionResult Index()
   4:     {
   5:         return Content("預設ActionInvoker型別:" + this.ActionInvoker.GetType().FullName);
   6:     }
   7: }

當執行該Web應用時,會在瀏覽器上產生如下的輸出結果,我們可以清楚地看到預設採用的ActionInvoker型別正是AsyncControllerActionInvoker。

   1: 預設ActionInvoker型別:System.Web.Mvc.Async.AsyncControllerActionInvoker

為了進一步驗證基於DependencyResolver對ActionInvoker的提供機制,我們將《ASP.NET MVC Controller啟用系統詳解:IoC的應用[下篇]》建立的基於Ninject的自定義NinjectDependencyResolver應用在這裡。如下面的程式碼片斷所示,在初始化NinjectDependencyResolver的時候,我們將IActionInvoker和IAsyncActionInvoker影射到兩個自定義ActionInvoker型別,即FooActionInvoker和FooAsyncActionInvoker,它們分別繼承自ControllerActionInvoker和AsyncControllerActionInvoker。

   1: public class NinjectDependencyResolver : IDependencyResolver
   2: {
   3:     public IKernel Kernel { get; private set; }
   4:     public NinjectDependencyResolver()
   5:     {
   6:         this.Kernel = new StandardKernel();
   7:         AddBindings();
   8:     }
   9:     private void AddBindings()
  10:     {
  11:         this.Kernel.Bind<IActionInvoker>().To<FooActionInvoker>();
  12:         this.Kernel.Bind<IAsyncActionInvoker>().To<FooAsyncActionInvoker>();
  13:     }
  14:     public object GetService(Type serviceType)
  15:     {
  16:         return this.Kernel.TryGet(serviceType);
  17:     }
  18:     public IEnumerable<object> GetServices(Type serviceType)
  19:     {
  20:         return this.Kernel.GetAll(serviceType);
  21:     }
  22: }
  23: public class FooActionInvoker : ControllerActionInvoker
  24: {}
  25: public class FooAsyncActionInvoker : AsyncControllerActionInvoker
  26: {}

在Global.asax中對NinjectDependencyResolver進行註冊後執行我們的程式,會在瀏覽器中得到如下的輸出結果。IAsyncActionInvoker和FooAsyncActionInvoker進行了影射,NinjectDependencyResolver可以通過IAsyncActionInvoker提供一個FooAsyncActionInvoker例項。

   1: 預設ActionInvoker型別:Artech.Mvc.FooAsyncActionInvoker

現在我們對NinjectDependencyResolver的定義稍加修改,將針對IAsyncActionInvoker介面的型別影射刪除,只保留針對IActionInvoker的對映。

   1: public class NinjectDependencyResolver : IDependencyResolver
   2: {
   3:     //其它成員
   4:     private void AddBindings()
   5:     {
   6:         this.Kernel.Bind<IActionInvoker>().To<FooActionInvoker>();
   7:         //this.Kernel.Bind<IAsyncActionInvoker>().To<FooAsyncActionInvoker>();

            
           

相關推薦

ASP.NET MVC涉及到的5同步非同步

Action方法的執行具有兩種基本的形式,即同步執行和非同步執行,而在ASP.NETMVC的整個體系中涉及到很多同步/非同步的執行方式,雖然在前面相應的文章中已經對此作了相應的介紹,為了讓讀者對此有一個整體的瞭解,我們來做一個總結性的論述。[本文已經同步到《How

ASP.NET MVC 入門5、ViewViewData

本系列文章基於ASP.NET MVC Preview5. view在MVC模式中與使用者進行最直接的接觸,它負責資料的呈現。這裡要注意一點就是,view只是負責資料的呈現,所以我們應該要儘量讓view中不涉及業務邏輯的處理。 我們來新增一個Blog首頁的view。在安裝了ASP.NET MVC後,我們在新

ASP.NET MVC Identity 兩連接字符串問題解決一例

fail conn init led user asp identity 字符串 initial 按照ASP.NET MVC Identity建立了一個用戶權限管理模塊,由於還要加自己已有的數據庫,所以建立了一個實體模型,建立了之後,發現登錄不了: 一直顯示“Login i

ASP.NET MVC編程——錯誤處理日記

CP 引用 args context mvc4 strong gpo pub family ASP.NET MVC的錯誤處理應考慮到這幾個方面:模型綁定期間發生的錯誤,未能路由到指定操作,針對控制器的錯誤處理。使用配置文件可以幫助我們處理異常,但是不夠靈活和全面;使用Han

ASP.NET MVC同時支持webwebapi模式

mod AR center 擴展 ica app attr host 版本 原文地址:https://blog.csdn.net/laymat/article/details/65444701 我們在創建 web mvc項目時是不支持web api的接口方式訪問的,所以我

ASP.NET MVC@model多對象

type eat ret str idt urn 問題 同時 em1 需求:同時查看一個產品信息和發布會員的信息 方案1:新建ViewModel 方案2:ViewData、ViewBag 方案3:Tuple<obj1,obj2> 在這裏我們使用方

c# ASP.NET MVC模式 WPS的匯入匯出的實現

前提準備:  1.想要成功進行WPS的匯入與匯出,你得先下載WPS,然後找到etapi.dll檔案(路徑:\Kingsoft\WPS Office\10.1.0.7520\office6),WPS安裝路徑看你們具體的安裝路徑。  2.然後在自己的ASP.NET MVC

asp.net mvc 裡的Url.ActionUrl.RenderAction

其實,asp.net mvc 裡的Url.Action與Url.RenderAction,這根本就是兩個不同類的東西,不能相提並論。唯一有聯絡的,就是都跟action有關。記錄下來,主要是做個備忘錄。

ASP.NET MVC 入門8、ModelState資料驗證

ViewData有一個ModelState的屬性,這是一個型別為ModelStateDictionary的ModelState型別的字典集合。在進行資料驗證的時候這個屬性是比較有用的。在使用Html.ValidationMessage()的時候,就是從ViewData.ModelState中檢測是否有指定的K

ASP.NET MVC 入門4、ControllerAction

本系列文章基於ASP.NET MVC Preview5. Controller是MVC中比較重要的一部分。幾乎所有的業務邏輯都是在這裡進行處理的,並且從Model中取出資料。在ASP.NET MVC Preview5中,將原來的Controller類一分為二,分為了Controller類和Controller

ASP.NET MVC 入門7、Hellper資料的提交繫結

本系列文章基於ASP.NET MVC Preview5. ASP.NET MVC提供了很多Hellper的方法,Hellper就是一些生成HTML程式碼的方法,方便我們書寫HTML程式碼(有一部分的朋友更喜歡直接寫HTML程式碼)。我們也可以利用.NET 3.5的擴充套件方法來書寫我們自己的Hellper。

Asp.net Mvc Preview 5 體驗--實現ActionSelectionAttribute來判斷是否為AJAX請求而選擇不同的Action

ActionSelectionAttribute是ASP.NET MVC Preview 5 提供的一個抽象基類,通過ActionSelectionAttribute的命名我們就可以猜想到這個Attribute是用來選擇(匹配)Action方法的。該抽象類只提供了一個抽象的方法 IsValidForReque

ASP.NET MVC使用UEditor,並Controller共享

今天有人問我個小問題,我還是記錄一下吧。 在ASP.NET MVC下使用UEditor是一件很簡單的事情: 1、首先下載UEditor的JS。 2、定義一個實體類: public class Article { [Key] pu

【 .Net碼農】認識ASP.NET MVC5種AuthorizationFilter

在總體介紹了篩選器及其提供機制(《深入探討ASP.NET MVC的篩選器》)之後,我們按照執行的先後順序對四種不同的篩選器進行單獨介紹,首先來介紹最先執行的AuthorizationFilter。從命名來看,AuthorizationFilter用於完成授權相關的工作,所以它應該在Action方法被呼叫之前執

Asp.NET MVC 使用 SignalR 實現推送功能(Hubs 線上聊天室 獲取儲存使用者資訊)

簡單介紹 在上一篇中,我們只是介紹了簡單的訊息推送,今天我們來修改一下,實現儲存訊息,歷史訊息和使用者線上 使用者登入註冊資訊 當用戶登入之後,我們註冊一下使用者的資訊,我們在ChatHub中 新建一個方法 Register(使用者帳號,使用者密碼) 前臺js呼叫這個方法實現使用者註冊 

【無私分享:從入門到精通ASP.NET MVC】從0開始,一起搭框架、做專案(5.4) 登入功能的實現,建立登入使用者相關的介面和實現類

索引 簡述 今天我們建立幾個與登入使用者相關的資料表的介面和實現類 專案準備 我們用的工具是:VS 2013 + SqlServer 2012 + IIS7.5 希望大家對ASP.NET MVC有一個初步的理解,理論性的東西我們不做過多解釋,有些地方不理解也沒關係,會用就行了,用的多了,用的久了

ASP.NET MVC 5 Controllers and Actions

del png asp.net obj into sse ascx stat wan Creating a Controller with IController All controller classes must implemet IController interf

ASP.NET MVC 排球計分程序 (三)需求分析數據庫設計

arch 情況 img 需求 全場 ima 功能 每次 str 需求分析: 軟件名稱:排球計分程序 1、 需要鍵入比賽人員的的姓名,需要根據場上的比賽結果及時做出操作,記分員可以在記錯的情況下撤銷上一部操作。比賽結束,記分員應能查詢到每個隊伍的進球情況,以及攔網、擊球等的

asp.net mvc中如何處理字符串對象之間的序列化反序列化(一)

osi strong 類結構 plain pbo edate inf esc arp 前臺我們一般用ajax來發送數據到後端進行處理,如果json數據結構和後臺的實體類結構一致,就直接可以反序列化為指定的對象進行操作,非常方便。 前端發送的json數據結構: 後端實體結

asp.net MVC 5 路由 Routing

onf 模型 控制 ace 讓我 view 字符 blog cal ASP.NET MVC ,一個適用於WEB應用程序的經典模型 model-view-controller 模式。相對於web forms一個單一的整塊,asp.net mvc是由連接在一起的各種代碼層所組成