----------------------------------------------
提示:.net 4.0 使用 async 和 await 时:Nuget中 加载 Microsoft.Bcl.Async !
----------------------------------------------
一、控制器工厂(IControllerFactory)
1.作用:负责创建对请求进行服务的控制器实例
2.方法:(1)CreateController(RequestContext requestContext,string controllerName)
--MVC框架需要控制器对请求进行服务时调用。创建能够对当前请求进行处理的实例。
(2)SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext,string controllerName)
--指定处理请求所需的会话支持的类型。是否应该为控制器维护会话数据。
(3)ReleaseController(IController controller) --资源释放。
RequestContext属性
名称 | 类型 | 描述 |
HttpContext | HttpContextBase | HTTP请求的信息 |
RouteData | RouteData | 与请求匹配的路由信息 |
3.默认控制器工厂(DefaultControllerFactory)
(1)与路由中controller匹配的类的要求:
public类
具体类(不是抽象类)
没有泛型(Generic)参数
以Controller结尾
实现IController接口
(2)创建自定义控制器工厂:对默认工厂的设置进行配置,或重写它的一些方法。
(3)命名空间优先:Global优先级会被路由优先级所重写。:用户可以定义一个全局策略,然后在必要时定制个别路由。
//全局策略:命名空间Myprojdet下的所有子空间优先相对与其它命名空间,本身没有优先顺序,是一视同仁的 ControllerBuilder.Current.DefaultNamespaces.Add("Myprojdet.*");
(4)定制控制器实例化:1.使用依赖性解析器;2.使用控制器激活器
(5)重写DefaultControllerfactory方法
可重写的DefaultControllerfactory方法
方法 | 结果 | 描述 |
CreateController | IController | IControllerFactory接口的CreateController方法的实现。默认这个方法调用GetControllerType来确认控制器实例化的类型,将结果传递给GetControllerInstance方法来获得一个控制器对象。 |
GetControllerType | Type | 将请求映射到控制器类型。 |
GetControllerInstance | IController | 创建指定类型的实例。 |
二、动作调用器(IActionInvoker)负责查找并调用控制器类中的动作方法
1.动作调用器是包含在Controller类中的一部分功能。
2.当控制器通过Controller类派生而来时,动作是由动作调用器(IActionInvoker)来调用,当直接通过IController接口创建控制器时,则要自己去负责执行动作。
3.bool InvokeAction(ControllerContext controllerContext,string actionName)
true表示找到并调用了这个动作;false表示控制器没有匹配的动作(返回401-未找到)。
注:动作是一种行为,而动作方法是实现这种行为的代码。动作调用器的作用:实现对一个动作的调用,而控制器中才是实现这个动作的动作方法。
4.Controller.ActionInvoker属性获得或设置控制器相关联的动作调用器。(不建议使用)
5.内建动作调用器(ControllerActionInvoker):依靠(动作)方法进行操作。 方法条件:
该方法必须是public
不是Static(静态方法)
必须不在System.Web.Mvc.Controller、或它的任何基类中。(不能与所有父类方法重复,如:ToString、GetHashCode)
没有专用名(构造器、属性、事件访问器)。
不是泛型方法(抛异常)
6.使用自定义方法名:
使用注解属性[ActionName("Enumerate")]
[ActionName("Enumerate")] public ViewResult List() { return View("Result", new Result() { ControllerName = "Customer", ActionName = "List" }); }
重写原因:
1.可以接收一个C#方法名不合法的动作名([ActionName("List-Enumerate")])
2. 如果希望有两个不同的C#方法接收同一组参数,并且运用同样的动作名,但却要对不同的HTTP请求类型进行响应。
7.使用动作方法选择:派生于ActionMethodSelectorAttribute类
[HttpPost] [HttpGet] [HttpPut] .....[NonAction](404-NotFound)
调用器会优先考虑具有选择器的动作。
动作方法的去歧义过程:
首先,调用器会根据名称尽可能的丢弃掉一些方法(名称不相同)。
其次,调用器丢弃选择器注解属性返回false的动作方法。
此时,得到一个方法就调用,多个方法就抛异常。没有找到继续:
再次,查找不带注解属性的方法。
此时,得到一个方法就调用,多个方法就抛异常。
处理未知动作:
InvokeAction返回false,调用HandleUnknownAction方法,返回“404-未找到”。可以重写此方法:
protected override void HandleUnknownAction(string actionName) { Response.Write(string.Format("你请求的{0}方法不存在!" ,actionName)); }
三、特殊控制器:提高应用程序的请求处理能力!!!!!
ViewBag特性是不受会话状态影响的。
1.使用无会话控制器(DefaltControllerFactory):用于处理一个请求时,MVC框架不加载或不存储会话的状态;重叠请求可以同时处理。
SessionStateBehavior枚举值
值 | 描述 | HttpContext.Session值 |
Default | 使用默认的ASP.NET行为,根据HttpContext来决定会话状态的配置 | / |
Required | 启用完全的读写会话状态 | / |
ReadOnly | 启用只读会话状态 | Session["name"]修改会抛异常 |
Disabled | 完全禁用会话状态 | null,Session["name"]读取、修改都会抛异常 |
DefaltControllerFactory管理会话状态:将SessionState注解属性运用于每一个控制器类(不能用于Action方法)。
[SessionState(SessionStateBehavior.Disabled)] public class ProductController : Controller { 。。。。。。 }
2.异步控制器:
工作线程:工作线程池中的一个工作线程。
工作线程池:用来处理客户请求的.net线程池。
当收到一个请求时,将占用一个工作线程,以进行对请求进行处理,当处理完成后,该线程被返回线程池(不回收)等待处理下一个请求。
使用线程池的好处:
1.通过重用工作线程,避免每次处理请求时,创建新线程的开销。
2.通过具有固定数目的可用工作线程,避免了超出服务器处理能力的并发请求情况。
当出现依赖于其他服务器、且占用较长时间才能完成的请求时,就会出现线程被占用,处于等待状态,使用应用程序处理停顿,
而服务器又大片闲置的状态,此时可以使用异步控制器。
异步控制器只能对占用I/O或占用网络带宽,而且非CPU密集型的动作是有用的。解决的问题应当是线程池与
所处理的请求类型之间搭配不当的情况。线程池意在确保每一个请求得到一片服务器资源,但很可能最终停滞于一组无所事事的工作线程上。
如果对CPU密集弄动作使用额外的后台线程,那么会因为涉及太多的并发请求而削弱服务器资源。
System.Web.Mvc.AsyncController对控制器派生,创建一个新的Task对象并await它的响应。
使用异步控制器的作用:在等待异步方法调用结束期间,不会绑定工作线程,减少服务器的压力。
public async Task<ActionResult> AsyncMethod() { //调用 RemoteService对象的异步方法 string data = await new RemoteService().GetStringAsync(); return View("Data", (object) data); } public async Task<ActionResult> DataAsync() { //调用 RemoteService对象的同步方法 string data = await Task<string>.Factory.StartNew( () => new RemoteService().GetRemoteData()); return View((object) data); }