MVC中DeviceController无法转换为System.Web.UI.Page的问题求助
问题分析
你的核心问题是原类库的ExecuteCommand方法依赖ASP.NET Web Forms的System.Web.UI.Page类型来注册异步任务,但MVC控制器继承自Controller,和Page属于完全不同的请求处理体系,直接传递控制器实例this必然触发类型转换错误。而你尝试通过BuildManager创建Page实例的方式,因为脱离了当前请求的真实上下文,导致后续出现一系列页面生命周期相关的异常,且无法正常触发异步逻辑。
解决方案
根据是否能修改类库代码,提供两种可行方案:
方案一:重构类库,移除对Page的依赖(推荐)
类库中使用Page.RegisterAsyncTask是Web Forms特有的异步处理方式,MVC有自己的异步控制器模型,因此最好将类库的异步逻辑与Web Forms的Page解耦,改为通用的异步实现:
修改类库的ExecuteCommand方法
移除Page参数,直接处理异步回调逻辑:
public void ExecuteCommand(XmlDocument request, DeviceResponseHandler responseHandler, ExceptionHandler responseExceptionHandler) { AsyncCallback completedCallback = ar => { try { using (var resp = new DeviceResponse(this, ar)) responseHandler(resp); } catch (Exception ex) { responseExceptionHandler(ex); } }; // 直接启动异步命令逻辑 BeginCommand(request, completedCallback, null); }
MVC控制器中使用异步方法调用
MVC支持异步控制器方法,通过TaskCompletionSource将回调式异步转换为async/await风格:
public async Task<ActionResult> YourAction() { var tcs = new TaskCompletionSource<DeviceResponse>(); Exception exception = null; session.ExecuteCommand(doc, response => tcs.SetResult(response), ex => exception = ex); // 等待异步操作完成 var response = await tcs.Task; if (exception != null) { Result = exception.Message; return View(); } CmdGetNextGlogResponse cmd_resp = new CmdGetNextGlogResponse(); switch (cmd_resp.ParseResult(response.Xml)) { case CommandExeResult.OK: cmd_resp.Parse(response.Xml); break; default: Result = "Failed!"; break; } return View(); }
方案二:无法修改类库时,模拟Page上下文(不推荐,仅应急)
如果无法修改类库代码,可以尝试创建一个关联当前请求上下文的Page实例,避免上下文异常:
// 创建Page实例并绑定当前请求的上下文 var page = new Page(); page.Context = HttpContext.Current; session.ExecuteCommand(page, doc, (response) => { CmdGetNextGlogResponse cmd_resp = new CmdGetNextGlogResponse(); switch (cmd_resp.ParseResult(response.Xml)) { case CommandExeResult.OK: cmd_resp.Parse(response.Xml); break; default: Result = "Failed!"; break; } }, (ex) => { Result = ex.Message; });
注意:这种方式属于hack手段,可能会因为MVC与Web Forms上下文的差异,引发后续未知问题,仅在无法重构类库时临时使用。
内容的提问来源于stack exchange,提问作者Raguraman
相关产品推荐
相关产品推荐

