日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
為ASP.NETMVC擴(kuò)展異步Action功能(上)

編輯推薦:為ASP.NET MVC擴(kuò)展異步Action功能(下)

請(qǐng)求處理方式的改變

在制定基本改造策略之前,我們需要了解ASP.NET MVC框架目前的架構(gòu)及請(qǐng)求處理流程。如下:

◆ 在應(yīng)用程序啟動(dòng)時(shí)(此時(shí)還沒有接受任何請(qǐng)求),將針對(duì)MVC請(qǐng)求的Route策略注冊(cè)至ASP.NET Routing模塊。此時(shí)每個(gè)Route策略(即Route對(duì)象)中的RouteHandler屬性為ASP.NET MVC框架中的MvcRouteHandler。

◆ 當(dāng)ASP.NET Routing模塊接收到一個(gè)匹配某個(gè)Route策略的HTTP請(qǐng)求時(shí),將會(huì)調(diào)用該Route對(duì)象中RouteHandler對(duì)象的GetHttpHandler以獲取一個(gè)HttpHandler,并交由ASP.NET執(zhí)行。MvcRouteHandler永遠(yuǎn)將返回一個(gè)MvcHandler對(duì)象。

◆ MvcHandler在執(zhí)行時(shí),將取出RouteData中的controller值,并以此構(gòu)建一個(gè)實(shí)現(xiàn)了IController接口的控制器對(duì)象,并調(diào)用IController接口的Execute方法執(zhí)行該控制器。

◆ 對(duì)于一個(gè)ASP.NET MVC應(yīng)用程序來說,大部分控制器將會(huì)繼承System.Web.Mvc.Controller類型。Controller類將會(huì)從RouteData獲取action值,并交給實(shí)現(xiàn)IActionInvoker接口的對(duì)象來執(zhí)行一個(gè)Action。

◆ ……

如果我們要將這個(gè)流程改造成異步處理,那么就要讓它符合ASP.NET架構(gòu)中的異步處理方式。ASP.NET架構(gòu)對(duì)于異步請(qǐng)求的處理可以體現(xiàn)在好幾種方式上,例如異步頁(yè)面,異步Http Module等,而最適合目前場(chǎng)合的做法自然是異步Http Handler。為實(shí)現(xiàn)一個(gè)異步Handler,我們需要讓處理請(qǐng)求的Handler實(shí)現(xiàn)IHttpAsyncHandler接口,而不是傳統(tǒng)的IHttpHandler接口。IHttpAsyncHandler接口中的BeginProcessRequest和EndProcessRequest兩個(gè)方法構(gòu)成了.NET中的APM(Aynchronous Programming Model,異步編程模型)模式,可以使用“二段式”的異步調(diào)用來處理一個(gè)HTTP請(qǐng)求。

您應(yīng)該已經(jīng)發(fā)現(xiàn),如果我們要支持異步Action,就必須根據(jù)當(dāng)前的請(qǐng)求信息來確認(rèn)究竟是執(zhí)行一個(gè)IHttpHandler對(duì)象還是IHttpAsyncHandler對(duì)象。而在ASP.NET MVC框架在默認(rèn)情況下是在Http Handler(即MvcHandler對(duì)象)內(nèi)部進(jìn)行控制器的檢查,構(gòu)造和調(diào)用。這為時(shí)已晚,我們必須講這些邏輯提前到Routing過程中才行。幸運(yùn)的是,ASP.NET Routing所支持的IRouteHandler就像是ASP.NET中的IHttpHandlerFactory,可以根據(jù)情況生成不同的Handler來執(zhí)行。因此,我們只要構(gòu)建一個(gè)新的IRouteHandler類型即可。于是就誕生了AsyncMvcRouteHandler——可以想象的出,其中的部分代碼與框架中的MvcHandler相同,因?yàn)樵谝欢ǔ潭壬衔覀兊拇_只是把原本在MvcHandler里做的事情給提前了:

public class AsyncMvcRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        string controllerName = requestContext.RouteData.GetRequiredString("controller");

        var factory = ControllerBuilder.Current.GetControllerFactory();
        var controller = factory.CreateController(requestContext, controllerName);
        if (controller == null)
        {
            throw new InvalidOperationException(...);
        }

        var coreController = controller as Controller;
        if (coreController == null)
        {
            return new SyncMvcHandler(controller, factory, requestContext);
        }
        else
        {

            string actionName = requestContext.RouteData.GetRequiredString("action");
            return IsAsyncAction(coreController, actionName, requestContext) ?
                (IHttpHandler)new AsyncMvcHandler(coreController, factory, requestContext) :
                (IHttpHandler)new SyncMvcHandler(controller, factory, requestContext);
        }
    }

    internal static bool IsAsyncAction(
        Controller controller, string actionName, RequestContext requestContext)
    {
        ...
    }
}

在GetHttpHandler方法中,我們先從RouteData的controller字段中獲取控制器的名字,并通過注冊(cè)在ControllerBuilder上的Factory來創(chuàng)建一個(gè)實(shí)現(xiàn)了IController接口的控制器對(duì)象。由于我們需要使用Controller類中包含的ActionInvoker來輔助檢測(cè)Action的異步需求,因此我們會(huì)設(shè)法將其轉(zhuǎn)化為Controller類型。如果轉(zhuǎn)換成功,就會(huì)取出RouteData中的action字段的值,并通過IsAsyncAction方法來確認(rèn)當(dāng)前Action是否應(yīng)該異步執(zhí)行。如果是,則返回一個(gè)實(shí)現(xiàn)了IHttpAsyncHandler的AsyncMvcHandler對(duì)象,否則就返回一個(gè)實(shí)現(xiàn)IHttpHandler的SyncMvcHandler對(duì)象。

至于AsyncMvcRouteHandler的使用,只需在MapRoute時(shí)將Route Handler重新設(shè)置一下即可:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    ).RouteHandler = new AsyncMvcRouteHandler();
}

#p#

檢查是否為異步Action

從上面的代碼中我們已經(jīng)形成了一個(gè)約定:如果要執(zhí)行一個(gè)異步Action,那么控制器對(duì)象必須為Controller類型。這個(gè)約定的目的是為了使用Controller類中包含的IActionInvoker——確切地說,是ControllerActionInvoker類型里的功能。因此,另一個(gè)約定便是Controller的ActionInvoker對(duì)象必須返回一個(gè)ControllerActionInvoker的實(shí)例。

ControllerActionInvoker中有一些輔助方法,能夠返回對(duì)于一個(gè)Controller或Action的描述對(duì)象。從一個(gè)Action描述對(duì)象中我們可以獲取關(guān)于這個(gè)Action的各種信息,而它是否被標(biāo)記了AsyncActionAttribute,就是我們判斷這個(gè)Action是否應(yīng)該被異步執(zhí)行的依據(jù)。如下:

private static object s_methodInvokerMutex = new object();
private static MethodInvoker s_controllerDescriptorGetter;

internal static bool IsAsyncAction(
    Controller controller, string actionName, RequestContext requestContext)
{
    var actionInvoker = controller.ActionInvoker as ControllerActionInvoker;
    if (actionInvoker == null) return false;

    if (s_controllerDescriptorGetter == null)
    {
        lock (s_methodInvokerMutex)
        {
            if (s_controllerDescriptorGetter == null)
            {
                BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
                MethodInfo method = typeof(ControllerActionInvoker).GetMethod(
                    "GetControllerDescriptor", bindingFlags);
                s_controllerDescriptorGetter = new MethodInvoker(method);
            }
        }
    }

    var controllerContext = new ControllerContext(requestContext, controller);
    var controllerDescriptor = (ControllerDescriptor)s_controllerDescriptorGetter.Invoke(
        actionInvoker, controllerContext);
    var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
    return actionDescriptor == null ? false :
        actionDescriptor.GetCustomAttributes(typeof(AsyncActionAttribute), false).Any();
}

ControllerActionInvoker類型中有個(gè)protected方法GetControllerDescriptor,它接受一個(gè)ControllerContext類型的參數(shù),并返回一個(gè)ControllerDescriptor對(duì)象來描述當(dāng)前控制器,而從該描述對(duì)象中可以通過FindAction方法獲得一個(gè)ActionDescriptor對(duì)象來描述即將執(zhí)行的Action。如果是一個(gè)不存在的Action,那么就返回false,***就通過SyncMvcHandler對(duì)象來執(zhí)行默認(rèn)的行為。當(dāng)且僅當(dāng)該Action上擁有AsyncActionAttribute標(biāo)記時(shí),才說明它應(yīng)該被異步執(zhí)行,返回true。此外,這段代碼中用到了MethodInvoker,這是一個(gè)輔助類,它來源于Fast Reflection Library,它實(shí)現(xiàn)了反射調(diào)用功能,但是它的性能十分接近于方法的直接調(diào)用,我在這篇文章中詳細(xì)描述了這個(gè)項(xiàng)目的功能和使用。

這段代碼便涉及到ASP.NET MVC RC版本在Beta版本基礎(chǔ)上的改進(jìn)。在原先的ControllerActionInvoker類中只有獲取Action方法的MethodInfo,而沒有RC中各描述對(duì)象這樣的抽象類型。從目前的設(shè)計(jì)上來看,我們使用的都是基于反射的抽象描述類型的子類。例如默認(rèn)情況下,我們通過ActionDescriptor抽象類型訪問的實(shí)際上是ReflectedActionDescriptor類型的實(shí)例。這是一個(gè)很有用的改進(jìn),由于我們通過描述對(duì)象進(jìn)行抽象,于是我們就可以:

◆ 使用不同的實(shí)現(xiàn)方式來描述各對(duì)象,默認(rèn)情況下是使用基于反射(也就是“約定”)的實(shí)現(xiàn),如果需要的話我們也可以使用基于配置文件的方式替換現(xiàn)有實(shí)現(xiàn)。

◆ 使用特定對(duì)象的描述方式可以不拘泥于內(nèi)部細(xì)節(jié),例如一個(gè)異步的Action可能就由兩個(gè)方法組成。

◆ 有了特定的描述對(duì)象,也方便添加額外的屬性,例如該Action是否應(yīng)該異步執(zhí)行,是否應(yīng)該禁用Session State等等。

◆ ……


新聞標(biāo)題:為ASP.NETMVC擴(kuò)展異步Action功能(上)
轉(zhuǎn)載來于:http://www.5511xx.com/article/cdpedsp.html