Следующий код прекрасно работает для рендеринга 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"
});
}
Приведенный выше код выполняется синхронно, что означает, что AJAX-запрос к /api/createHtml/
завершится созданным файлом temp/foo.html
.
Я хочу сделать это асинхронно: это означает, что AJAX-запрос быстро возвращается пользователю с сообщением типа: " Ваше представление БУДЕТ доступным в temp / foo.html.».И затем пользователь должен проверить, готов ли файл (просто опросив временный каталог [или используя другой метод, не важный в этом вопросе])
Итак, когда я пытаюсь использовать тот же код в 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
, переданный в viewResult.View.Render(...)
, больше не действителен в новом потоке, как показано здесь: ASP.NET MVC: представление рендеринга исключений в новом потоке
Есть ли обходной путь для рендеринга вида в Task
?
Я знаю, что мог бы использовать "RazorEngine", бесплатную библиотеку, которая отображает бритвенные виды без всего контроллера mumbo jumbo,но я бы предпочел использовать нативный код для повторного использования кода.
ПОСЛЕ РЕДАКТИРОВАНИЯ:
В нескольких ответах говорилось, что я хотел использовать "await async", Не знаю.Я не хочу ждать завершения задания.