为什么Rotativa总是生成我的登录页面?它为什么慢?

Jes*_*ess 13 rotativa asp.net-mvc-5

我正在使用这个Rotativa 1.6.4代码示例从我的.NET MVC 5应用程序中的页面生成PDF.

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();
}
Run Code Online (Sandbox Code Playgroud)

它没有打印索引页面,而是打印我的登录页面.

一旦我修复了身份验证问题,即使使用,PDF生成也非常慢CustomSwitches.(几分钟)

上面的代码可能实际上适合你 - 它使用Cookies属性解决了身份验证问题,但对我来说这太慢了.

如何打印安全页面以及快速完成?

Jes*_*ess 17

我挣扎了大概8个小时,我发布自己的解决方案部分作为自我参考,但也因为堆栈溢出没有好的答案.

下载Rotativa Source

它是github上的开源软件.我尝试了许多其他解决方案,其中人们说使用UrlAsPdf和github问题的其他解决方案,但这些都不适合我.除了阅读代码之外的另一个优点...构建pdb文件,将其丢入您的解决方案并调试到它.它会揭示很多!我发现的一件事是Rotativa wkhtmltopdf.exe在幕后使用.这使用Web工具包来呈现html.该命令通常也会向URL发出http请求.为什么?我们已经在服务器上了!这意味着我们必须重新进行身份验证并解释为什么我们有时可以获得"登录"页面.复制cookie会有所帮助,但是为什么当你可以在线进行时向自己发出http请求?

突破

我在源代码中找到了一个扩展方法,GetHtmlFromView它生成视图html而不需要单独的http请求!是!谁打电话GetHtmlFromViewViewAsPdf当然是为什么 所以这导致我尝试下面的代码,这是有效的,并且很快!

放入ASP.NET MVC控制器动作的代码:

// 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");
Run Code Online (Sandbox Code Playgroud)

  • @SAR,将 `a.Model = _service.GetMyViewModel(id);` 替换为您的代码,以填充您想要传递到视图中的模型、视图模型或视图包。 (2认同)

小智 5

我希望这段代码能解决第一个问题

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
        };
     }
Run Code Online (Sandbox Code Playgroud)