用ASP.NET MVC源代码寻找解决方案

开发 后端
本文介绍用ASP.NET MVC源代码寻找解决方案,具体实现非常容易,在这里就展示一下异步Action的编写方式。

ASP.NET MVC源代码来寻找解决方案,由于在Action方法中可以调用BeginXxx方法,我们在AsyncActionResult中只需保留Begin方法返回的IAsyncResult,以及另一个对于EndXxx方法的引用。在AsyncActionResult的ExecuteResult方法中将会保存这两个对象,以便在AsyncMvcHandler的EndProcessRequest方法中重新获取并使用。根据“惯例”,我们还需要定义一个扩展方法,方便开发人员在Action方法中返回一个AsyncActionResult。具体实现非常容易,在这里就展示一下异步Action的编写方式:

  1. [AsyncAction]  
  2. publicActionResultAsyncAction(AsyncCallbackasyncCallback,objectasyncState)  
  3. {  
  4. SqlConnectionconn=newSqlConnection("...;AsynchronousProcessing=true");  
  5. SqlCommandcmd=newSqlCommand("WAITFORDELAY'00:00:03';",conn);  
  6. conn.Open();  
  7.  
  8. returnthis.Async(  
  9. cmd.BeginExecuteNonQuery(asyncCallback,asyncState),  
  10. (ar)=> 
  11. {  
  12. intvalue=cmd.EndExecuteNonQuery(ar);  
  13. conn.Close();  
  14. returnthis.View();  
  15. });  

至此,似乎AsyncMvcHandler也无甚秘密可言了:

  1. publicclassAsyncMvcHandler:IHttpAsyncHandler,IRequiresSessionState  
  2. {  
  3. publicAsyncMvcHandler(  
  4. Controllercontroller,  
  5. IControllerFactorycontrollerFactory,  
  6. RequestContextrequestContext)  
  7. {  
  8. this.Controller=controller;  
  9. this.ControllerFactory=controllerFactory;  
  10. this.RequestContext=requestContext;  
  11. }  
  12.  
  13. publicControllerController{get;privateset;}  
  14. publicRequestContextRequestContext{get;privateset;}  
  15. publicIControllerFactoryControllerFactory{get;privateset;}  
  16. publicHttpContextContext{get;privateset;}  
  17.  
  18. publicIAsyncResultBeginProcessRequest(  
  19. HttpContextcontext,  
  20. AsyncCallbackcb,  
  21. objectextraData)  
  22. {  
  23. this.Context=context;  
  24. this.Controller.SetAsyncCallback(cb).SetAsyncState(extraData);  
  25.  
  26. try  
  27. {  
  28. (this.ControllerasIController).Execute(this.RequestContext);  
  29. returnthis.Controller.GetAsyncResult();  
  30. }  
  31. catch  
  32. {  
  33. this.ControllerFactory.ReleaseController(this.Controller);  
  34. throw;  
  35. }  
  36. }  
  37.  
  38. publicvoidEndProcessRequest(IAsyncResultresult)  
  39. {  
  40. try  
  41. {  
  42. HttpContext.Current=this.Context;  
  43. ActionResultactionResult=this.Controller.GetAsyncEndDelegate()(result);  
  44. if(actionResult!=null)  
  45. {  
  46. actionResult.ExecuteResult(this.Controller.ControllerContext);  
  47. }  
  48. }  
  49. finally  
  50. {  
  51. this.ControllerFactory.ReleaseController(this.Controller);  
  52. }  
  53. }  

在BeginProcessRequest方法中将保存当前Context——这点很重要,HttpContext.Current是基于 CallContext的,一旦经过一次异步回调HttpContext.Current就变成了null,我们必须重设。接着将接收到的 AsyncCallback和AsyncState保留,并使用框架中现成的Execute方法执行控制器。当Execute方法返回时一整个Action方法的调用流程已经结束,这意味着其调用结果——即IAsyncResult和EndDelegate对象已经保留。于是将IAsyncResult对象取出并返回。至于EndProcessRequest方法,只是将BeginProcessRequest方法中保存下来的EndDelegate取出,调用,把得到的ActionResult再执行一遍即可。

以上的代码只涉及到普通情况下的逻辑,而在完整的代码中还会包括对于Action方法被某个Filter终止或替换等特殊情况下的处理。此外,无论在BeginProcessRequest还是EndProcessRequest中都需要对异常进行合适地处理,使得Controller Factory能够及时地对Controller对象进行释放。

如果这个解决方案没有缺陷,那么相信它已经被放入ASP.NET MVC 1.0中,而轮不到我在这里扩展一番了。目前的这个解决方案至少有以下几点不足:

没有严格遵守.NET中的APM模式,虽然不影响功能,但这始终是一个遗憾。

由于利用了框架中的现成功能,所有的Filter只能运行在BeginXxx方法上。

由于EndXxx方法和最终ActionResult的执行都没有Filter支持,因此如果在这个过程中抛出了异常,将无法进入ASP.NET MVC建议的异常处理功能中。

根据ASP.NET MVC框架的Roadmap,ASP.NET MVC框架1.0之后的版本中将会支持异步Action,相信以上这些缺陷到时候都能被弥补。不过这就需要大量的工作,这只能交给ASP.NET MVC团队去慢慢执行了。事实上,您现在已经可以在ASP.NET MVC源代码的MvcFutures项目中找到异步Action处理的相关内容。它添加了 IAsyncController,AsyncController,IAsyncActionInvoker,AsyncControllerActionInvoker 等许多扩展。虽说它们都“继承”了现有的类,但是与我之前的判断相似,如AsyncControllerActionInvoker几乎完全重新实现了一遍ActionInvoker中的各种功能——我还没有仔细阅读代码,因此无法判断出这种设计是否优秀,只希望它能像ASP.NET MVC本身那样的简单和优雅。

我打算为现在的代码的EndXxx方法也加上Filter支持,我需要仔细阅读ASP.NET MVC源代码来寻找解决方案。希望它能够成为ASP.NET MVC正式支持异步Action之前较好的替代方案。

【编辑推荐】

  1. ASP.NET的AsyncState参数
  2. ASP.NET MVC执行异步Action
  3. 概述ASP.NET MVC框架
  4. ASP.NET MVC中使用UpdataModel方法
  5. ASP.NET MVC的Action方法
责任编辑:佚名 来源: IT168
相关推荐

2009-04-02 11:00:09

微软ASP.NETMVC

2012-01-11 10:55:02

ASP.NET MVC

2009-07-24 11:24:33

ASP.NET中文乱码

2009-07-22 17:37:06

ASP.NET Ses

2009-07-24 13:20:44

MVC框架ASP.NET

2009-07-31 12:43:59

ASP.NET MVC

2009-07-23 16:53:17

ASP.NET中文变问

2010-09-02 15:18:42

CSSASP.NET

2009-07-20 10:53:59

ASP.NET MVC

2009-07-22 10:09:59

ASP.NET MVC

2009-07-23 14:31:20

ASP.NET MVC

2009-07-23 15:44:39

ASP.NET MVC

2009-07-22 13:24:24

ASP.NET MVC

2009-07-30 16:02:53

2010-06-04 19:06:47

连接MySQL数据库

2010-06-23 15:44:03

ASP.NET MVC

2009-07-22 13:08:55

拯救UpdatePanASP.NET MVC

2010-03-19 09:17:16

ASP.NET MVC

2009-07-24 11:33:12

MVC单元测试ASP.NET

2009-07-22 10:34:37

ActionInvokASP.NET MVC
点赞
收藏

51CTO技术栈公众号