Rotativa 1.6.4在Rotativa.dll中继续发出System.NullReferenceException
具体地说,它发生在BuildPdf(上下文)
上我尝试过Thread,Task和其他背景类型的工作。为什么?使用ActionAsPdf(请参阅Here),PDF生成速度非常慢,因此我希望将其转换为新的线程/任务或后台作业,并且只记录错误,这样我就可以重新启动用户他们的方式尽快。
BuildPdf获取当前的控制器上下文,它始终为null我尝试使用httpcontext创建一个新的上下文,使得一个新的控制器实例都具有相同的结果。一旦它进入Rotativa.dll,无论我是在线程/任务之前是否传入它,或者在我调用BuildPdf()之前创建一个新上下文,上下文都会被强制删除;
如何在开始线程/任务作业之前获取有效的控制器上下文,或者在线程/任务作业进入Rotativa之前获取有效的控制器上下文?
此时我已经准备好在真正的PDF解决方案上花钱了,但到目前为止它们似乎都是PITA,并且即使你有最简单的儿童PDF需求,它们也只是平庸。 / p>
答案 0 :(得分:0)
您是否尝试创建SynchronizationContext
?
看起来这个库是非线程安全的。
答案 1 :(得分:0)
我正在处理同样的问题。我试图模拟ControllerContext,用MvcContrib创建FakeControllerContexts(因为它可以在Rotativa单元测试库中看到)等等......但是所有方法都给了我乱七八糟的循环引用,它们在线程中运行不好。
为了从模型中调用函数,我最终使用RazorEngine(以获取由模型数据填充的html)+ iTextSharp(将html转换为pdf)而不是Rotativa。这在我的项目中创建了一个优雅的模板可能性(电子邮件,pdf,...)。
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;
...
public class PDFHelper {
public static byte[] GetPDFGromHTMLString(string pHTML) {
byte[] bPDF = null;
MemoryStream ms = new MemoryStream();
TextReader txtReader = new StringReader(pHTML);
// 1: create object of a itextsharp document class
Document doc = new Document(PageSize.A4, 25, 25, 25, 25);
// 2: we create a itextsharp pdfwriter that listens to the document and directs a XML-stream to a file
PdfWriter oPdfWriter = PdfWriter.GetInstance(doc, ms);
// 3: we create a worker parse the document
HTMLWorker htmlWorker = new HTMLWorker(doc);
// 4: we open document and start the worker on the document
doc.Open();
htmlWorker.StartDocument();
// 5: parse the html into the document
htmlWorker.Parse(txtReader);
// 6: close the document and the worker
htmlWorker.EndDocument();
htmlWorker.Close();
doc.Close();
bPDF = ms.ToArray();
return bPDF;
}
在模型中我用它作为:
using RazorEngine;
using RazorEngine.Templating;
...
string razorText = System.IO.File.ReadAllText(HostingEnvironment.MapPath(@"~/Views/MyReport.cshtml"));
string body = Razor.Parse(razorText, model);
byte[] pdfBinary = MyFramework.PDFHelper.GetPDFGromHTMLString(body);
/**other stuff */
如果您不想在RazorEngine中处理RequestContext,则不应使用Html和Url助手(将@ Html.DisplayFor(model => ..)更改为@ Model.MyProperty)
答案 2 :(得分:0)
对于任何人都拉着他们的头发试图像我一样想出这个......我尝试了所有的东西,从使用DriverOptions
(描述为here)传递cookie到渲染{{1}由Rotativa生成一个字符串(自定义Razor扩展)并将其转换为字节数组 - 但只是从ViewAsPdf
更改为ActionAsPdf
为我解决了这个问题。
无论出于何种原因PartialViewAsPdf
包含与PartialViewAsPdf
相同(或更好/改进的??)BuildPdf(ControllerContext)
方法,但ActionAsPdf
不包含ViewAsPdf
。 PartialViewAsPdf
中传递了ControllerContext
类,并按照我的预期访问了特定于上下文的变量。
答案 3 :(得分:0)
试试这个!!
Task.Factory.StartNew(() =>
{
Do Something here
},
CancellationToken.None,
TaskCreationOptions.PreferFairness,
TaskScheduler.FromCurrentSynchronizationContext()
);