以下代码可以很好地将Razor View呈现为字符串:
///
/// url: /api/createHtml
///
public ActionResult CreateHtml()
{
// Heavy calculations
MyModel myModel = new MyModel();
myModel.Feature1 = ...;
myModel.Feature2 = ...;
myModel.Feature3 = ...;
ViewData.Model = myModel;
using (var stringWriter = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, "MyView");
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, stringWriter);
viewResult.View.Render(viewContext, stringWriter);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
string html = stringWriter.GetStringBuilder().ToString();
byte[] htmlBytes = Encoding.ASCII.GetBytes(html);
System.IO.File.WriteAllBytes(Server.MapPath("~/temp/foo.html"), htmlBytes);
}
return JSON(new
{
error = false,
message = "Your view is available at temp/foo.html"
});
}
以上代码同步运行,这意味着对/api/createHtml/
的AJAX请求将以创建的temp/foo.html
文件结束。
我想异步执行此操作:这意味着AJAX请求会通过以下消息快速返回给用户:“ 您的视图将可以在temp / foo.html 获得>”。然后用户必须去检查文件是否准备好(通过简单地轮询到temp目录[或使用其他方法,在这个问题上不重要])
因此,当我在Task
中尝试相同的代码时,它不起作用:
///
/// url: /api/createHtml
///
public ActionResult CreateHtml()
{
new Task(() =>
{
// Heavy calculations
MyModel myModel = new MyModel();
myModel.Feature1 = ...;
myModel.Feature2 = ...;
myModel.Feature3 = ...;
ViewData.Model = myModel;
using (var stringWriter = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, "MyView");
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, stringWriter);
viewResult.View.Render(viewContext, stringWriter); // <--- Problem
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
string html = stringWriter.GetStringBuilder().ToString();
byte[] htmlBytes = Encoding.ASCII.GetBytes(html);
System.IO.File.WriteAllBytes(Server.MapPath("~/temp/foo.html"), htmlBytes);
}
}).Start();
return JSON(new
{
error = false,
message = "Your view _WILL BE_ available at temp/foo.html"
});
}
它不起作用,因为它在viewResult.View.Render(...)
处引发了异常
值不在预期范围内。
传递给viewContext
的{{1}}在新线程中似乎不再有效,如下所示:ASP.NET MVC: Exception rendering view in new thread
是否存在一种在viewResult.View.Render(...)
中呈现视图的解决方法?
我知道我可以使用“ RazorEngine”,这是一个免费的库,可以呈现剃刀视图,而无需所有控制器混合框,但是我更喜欢使用本机代码来重新利用代码。
后期编辑:
一些答案认为我想使用“等待异步”。 我不知道。我不想等待任务完成。
答案 0 :(得分:1)
好吧,您的任务可能正在做应做的事情,但是主要的威胁不是在等他。
尝试使用:
var myTask=new Task(() =>
{
// all of your code
}).Start();
myTask.Wait();
检查更多info
最好的方法是使用async and await,因为应该将Tasks用于异步操作,祝您好运。
答案 1 :(得分:0)
异步操作方法仅在Web服务器内部异步工作。异步方法的优点是,当它们不需要时(而不是阻塞它),它们会将宝贵的线程释放回线程池中。但是 HttpRequest仍然是同步的。 。您的浏览器将同步等待异步操作方法的响应。
您需要的是产生一个新的线程或任务来执行您的长时间运行的任务,然后从action方法中返回。
看看:Long Running Background Tasks in Asp.Net MVC3
这个问题可能也有帮助:Do asynchronous operations in ASP.NET MVC use a thread from ThreadPool on .NET 4