ASP.NET MVC 调用Async后缀Action报找不到Completed方法的InvalidOperationException
问题现象
开发者编写了标注[HttpPost]特性的如下Action:
[HttpPost] public ActionResult AddVideoAsync(string permaLinkFixed) { return Json(new { Success = true }); }
调用该Action时系统抛出InvalidOperationException异常,错误提示为:在YYY控制器类型上找不到名为AddVideoCompleted的方法。
该问题存在固定的复现规律:无论怎么修改Action命名,都会触发同类异常——若将Action命名为AddVideoCompletedAsync,系统就会提示找不到AddVideoCompletedCompleted方法。
问题根因
该问题来自老式ASP.NET MVC的异步Action匹配机制:
当控制器继承了已被官方标记为过时的AsyncController基类时,框架会启用早期版本的双方法异步约定:只要发现Action的名称以Async结尾,就会自动截掉名称末尾的Async后缀,拼接上Completed后缀去查找对应的异步完成回调方法,完全不会校验方法本身的签名和返回值逻辑。
这一逻辑刚好匹配观察到的异常规律:
- 遇到方法名
AddVideoAsync时,截掉末尾的Async得到AddVideo,直接拼接后缀查找AddVideoCompleted方法 - 遇到方法名
AddVideoCompletedAsync时,截掉末尾的Async得到AddVideoCompleted,直接拼接后缀查找AddVideoCompletedCompleted方法
解决方案
- 如果需要沿用老式的双方法异步开发模式,需要严格按照框架约定拆分方法:单独编写
AddVideoAsync方法处理请求入参与业务逻辑,再编写配套的AddVideoCompleted方法返回最终响应结果,匹配框架的查找规则 - 如果使用现代async/await语法开发,直接将控制器的基类从过时的
AsyncController替换为默认的Controller类即可。此时框架会自动识别返回Task<ActionResult>类型的异步方法,不会再触发老式的双方法匹配逻辑 - 额外注意:即使使用默认的
Controller基类,也不要给普通同步返回值的方法硬加Async后缀,避免后续路由解析出现非预期的匹配问题
内容的提问来源于stack exchange,提问作者Christian Lavallee
相关产品推荐
相关产品推荐

