日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

精通ASP.NET MVC ——控制器可扩展性

發(fā)布時(shí)間:2025/3/11 asp.net 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 精通ASP.NET MVC ——控制器可扩展性 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

MVC中引導(dǎo)動(dòng)作方法執(zhí)行過程的請(qǐng)求流程管道中,有兩個(gè)重要的部件:控制器工廠(Controller Factory)動(dòng)作調(diào)用器(Action Invoker)。控制器工廠負(fù)責(zé)創(chuàng)建對(duì)請(qǐng)求進(jìn)行服務(wù)的控制器實(shí)例,動(dòng)作調(diào)用器負(fù)責(zé)查找并調(diào)用控制器類中的動(dòng)作方法。MVC框架中含有這兩個(gè)組件的默認(rèn)實(shí)現(xiàn),可以配置并控制他們的行為,也可以完全替換這些組件。

準(zhǔn)備示例項(xiàng)目

新建一個(gè)空的MVC項(xiàng)目名叫ControllerExtensibility的項(xiàng)目。在Model中添加一個(gè)Result.cs文件,代碼如下圖所示:

namespace ControllerExtensibility.Models {public class Result{public string ControllerName { get; set; }public string ActionName { get; set; }} }

在/Views/Shared文件夾下,添加一個(gè)名稱為Result.cshtml的視圖?,代碼如下:

@model ControllerExtensibility.Models.Result @{Layout = null; }<!DOCTYPE html><html> <head><meta name="viewport" content="width=device-width" /><title>Result</title> </head> <body><div>Controller:@Model.ControllerName</div><div>Action:@Model.ActionName</div> </body> </html>

新增兩個(gè)控制器, Product控制器和Customer控制器,代碼如下圖所示:

public class CustomerController : Controller{// GET: Customerpublic ActionResult Index(){return View("Result",new Result { ControllerName = "Customer",ActionName = "Index" });}public ViewResult List(){return View("Result", new Result { ControllerName = "Customer",ActionName = "Index" });}} public class ProductController : Controller{// GET: Productpublic ActionResult Index(){return View("Result",new Result { ControllerName = "Product",ActionName = "Index" } );}public ViewResult List(){return View("Result", new Result { ControllerName = "Product", ActionName = "List" });}}

這些控制器不執(zhí)行任何有用的動(dòng)作,只是通過Result.cshtml視圖報(bào)告他們已經(jīng)被調(diào)用了。?


創(chuàng)建自定義控制器工廠?

控制器工廠是由IControllerFactory接口定義的,如下圖所示:

public interface IControllerFactory{IController CreateController(RequestContext requestContext, string controllerName);SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);void ReleaseController(IController controller);}

這個(gè)接口中最重要的方法是CreateController,當(dāng)MVC框架需要控制器對(duì)請(qǐng)求進(jìn)行服務(wù)時(shí),便會(huì)調(diào)用這個(gè)方法。該方法的一個(gè)參數(shù)是一個(gè)RequestContext對(duì)象,它讓工廠能夠檢測(cè)請(qǐng)求的細(xì)節(jié),另一個(gè)參數(shù)是一個(gè)字符串,它包含了從路由的URL那里得到所得到的controller值。

GetControllerSessionBehavior 方法由MVC框架用來確定是否應(yīng)該為控制器維護(hù)會(huì)話數(shù)據(jù)。

當(dāng)不在需要CreateController,方法創(chuàng)建的控制器對(duì)象時(shí),會(huì)調(diào)用ReleaseController方法釋放資源。

下面簡(jiǎn)單創(chuàng)建了一個(gè)控制器工廠,代碼如下:

public class CustomControllerFactory : IControllerFactory{public IController CreateController(RequestContext requestContext, string controllerName){Type targetType = null;switch (controllerName){case "Product":targetType = typeof(ProductController);break;case "Customer":targetType = typeof(CustomerController);break;default:requestContext.RouteData.Values["controller"] = "Product";targetType = typeof(ProductController);break;}return targetType == null ? null : (IController)DependencyResolver.Current.GetService(targetType);}public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName){return SessionStateBehavior.Default;}public void ReleaseController(IController controller){IDisposable disposable = controller as IDisposable;if (disposable != null){disposable.Dispose();}}}

以上自定義控制器工廠只會(huì)指向?名叫Product Customer 控制器,并且如果控制器不是這兩個(gè),就默認(rèn)指向Product控制器。

靜態(tài)的DependencyResolver.Current屬性返回IDependencyResolver接口的實(shí)現(xiàn)。該接口定義了GetService方法,為方法傳遞了一個(gè)System.Type對(duì)象。這里可以理解為實(shí)例化一個(gè)目標(biāo)類型對(duì)象。


注冊(cè)使用自定義控制器工廠

通過ControllerBuilder類,可以告訴MVC框架使用這個(gè)自定義的控制器工廠。在Global.asax.cs文件中的Application_Start方法中加入如下代碼即可:

protected void Application_Start() {AreaRegistration.RegisterAllAreas();RouteConfig.RegisterRoutes(RouteTable.Routes);ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());//注冊(cè) }

一旦注冊(cè)了控制器工廠,將由它負(fù)責(zé)處理請(qǐng)求應(yīng)用程序接收到的所有請(qǐng)求,啟動(dòng)程序,就可以看到如下結(jié)果:?

? ? ? ? ? ??


?使用內(nèi)建的控制器工廠

對(duì)于大多數(shù)程序應(yīng)用程序,內(nèi)建的控制器工廠類DefaultControllerFactory完全足夠滿足需求。當(dāng)它從路由系統(tǒng)接收到一個(gè)請(qǐng)求時(shí),該工廠考察路由數(shù)據(jù),找到 Controller 屬性的值,并企圖在這個(gè)Web 應(yīng)用程序中找到滿足如下條件的類:

1、這個(gè)類必須是一個(gè)public類。

2、這個(gè)類必須是具體類(不是抽象類)。

3、這個(gè)類必須沒有泛型參數(shù)。

4、這個(gè)類必須以Contoller結(jié)尾。

5、這個(gè)類必須實(shí)現(xiàn)IController接口。

DefaultControllerFactory類里有這些類的一個(gè)列表,一個(gè)請(qǐng)求到達(dá)時(shí),它并不需要每次都執(zhí)行一次搜索。如果找到了,便用控制器激活器(Controller Activator)創(chuàng)建一個(gè)實(shí)例。


命名空間優(yōu)先排序

如果有同名控制器位于不同命名空間的,需要對(duì)命名空間優(yōu)先排序,在Global.asax.cs文件中的Application_Start方法中加入如下代碼即可:

ControllerBuilder.Current.DefaultNamespaces.Add("MyControllerNamespace"); ControllerBuilder.Current.DefaultNamespaces.Add("MyProject.*");

所有添加命名空間的順序,并不暗示搜索順序或者相對(duì)優(yōu)先級(jí)——?所有Add方法定義的命名空間一視同仁。而優(yōu)先級(jí)是相對(duì)于那些沒有Add的方法。如果控制器在Add方法中定義的命名空間找不到合適的控制器,那就會(huì)搜搜整個(gè)應(yīng)用程序。

上述代碼中第二句的“ * ”表示的是查詢MyProject命名空間及所包含的子命名空間。


定制DefaultControllerFactory的控制器實(shí)例化

也可以通過創(chuàng)建一個(gè)控制器激活器(Controller Activator)對(duì)一個(gè)指定一個(gè)控制器類型進(jìn)行實(shí)例化。代碼如下圖所示:

public class CustomerControllerActivator : IControllerActivator{public IController Create(RequestContext requestContext, Type controllerType){if (controllerType == typeof(ProductController)){controllerType = typeof(CustomerController);}return (IController)DependencyResolver.Current.GetService(controllerType);}}

IControllerActivator的實(shí)現(xiàn)很簡(jiǎn)單——如果請(qǐng)求的是ProductController類,將以CustomerController類的實(shí)例作為其響應(yīng)。?

為了激活這個(gè)自定義控制器,也需要在在Global.asax.cs文件中的Application_Start方法中加入如下代碼:

ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CustomerControllerActivator()));

啟動(dòng)程序并導(dǎo)航到/Product,效果如下圖所示:?

? ? ? ? ? ??


?重寫DefaultControllerFactory方法

可以重寫DefaultControllerFactory類中的方法,來控制控制器的創(chuàng)建。

可重寫的DefaultController方法
方法結(jié)果描述
CreateControllerIControllerIControllerFactory接口的CreatController方法的實(shí)現(xiàn)。默認(rèn)情況下,這個(gè)方法調(diào)用GetControllerType來確定應(yīng)該實(shí)例化哪個(gè)類型,然后通過將結(jié)果傳遞給GetControllerInstance方法,來獲得一個(gè)控制器對(duì)象。
GetControllerTypeType將請(qǐng)求映射到控制器類型。
GetControllerInstanceIController創(chuàng)建指定類型的一個(gè)實(shí)例。

?創(chuàng)建自定義動(dòng)作調(diào)用器

一旦控制器工廠創(chuàng)建了一個(gè)(控制器)類的實(shí)例,框架就需要一種辦法來調(diào)用這個(gè)實(shí)例上的一個(gè)動(dòng)作。如果控制器是通過Controller類派生的,那么將由動(dòng)作調(diào)用器(Action Invoker)調(diào)用動(dòng)作。

動(dòng)作調(diào)用器實(shí)現(xiàn)IActionInvoke接口,如下圖所示:

public interface IActionInvoker{bool InvokeAction(ControllerContext controllerContext, string actionName);}

該接口只有一個(gè)單一的成員:InvokeAction(調(diào)用動(dòng)作)?。其返回值是一個(gè)布爾類型的值,返回true,表示找到并調(diào)用了這個(gè)動(dòng)作方法;false表示控制器沒有匹配的動(dòng)作。

新增一個(gè)CustomActionInvoker.cs文件繼承此接口,代碼如下圖所示:

public class CustomActionInvoker : IActionInvoker{public bool InvokeAction(ControllerContext controllerContext, string actionName){if (actionName == "Index"){controllerContext.HttpContext.Response.Write("This is output from the Index action");return true;}else{return false;}}}

這個(gè)動(dòng)作方法并不關(guān)心控制器類中的方法。它只處理自己的動(dòng)作。如果這是對(duì)Index動(dòng)作的請(qǐng)求,那么該調(diào)用器直接將一條消息寫到Response。如果是對(duì)其他動(dòng)作的請(qǐng)求,則返回false,這將會(huì)導(dǎo)致一個(gè)“404——未找到”的錯(cuò)誤消息給用戶。

與一個(gè)控制器相關(guān)聯(lián)的動(dòng)作調(diào)用器是通過Controller.ActionInvoker屬性獲得的,同一個(gè)應(yīng)用程序中的不同控制器可以試用版不同的動(dòng)作調(diào)用器。新增一個(gè) ActionInvoker的新控制器,代碼如下:

public class ActionInvokerController : Controller{public ActionInvokerController() {this.ActionInvoker = new CustomActionInvoker();}}

這個(gè)控制器中沒有動(dòng)作方法,它依靠動(dòng)作調(diào)用器去處理請(qǐng)求。通過啟動(dòng)程序,并導(dǎo)航到/ActionInvoker/Index,可以看到其工作情況,而導(dǎo)航同一個(gè)控制器中的其他方法則看到404錯(cuò)誤。?如下圖所示:

? ? ? ? ? ? ? ??


使用內(nèi)建的動(dòng)作調(diào)用器?

內(nèi)建的動(dòng)作調(diào)用器ControllerActionInvoker類,有一些將請(qǐng)求與動(dòng)作方法進(jìn)行匹配的非常完善的技術(shù)。默認(rèn)的動(dòng)作調(diào)用器是依靠方法進(jìn)行操作的。為了具備一個(gè)動(dòng)作的資格,一個(gè)方法必須滿足如下幾個(gè)條件:

1、該方法是必須是public的。

2、該方法必須不是staticd的。

3、該方法必須不是在 System.Web.Mvc.Controller或它的任何基類中。

4、該方法沒有專用名。

前兩個(gè)條件很簡(jiǎn)單。第三個(gè)條件排除了Controller類或其基類出現(xiàn)的方法,這意味著不包括ToString及GetHashCode這樣的方法,因?yàn)檫@些都是IController接口實(shí)現(xiàn)的方法。最后一個(gè)條件意味著排除了構(gòu)造器、屬性以及事件訪問器。

注:具有泛型參數(shù)的方法(如 MyMethod<T>() 滿足所有條件,但是如果視圖調(diào)用這樣的方法吹里一個(gè)請(qǐng)求,MVC框架會(huì)報(bào)錯(cuò))。

默認(rèn)情況下,ControllerActionInvoker 查找一個(gè)具有與請(qǐng)求的動(dòng)作同名的方法。?而且,MVC框架提供了一些可以調(diào)整的方法。


使用自定義動(dòng)作名

通常,動(dòng)作方法的名稱確定了它所表示的動(dòng)作。Index動(dòng)作方法對(duì)Index動(dòng)作進(jìn)行服務(wù)。但是可以用ActionName注解屬性來重寫這一行為。如下圖所示:

public class CustomerController : Controller{// GET: Customerpublic ActionResult Index(){return View("Result",new Result { ControllerName = "Customer",ActionName = "Index" });}[ActionName("Enumerate")]public ViewResult List(){return View("Result", new Result { ControllerName = "Customer",ActionName = "Index" });}}

導(dǎo)航到/Customer/Enumerata,效果如下圖所示:?

? ? ? ? ? ? ??

這一注解屬性重寫了動(dòng)作的名稱,這意味著導(dǎo)航到List方法不再工作,如下圖所示:

? ? ? ? ? ??

以這種方式重寫方法名的原因主要有兩個(gè):

1、可以接收一個(gè)作為C# 方法名不合法的動(dòng)作名,例如【ActionName(“User-Registration”】,其中“-”符號(hào)在C#中是不合法的。

2、如果希望有兩個(gè)不同的C#方法接受同一組參數(shù),并且運(yùn)用同樣的動(dòng)作名(具有同樣參數(shù)的方法不能實(shí)現(xiàn)重載,只能采用不同的方法名),但是要對(duì)不同的HTTP請(qǐng)求類型進(jìn)行響應(yīng),例如一個(gè)是【HttpGet】,而另一個(gè)是【HttpPost】那么可以對(duì)這些方法用不同的C#名來滿足編譯器的要求,然后用【ActionName】將他們映射到同一個(gè)動(dòng)作名。


使用動(dòng)作方法選擇?

很多情況是一個(gè)控制器中含有幾個(gè)同名的動(dòng)作,這可能是因?yàn)橛卸鄠€(gè)方法,每個(gè)方法的參數(shù)個(gè)數(shù)不同。或者是使用[ActionName]注解屬性,使多個(gè)方法表示同一個(gè)動(dòng)作。

動(dòng)作調(diào)用器在選擇一個(gè)動(dòng)作時(shí),會(huì)利用動(dòng)作方法選擇器來消除不確定性。比如【HttPost】注解屬性就是一個(gè)動(dòng)作方法的選擇器。首先會(huì)評(píng)估帶動(dòng)作方法選擇器的動(dòng)作,以考察其是否適合處理該請(qǐng)求。

【HttpGet】用于Get請(qǐng)求,【HttpPost】用于Post請(qǐng)求,另一個(gè)內(nèi)建的注解屬性是NonAction(非動(dòng)作),它向動(dòng)作調(diào)用器解釋不應(yīng)該作為作為動(dòng)作方法來使用。如下圖所示:

[NonAction]public ActionResult MyAction(){return View();}

上述代碼中的MyAction方法,將不會(huì)被看成是一個(gè)動(dòng)作。以NonAction方法為目標(biāo)的URL請(qǐng)求會(huì)生成“404——未找到”錯(cuò)誤。另一個(gè)通常的方法是把這些方法標(biāo)記為Private。?


創(chuàng)建自定義動(dòng)作方法選擇器

動(dòng)作方法選擇器派生于ActionMethodSelectorAttribute類,如下圖所示:

//// 摘要:// 表示一個(gè)特性,該特性用于影響操作方法的選擇。[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]public abstract class ActionMethodSelectorAttribute : Attribute{//// 摘要:// 初始化 System.Web.Mvc.ActionMethodSelectorAttribute 類的新實(shí)例。protected ActionMethodSelectorAttribute();//// 摘要:// 確定操作方法選擇對(duì)指定的控制器上下文是否有效。//// 參數(shù):// controllerContext:// 控制器上下文。//// methodInfo:// 有關(guān)操作方法的信息。//// 返回結(jié)果:// 如果操作方法選擇對(duì)指定的控制器上下文有效,則為 true;否則為 false。public abstract bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo);}

ActionMethodSelectorAttribute是一個(gè)抽象類,它定義了一個(gè)抽象方法:IsValidForRequest。該方法的一個(gè)參數(shù)是controllercontext對(duì)象,用來對(duì)請(qǐng)求進(jìn)行檢測(cè),另一個(gè)參數(shù)是MethodInfo對(duì)象,用來獲取運(yùn)用了選擇器方法的信息。如果該方法能處理請(qǐng)求,便返回true,否則便返回false

如下圖中創(chuàng)建了一個(gè)簡(jiǎn)單的自定義選擇器,代碼如下圖所示:

public class LocalAttribute : ActionMethodSelectorAttribute{public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo){return controllerContext.HttpContext.Request.IsLocal;}}

將該動(dòng)作方法選擇器運(yùn)運(yùn)用,創(chuàng)建了Home控制器,代碼如下圖所示:?

public class HomeController : Controller{// GET: Homepublic ActionResult Index(){return View("Result",new Result { ControllerName = "Home",ActionName = "Index"});}[ActionName("Index")]public ActionResult LocalIndex(){return View("Result", new Result { ControllerName = "Home", ActionName = "LocalIndex" });}}

上述代碼創(chuàng)建了兩個(gè)Index動(dòng)作方法,因此,當(dāng)/Home/Index請(qǐng)求達(dá)到時(shí),動(dòng)作調(diào)用器無法猜出應(yīng)該使用哪一個(gè),就會(huì)報(bào)錯(cuò):?

對(duì)Home控制器運(yùn)用注解屬性:

public class HomeController : Controller{// GET: Homepublic ActionResult Index(){return View("Result",new Result { ControllerName = "Home",ActionName = "Index"});}[Local][ActionName("Index")]public ActionResult LocalIndex(){return View("Result", new Result { ControllerName = "Home", ActionName = "LocalIndex" });}}

如果重啟程序,并從本地機(jī)器上運(yùn)行瀏覽器導(dǎo)航到根URL,將會(huì)看到MVC框架已經(jīng)考慮了方法的選擇注解屬性。解決了控制器類中方法之間的歧義問題:?

? ? ? ? ? ? ? ? ??


處理未知?jiǎng)幼?

如果動(dòng)作方法調(diào)用器找不到一個(gè)要調(diào)用的動(dòng)作方法,便從它的InvokerAction方法返回false,當(dāng)這種情況發(fā)生時(shí),Controller類會(huì)調(diào)用它的HandleUnknowAction方法,默認(rèn)情況下,這個(gè)方法會(huì)將一個(gè)“404——未找到”響應(yīng)給客戶端。這是控制器大多數(shù)應(yīng)用程序所能做的最有用的事情。如果想做一些特殊的事情,可以在控制器類中選擇重寫這個(gè)方法。代碼如下圖所示:

public class HomeController : Controller{// GET: Homepublic ActionResult Index(){return View("Result",new Result { ControllerName = "Home",ActionName = "Index"});}[Local][ActionName("Index")]public ActionResult LocalIndex(){return View("Result", new Result { ControllerName = "Home", ActionName = "LocalIndex" });}protected override void HandleUnknownAction(string actionName){Response.Write(string.Format("You requested the {0} action ",actionName));}}

導(dǎo)航到一個(gè)不存在動(dòng)作,如下圖所示:?

? ? ? ? ??


使用無會(huì)話控制器?

默認(rèn)情況下,控制器是支持會(huì)話狀態(tài)的,這可以用來跨請(qǐng)求地存取數(shù)據(jù)值,使MVC程序員的工作更輕松。創(chuàng)建和維護(hù)會(huì)話狀態(tài)是一個(gè)棘手的過程。必須對(duì)數(shù)據(jù)進(jìn)行存儲(chǔ)和接收,且必須對(duì)會(huì)話進(jìn)行管理,以使他們能適當(dāng)?shù)亟K止。會(huì)話數(shù)據(jù)會(huì)消耗服務(wù)器內(nèi)存或一些其他存儲(chǔ)單元空間。而且多個(gè)Web服務(wù)器之間的數(shù)據(jù)同步的需求,使得在服務(wù)器場(chǎng)(server farm)上運(yùn)行應(yīng)用程序更加困難。

為了簡(jiǎn)化會(huì)話狀態(tài),ASP.NET 對(duì)一個(gè)給定的會(huì)話在某一個(gè)時(shí)刻只處理一個(gè)查詢,如果客戶形成了多個(gè)重疊的請(qǐng)求,它們將被排成隊(duì)列,并由服務(wù)器依次處理。其好處是不需要擔(dān)心多個(gè)請(qǐng)求對(duì)同一數(shù)據(jù)進(jìn)行修改的情況,缺點(diǎn)是得不到所希望的請(qǐng)求的吞吐量。

并非所有控制器都需要這種會(huì)話狀態(tài)特性。在這種情況下,能夠改善應(yīng)用程序的性能,而又避免了棘手的會(huì)話狀態(tài)維護(hù)工作。這可以通過無會(huì)話控制器來實(shí)現(xiàn)。它們與規(guī)則控制器一樣,但是有兩個(gè)方面不同:在把它們用于處理一個(gè)請(qǐng)求時(shí),MVC框架不加載或不存儲(chǔ)會(huì)話狀態(tài),重疊請(qǐng)求可以同時(shí)處理。

IControllerFactory接口中,含有一個(gè)叫做“SessionStateBehavior”的方法,該方法返回SessionStateBehavior枚舉中的一個(gè)值。如下圖所示:

SessionStateBehavior枚舉的值
SessionStateBehavior枚舉的值
Default使用默認(rèn)的ASP.NET行為,它會(huì)根據(jù)HttpContext來決定會(huì)話狀態(tài)的配置
Required啟用完全會(huì)話狀態(tài)
ReadOnly啟用只讀會(huì)話狀態(tài)
Disable完全禁用會(huì)話狀態(tài)

通過返回GetControllerSessionBehavior方法的SessionStateBehavior的值,實(shí)現(xiàn)IControllerFactory接口的控制器工廠會(huì)直接設(shè)置控制器會(huì)話狀態(tài)的行為。?傳遞給這個(gè)方法的參數(shù)是RequestContext 和一個(gè)含有控制器名稱的字符串,可以返回如上圖中任意一個(gè)值,也可以根據(jù)不同的控制器返回不同的值,如下圖所示:

public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName) {switch (controllerName){case "Home":return SessionStateBehavior.ReadOnly;case "Prouduct":return SessionStateBehavior.Required;default:return SessionStateBehavior.Default;} }

?用DefaultControllerFactory管理會(huì)話狀態(tài)

當(dāng)使用內(nèi)建的控制器工廠(MVC 應(yīng)用程序默認(rèn)使用的就是這個(gè)默認(rèn)的控制器工廠DefaultControllerFactroy)時(shí),可以將SessionState注解屬性運(yùn)用于每個(gè)控制器類,以便對(duì)控制器的會(huì)話進(jìn)行控制,如下圖所示:

[SessionState(System.Web.SessionState.SessionStateBehavior.Disabled)] public class FastController : Controller {// GET: Fastpublic ActionResult Index(){return View("Result", new Result { ControllerName = "Fast",ActionName = "Index"});} }

上述控制器運(yùn)用了SessionState注解屬性,它影響著該控制器的所有動(dòng)作。?Disable完全禁用了會(huì)話狀態(tài),如果在控制中設(shè)置了一個(gè)會(huì)話值:

Session[" Message "]? = " Hello "

如果想從其他地方試圖讀取這個(gè)值,@Session[" Message "] ,MVC框架會(huì)報(bào)錯(cuò)。HttpContext.Session屬性會(huì)返回Null。

如果制定了Readonly,那么可以讀取從其他控制器設(shè)置的值,但是企圖修改,也會(huì)報(bào)錯(cuò)。


使用異步控制器?

核心ASP.NET 平臺(tái)維護(hù)著一個(gè)用來處理客戶端請(qǐng)求的.NET 線程池。這個(gè)線程池叫做“工作線程池(Work Thread Pool)”,而這些線程叫做“工作線程(Work Thread)”。當(dāng)接受到一個(gè)請(qǐng)求時(shí),將占用線程池中的一個(gè)工作線程,以進(jìn)行這個(gè)請(qǐng)求的處理工作。當(dāng)請(qǐng)求處理完成后,該工作線程被返回給線程池,以便用于新請(qǐng)求的處。對(duì)ASP.NET應(yīng)用程序使用線程池有兩個(gè)好處:

1、通過重用工作線程,避免了每次處理一個(gè)請(qǐng)求時(shí),都要?jiǎng)?chuàng)建一個(gè)新的線程的開銷(創(chuàng)建線程是需要時(shí)間的,若采用現(xiàn)有的線程就不一樣了)。

2、通過具有固定數(shù)目的可用工作線程,避免了超出服務(wù)器處理能力的并發(fā)請(qǐng)求情況。

在請(qǐng)求可以被短時(shí)間處理完畢的情況下,工作線程池工作的最好。這也是大多數(shù)MVC應(yīng)用程序的情況。但是,如果有一些依賴于其他的服務(wù)器且占用較長(zhǎng)時(shí)間才能完成的動(dòng)作,那么你可能會(huì)遇到所有工作線程都被綁定于等待其他系統(tǒng)完成其工作的情況。

此刻服務(wù)器有能力做更多的工作——畢竟,這只是在等待,只占用了很少的資源——但是因?yàn)樗芯€程都被綁定,傳入的請(qǐng)求都被排成隊(duì)列。這將陷入應(yīng)用程序處理停頓,而服務(wù)器大片的閑置的奇怪狀態(tài)。

這一問題的解決方案是使用異步控制器,這是提高應(yīng)用程序的整體性能,但是不利于執(zhí)行異步操作(即可提高性能,但實(shí)現(xiàn)(異步操作)難)。

注意:編寫并發(fā)代碼容易,編寫能夠正常工作的并發(fā)代碼是及其困難的。最好使用默認(rèn)的線程池。特別是對(duì)于新手。即便是老手,也應(yīng)該知道,編寫和測(cè)試一個(gè)新的線程池所付出的努力,與得到的回報(bào)是相比,是微不足道的。

異步控制器只能對(duì)占用I / O 或占用網(wǎng)絡(luò)帶寬,而且非CPU密集型的動(dòng)作是有用的(CPU密集型動(dòng)作是指,需要CPU高負(fù)荷運(yùn)轉(zhuǎn),占用較多內(nèi)存,執(zhí)行大量處理才能完成的動(dòng)作)。??異步控制器解決的問題應(yīng)當(dāng)是,線程池與所處理的請(qǐng)求類型之間搭配不當(dāng)?shù)臓顟B(tài)。線程池意在確保每個(gè)請(qǐng)求到得到一片服務(wù)器資源,但是很可能停滯于一組無所事事的工作線程上。如果對(duì)CPU密集型動(dòng)作使用額外的后臺(tái)線程,那么會(huì)因?yàn)樯婕疤嗟牟l(fā)請(qǐng)求而削弱服務(wù)器資源。

創(chuàng)建一個(gè)RemoteData常規(guī)同步控制器,如下圖所示:?

public class RemoteDataController : Controller{// GET: RemoteDatapublic ActionResult Index(){return View();}public ActionResult Data(){RemoteService service = new RemoteService();string data = service.GetRemoteData();return View((object)data);}}

? ?RemoteService 實(shí)例代碼如下圖所示:

public class RemoteService{public string GetRemoteData(){Thread.Sleep(2000);return "Hello from the other side of world";}}

添加對(duì)動(dòng)作Data的新視圖,如下圖所示?:

@model string @{Layout = null; }<!DOCTYPE html><html> <head><meta name="viewport" content="width=device-width" /><title>Data</title> </head> <body><div> Data:@Model</div> </body> </html>

運(yùn)行效果如下圖所示:?

? ? ? ? ? ? ??


創(chuàng)建異步控制器?

使用關(guān)鍵字await async,創(chuàng)建一個(gè)新的Task對(duì)象,并await它的響應(yīng)。修改Data動(dòng)作器代碼如下圖所示:

public async Task<ActionResult> Data() {RemoteService service = new RemoteService();string data = await Task<string>.Factory.StartNew( () => { return new RemoteService().GetRemoteData(); });return View((object)data); }

在控制器中使用異步方法?

也可以在其他地方通過異步控制器來使用異步方法,在RemoteService.cs中添加如下方法:

public class RemoteService {public string GetRemoteData(){Thread.Sleep(2000);return "Hello from the other side of world";}public async Task<string> GetRemoteDataAsync(){return await Task<string>.Factory.StartNew(() => { Thread.Sleep(2000); return "Hello from the other side of the world"; });} }

在控制器中調(diào)用異步方法:?

public class RemoteDataController : Controller {// GET: RemoteDatapublic ActionResult Index(){return View();}public async Task<ActionResult> Data(){RemoteService service = new RemoteService();string data = await Task<string>.Factory.StartNew( () => { return new RemoteService().GetRemoteData(); });return View((object)data);}public async Task<ActionResult> ConsumeAsyncMethod(){string data = await new RemoteService().GetRemoteDataAsync();return View("Data", (object)data);} }

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

總結(jié)

以上是生活随笔為你收集整理的精通ASP.NET MVC ——控制器可扩展性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲国产欧美一区二区三区深喉 | 鲁一鲁在线视频 | 中字幕视频在线永久在线观看免费 | 蜜乳av中文字幕 | 高潮毛片无遮挡高清免费 | 亚洲av无码一区二区三区人 | 少妇名器的沉沦 | 久久欲| 日一日射一射 | 美女被到爽高潮视频 | 精品欧美一区二区久久久久 | 久久久久国产一区二区三区 | 国产精品区二区三区日本 | 日本人和亚洲人zjzjhd | 欧美一区二区视频在线观看 | 国模人体私拍xvideos | 日韩麻豆视频 | 夜夜操操操 | 一级黄色大片视频 | 少妇偷人精品无码人妻 | 色噜噜狠狠一区二区三区果冻 | www.夜夜| 久久不卡影院 | av福利在线观看 | 瑟瑟在线观看 | 日韩欧美视频免费观看 | 波多野结衣免费在线视频 | 天天操天 | 国产亚洲激情 | 色老头在线一区二区三区 | 午夜精品视频在线 | 男男做性免费视频网 | 国产日本在线观看 | 浪浪视频在线观看 | 日韩一区二区三区免费 | 日韩欧美自拍 | 国产chinese男男网站大全 | 黄色美女片 | 亚洲色图欧美色 | 成人网址在线观看 | 亚洲国产成人在线 | 日韩中文字幕一区二区三区四区 | 95香蕉视频 | 在线一区二区视频 | 中出 在线| 日本人妻丰满熟妇久久久久久 | 亚洲自偷自偷偷色无码中文 | 国产视频福利在线 | 影音先锋男人资源网站 | 久久久久久久色 | 免费看一级黄色大片 | 男人的天堂在线视频 | www麻豆视频 | 91精品免费视频 | 美女精品久久 | 亚洲a视频在线观看 | 色www情 | 一级片在线免费 | 吻胸摸激情床激烈视频大胸 | 四虎最新站名点击进入 | 日本黄色激情视频 | 夜色快播 | 精品久久久久久久久久久aⅴ | 插插插综合 | 18我禁在线观看 | 国产精品99久久久久久久久久久久 | 日韩国产在线一区 | 激情久久婷婷 | 男女视频一区二区 | 国产高清一级片 | www.爆操| 92久久精品一区二区 | 两女双腿交缠激烈磨豆腐 | 风间由美在线视频 | 亚洲美女屁股眼交3 | 快色在线观看 | www.777含羞草 | 久久久久久9999 | 国产ts在线视频 | 亚洲二区在线播放视频 | 精品视频在线免费观看 | 日本xx视频免费观看 | 图书馆的女友动漫在线观看 | 日韩高清免费观看 | 日本午夜一级 | 鬼眼 电影| 91欧美日韩麻豆精品 | 久久久精品欧美 | 欧美成本人视频 | 草1024榴社区成人 | 午夜视频日韩 | 日本高清精品 | 99re这里只有精品在线 | 69xav | 美女黄页在线观看 | 在线午夜电影 | 午夜欧美激情 | 变态另类ts人妖一区二区 | 免费观看黄色av |