Почему Rotativa всегда создает мою страницу входа? Почему это медленно?

Я использовал этот пример кода Rotativa 1.6.4 для создания PDF файла со страницы в приложении .NET MVC 5.

public ActionResult PrintIndex()
{
    var a = new ActionAsPdf("Index", new { name = "Giorgio" }) { FileName = "Test.pdf" };
    a.Cookies = Request.Cookies.AllKeys.ToDictionary(k => k, k => Request.Cookies[k].Value);
    a.FormsAuthenticationCookieName = System.Web.Security.FormsAuthentication.FormsCookieName;
    a.CustomSwitches = "--load-error-handling ignore";
    return a;
}

public ActionResult Index(string name)
{
    ViewBag.Message = string.Format("Hello {0} to ASP.NET MVC!", name);

    return View();
}

Он не печатал страницу индекса, а вместо этого печатал мою страницу входа.

Как только я исправил проблему аутентификации, генерация PDF была чрезвычайно медленной даже с CustomSwitches. (Несколько минут)

Вышеприведенный код может действительно работать для вас - он обошел проблему аутентификации с помощью свойства Cookies, но для меня это было слишком медленным.

Как распечатать безопасную страницу, а также сделать это быстро?

Ответ 1

Я боролся с этим, вероятно, 8 часов, и я отправляю свое собственное решение частично как самостоятельную ссылку, но также и потому, что не было хорошего ответа при переполнении стека.

Загрузите источник Rotativa

С открытым исходным кодом на github. Я пробовал много других решений, где люди говорили использовать UrlAsPdf и другие решения из проблем github, но ничто из этого не сработало для меня. Еще одно преимущество, помимо чтения кода... Создайте файл pdb, подбросьте его в свое решение и отлаживайте его. Это покажет много! Я обнаружил, что Rotativa использует wkhtmltopdf.exe под обложками. Это использует веб-комплект для рендеринга html. Также команда обычно делает HTTP-запрос к URL-адресу. Зачем? Мы уже на сервере! Это означает, что нам пришлось бы повторно аутентифицировать и объяснять, почему мы иногда можем получить страницу входа. Копирование файлов cookie поможет, но зачем делать запрос http к себе, когда вы можете сделать это в режиме онлайн?

Прорыв

Я нашел метод расширения в источнике GetHtmlFromView, который генерирует html представления без отдельного запроса http! ДА! Кто звонит GetHtmlFromView? Почему ViewAsPdf, конечно. Так что это привело меня к тому, чтобы попробовать код ниже, который работает и быстро!

Код для размещения в ASP.NET MVC Controller Action:

// ViewAsPdf calls Rotativa.Extensions.ControllerContextExtensions.GetHtmlFromView
// Which generates the HTML inline instead of making a separate http request which CallDriver (wkhtmltopdf.exe) does.
var a = new ViewAsPdf();
a.ViewName = "Index";
a.Model = _service.GetMyViewModel(id);
var pdfBytes = a.BuildPdf(ControllerContext);

// Optionally save the PDF to server in a proper IIS location.
var fileName = string.Format("my_file_{0}.pdf", id);
var path = Server.MapPath("~/App_Data/" + fileName);
System.IO.File.WriteAllBytes(path, pdfBytes);

// return ActionResult
MemoryStream ms = new MemoryStream(pdfBytes);
return new FileStreamResult(ms, "application/pdf");

Ответ 2

У меня была такая же проблема, но ответ Джесса не помог мне.

Когда я обновил файл wkhtmltopdf.exe в своем проекте, скачанный с здесь, он снова работал быстро.

Ответ 3

Надеюсь, что этот код разрешит первый вопрос

public ActionResult DownloadViewPDF() {
 Dictionary<string, string> cookieCollection = new Dictionary<string, string>();
   foreach (var key in Request.Cookies.AllKeys)
     {
       cookieCollection.Add(key, Request.Cookies.Get(key).Value);
     }
     return new ActionAsPdf("Index")
       {
          FileName = "Name.pdf",
          Cookies = cookieCollection
        };
     }

Ответ 4

ViewAsPdf решил мою проблему. ActionAsPdf генерировать ошибку или генерировать страницу входа.

        Dictionary<string, string> cookieCollection = new Dictionary<string, string>();
        foreach (var key in Request.Cookies.AllKeys)
        {
            cookieCollection.Add(key, Request.Cookies.Get(key).Value);
        }
        var abc = new ViewAsPdf("invoice", _customers)
        {
            FileName = "Name.pdf",
            Cookies = cookieCollection,
            FormsAuthenticationCookieName = FormsAuthentication.FormsCookieName
        };
        var byteArray = abc.BuildPdf(ControllerContext);
        var fileStream = new FileStream(Server.MapPath(subPath) + "/abc.pdf", FileMode.Create, FileAccess.Write);
        fileStream.Write(byteArray, 0, byteArray.Length);
        fileStream.Close();