我将项目从MVC3转换为MVC4,也从实体框架5转换为EF 6.1。在代码中有一个VBHTML页面,其中包含代码部分"使用Html.BeginForm ....结束使用"。在此页面中,用户可以选择文件并单击“提交”。它在控制器中调用POST方法。控制器中的方法使用GData API的可恢复上传器(异步)将所选文件上载到Google驱动器。必须使用ResumableUploader(用于上传PDF和大文件的GData API限制)。现在,这段代码在MVC3中一直有效。一旦平台更改为MVC4,就开始获得此异常:
此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async =" true" %GT;
at System.Web.AspNetSynchronizationContext.OperationStarted() at Google.GData.Client.ResumableUpload.ResumableUploader.AsyncStarter
(AsyncResumableUploadData data, WorkerResumableUploadHandler workerDelegate,
Object userData)
我确实把@Page Async =" true"在VBHTML页面中,但没有帮助。我100%确定这与MVC4和/或.Net 4.5有关,因为代码中没有进行任何其他更改(除了转移到MVC4并转移到.Net4.5)。我现在有两个代码分支,一个在MVC3上,一个在MVC4上。当我编译MVC3并在应用程序中复制输出DLL时,上述问题没有浮出水面。当我用MVC4版本替换该DLL时,会出现上述问题。如何处理?
这是导致此问题的代码:
Dim auth As Authenticator = New AuthSubAuthenticator("MyToken", authFactory.Token)
Dim uploader As New ResumableUploader(10485760)
AddHandler uploader.AsyncOperationCompleted, AddressOf UploaderCompleted
uploader.InsertAsync(auth, file, New Object())
跟踪显示异常是从最后一行抛出的(uploader.InsertAsync)
我知道有一种我可以使用的等待方法。相反,没有尝试将uploader.InsertAsync
更改为uploader.Insert
,代码正常。但是用户必须等到上传完成(对于更大的文件,相当长一段时间)。
答案 0 :(得分:1)
我100%确定这与MVC4和/或.Net 4.5相关
是的,这是ASP.NET 4.5的一个变化。但是,重要的是要注意之前的代码在技术上是错误的。 ASP.NET 4.5添加了一些保护措施来捕获不正确的异步使用。所以,MVC3代码实际上是不合适的;它只是没有被抓住并报告。
将uploader.InsertAsync更改为uploader.Insert并且代码正常工作。但是用户必须等到上传完成(对于更大的文件,相当长一段时间)。
这是"适当的"在ASP.NET上执行此操作的方法(在旁注中,使用await
将比Insert
更有效。没有用户连接,ASP.NET不能用于工作。
例如,考虑如果上传错误会发生什么;没有办法通知用户上传实际上没有完成。就此而言,无法通知用户上传 已完成。此外,ASP.NET可能会回收您的应用程序,这可能会导致正在进行的上载。出于这些原因,做了“开火”和“忘记”。不推荐在ASP.NET上工作。
但是,如果您愿意接受这些限制,我会在我的博客上描述各种方法fire and forget on ASP.NET。请注意,ASP.NET 4.5.2添加了一种内置方法:HostingEnvironment.QueueBackgroundWorkItem
。