asp.net

位置:IT落伍者 >> asp.net >> 浏览文章

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


发布日期:2019年03月06日
 
用ASP.NET MVC源代码寻找解决方案

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

[AsyncAction]

publicActionResultAsyncAction(AsyncCallbackasyncCallbackobjectasyncState)

{

SqlConnectionconn=newSqlConnection(;AsynchronousProcessing=true);

SqlCommandcmd=newSqlCommand(WAITFORDELAY::;conn); connOpen();

returnthisAsync( cmdBeginExecuteNonQuery(asyncCallbackasyncState) (ar)=>

{

intvalue=cmdEndExecuteNonQuery(ar);

connClose();

returnthisView();

});

}

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

publicclassAsyncMvcHandler:IHttpAsyncHandlerIRequiresSessionState

{

publicAsyncMvcHandler( Controllercontroller IControllerFactorycontrollerFactory RequestContextrequestContext)

{

thisController=controller;

thisControllerFactory=controllerFactory;

thisRequestContext=requestContext;

}

publicControllerController{get;privateset;

}

publicRequestContextRequestContext{get;privateset;

}

publicIControllerFactoryControllerFactory

{

get;privateset;

}

publicHttpContextContext{get;privateset;

}

publicIAsyncResultBeginProcessRequest( HttpContextcontext AsyncCallbackcb objectextraData)

{

thisContext=context;

thisControllerSetAsyncCallback(cb)SetAsyncState(extraData);

try

{

(thisControllerasIController)Execute(thisRequestContext);

returnthisControllerGetAsyncResult();

}

catch

{

thisControllerFactoryReleaseController(thisController);

throw;

}

}

publicvoidEndProcessRequest(IAsyncResultresult)

{

try

{

HttpContextCurrent=thisContext;

ActionResultactionResult=thisControllerGetAsyncEndDelegate()(result);

if(actionResult!=null)

{

actionResultExecuteResult(thisControllerControllerContext);

}

}

finally

{

thisControllerFactoryReleaseController(thisController);

}

}

}

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

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

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

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

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

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

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

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

               

上一篇:ASP.NET MVC创建TaskList应用程序

下一篇:Asp.net控件开发----控件开发基础