Визуализация представления Razor в виде строки в задаче - PullRequest
0 голосов
/ 05 марта 2019

Следующий код прекрасно работает для рендеринга 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", Не знаю.Я не хочу ждать завершения задания.

Ответы [ 2 ]

1 голос
/ 05 марта 2019

Ну, ваши задачи, вероятно, делают то, что предполагают, но главная угроза его не ждет.

Попробуйте использовать:

var myTask=new Task(() =>
{
    // all of your code

}).Start();

myTask.Wait();

проверить больше info

Лучший способ - использовать async и await , потому что задачи должны использоваться для асинхронных операций, удачи.

0 голосов
/ 06 марта 2019

Асинхронные методы действий, работают асинхронно только внутри веб-сервера.Преимущество асинхронных методов заключается в том, что они возвращают драгоценный поток обратно в пул потоков, когда им это не нужно (в отличие от его блокировки) ... Но запрос HttpRequest все еще синхронен ... Ваш браузер будет синхронно ожидать ответа от метода асинхронного действия .

. Вам нужно создать новый поток или задачу для выполнения вашей длительной задачи ивозврат из метода действия.

Взгляните на: Долгосрочные фоновые задачи в Asp.Net MVC3

Также этот вопрос может помочь: Выполнять асинхронные операции в ASP.NET MVC.поток из ThreadPool на .NET 4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...