[英]MVC ControllerContext, Threads/Tasks, Rotativa
Rotativa 1.6.4 不断在 Rotativa.dll 中发出 System.NullReferenceException
具体来说,它发生在 BuildPdf(context) 上
我尝试过线程、任务和其他后台类型的工作。 为什么? PDF 生成有时非常慢,而且使用 ActionAsPdf(请参阅此处)有问题,所以我想将它分拆到一个新的线程/任务或后台作业,并且只记录错误,这样我就可以让用户尽快回到他们的路上。
BuildPdf 采用当前的控制器上下文,它总是为 null 我试过创建一个新的上下文,使用 httpcontext,创建一个新的控制器实例,所有的结果都相同。 一旦它进入 Rotativa.dll,上下文就完全消失了,无论我是在成为线程/任务之前传入它,还是在调用 BuildPdf() 之前创建一个新的;
如何在开始线程/任务作业之前或在线程/任务作业内部进入 Rotativa 时获取有效的控制器上下文?
在这一点上,我已经准备好在真正的 PDF 解决方案上花真钱了,但到目前为止,它们似乎都是 PITA,即使您对 PDF 有最简单的儿童需求,也只能算中等。
您是否尝试创建SynchronizationContext
代替?
似乎该库是非线程安全的。
我正在处理同样的问题。 我尝试模拟 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)
对于那些试图像我一样把它们弄出去的人...我尝试了一切,从使用DriverOptions
( 在此描述)传递cookie到将ViewAsPdf
生成的ViewAsPdf渲染为字符串(自定义Razor扩展)并转换到一个字节数组 - 但只是从ActionAsPdf
更改为PartialViewAsPdf
为我解决了它。
无论出于何种原因PartialViewAsPdf
包含相同(或更好的/改善...?) BuildPdf(ControllerContext)
方法ActionAsPdf
,但ViewAsPdf
没有。 PartialViewAsPdf
类在ControllerContext
传递,并按照我的预期访问我的特定于上下文的变量。
试试这个!!
Task.Factory.StartNew(() =>
{
Do Something here
},
CancellationToken.None,
TaskCreationOptions.PreferFairness,
TaskScheduler.FromCurrentSynchronizationContext()
);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.