asp.net-mvc – 在ASP.NET MVC 4中强制同步执行异步操作
发布时间:2020-12-16 03:38:56 所属栏目:asp.Net 来源:网络整理
导读:由于MVC 4不支持异步子操作(通过 Html.Action),我正在寻找一种强制同步执行子操作的方法.解决此限制的一个简单方法是提供所有控制器操作的同步版本: public class FooAsyncController : Controller { public async TaskActionResult IndexAsync() { var mod
由于MVC 4不支持异步子操作(通过
Html.Action),我正在寻找一种强制同步执行子操作的方法.解决此限制的一个简单方法是提供所有控制器操作的同步版本:
public class FooAsyncController : Controller { public async Task<ActionResult> IndexAsync() { var model = await service.GetFoo().ConfigureAwait(false); return View(model); } } public class FooSyncController : FooAsyncController { public ActionResult Index() { return IndexAsync().Result; // blocking call } } 但是,由于我们允许对所有控制器操作执行子操作请求,因此对每个控制器执行此操作都是真正的PITA. 在框架中是否有任何可扩展性点,我们可以检查操作的返回值,如果它返回任务< T>我们正在处理儿童行动,强制同步通话? 解决方法
在几小时内浏览ASP.NET MVC源代码之后,我能够提出的最佳解决方案(除了创建每个控制器操作的同步版本之外)是手动调用Controller中异步Action方法的操作描述符. HandleUnknownAction.
我对这段代码并不是特别满意,我希望它可以改进,但确实有效. 这个想法是故意请求一个无效的操作(前缀为“_”),它将调用控制器上的HandleUnknownAction方法.在这里,我们寻找匹配的异步操作(首先从actionName中删除下划线)并调用AsyncActionDescriptor.BeginExecute方法.通过立即调用EndExecute方法,我们可以有效地同步执行操作描述符. public ActionResult Index() { return View(); } public async Task<ActionResult> Widget(int page = 10) { var content = await new HttpClient().GetStringAsync("http://www.foo.com") .ConfigureAwait(false); ViewBag.Page = page; return View(model: content); } protected override void HandleUnknownAction(string actionName) { if (actionName.StartsWith("_")) { var asyncActionName = actionName.Substring(1,actionName.Length - 1); RouteData.Values["action"] = asyncActionName; var controllerDescriptor = new ReflectedAsyncControllerDescriptor(this.GetType()); var actionDescriptor = controllerDescriptor.FindAction(ControllerContext,asyncActionName) as AsyncActionDescriptor; if (actionDescriptor != null) { AsyncCallback endDelegate = delegate(IAsyncResult asyncResult) { }; IAsyncResult ar = actionDescriptor.BeginExecute(ControllerContext,RouteData.Values,endDelegate,null); var actionResult = actionDescriptor.EndExecute(ar) as ActionResult; if (actionResult != null) { actionResult.ExecuteResult(ControllerContext); } } } else { base.HandleUnknownAction(actionName); } } 风景 <h2>Index</h2> @Html.Action("_widget",new { page = 5 }) <!-- note the underscore prefix --> 我几乎可以肯定通过重写Controller.BeginExecute有更好的方法.默认实现如下所示.我的想法是立即执行Controller.EndExecuteCore,尽管到目前为止我没有取得任何成功. protected virtual IAsyncResult BeginExecute(RequestContext requestContext,AsyncCallback callback,object state) { if (DisableAsyncSupport) { // For backwards compat,we can disallow async support and just chain to the sync Execute() function. Action action = () => { Execute(requestContext); }; return AsyncResultWrapper.BeginSynchronous(callback,state,action,_executeTag); } else { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } // Support Asynchronous behavior. // Execute/ExecuteCore are no longer called. VerifyExecuteCalledOnce(); Initialize(requestContext); return AsyncResultWrapper.Begin(callback,BeginExecuteCore,EndExecuteCore,_executeTag); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net-mvc – WebAPI窗体身份验证SimpleMembershipProvid
- asp.net-mvc – 每个请求DbContext发生随机错误
- asp.net – AspNetCore.Mvc与AspNetCore.Mvc.Core
- ASP.NET 或C# 中ASCII码含中文字符的编解码处理
- asp.net-mvc – 从MVC站点路由到Angular 2应用程序
- 勾选复选框时,禁用一些ASP.Net验证控件
- asp.net – 文件下载问题:文件名与空格被截断!
- asp.net – RadGrid自定义过滤器
- asp.net-mvc – 洋葱建筑 – 存储库与服务?
- ASP.NET MVC Web应用程序中的控制器是否应该调用存储库,服务