在hangfire作业中生成/发送pdf电子邮件附件

时间:2016-12-08 08:34:03

标签: asp.net-mvc pdf razorengine hangfire rotativa

在我们的ASP.NET MVC Web应用程序中,我们发送电子邮件作为Hangfire处理的计划任务的一部分,我正在使用Postal here 该方法工作正常,我们能够发送HTML /文本电子邮件。现在我们还需要生成和附加PDF文件。附加的PDF需要使用Razor模板动态生成。首先,我尝试使用Rotativa来生成PDF。但是我遇到了一个问题,即BuildPdf方法需要一个在后台HangFire进程中不可用的ControllerContext。我试图伪造ControllerContext为

using (var memWriter = new StringWriter(sb))
            {

                var fakeResponse = new HttpResponse(memWriter);

                var fakeRequest = new HttpRequest(null, "http://wwww.oururl.com", null);
                var fakeHttpContext = new HttpContext(fakeRequest, fakeResponse);
                var emailController = new BackgroundEmailController();
                var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeHttpContext), new RouteData(), emailController);

                var attachment = emailController.BillAttachment(email);

                var pdf = attachment.BuildPdf(fakeControllerContext);

                if (pdf != null && pdf.Count() > 0)
                {
                    using (MemoryStream ms = new MemoryStream(pdf))
                    {
                        var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
                        email.Attach(new System.Net.Mail.Attachment(ms, contentType));
                    }
                }
            }              

然而,这在Rotativa中引发了NullReference错误。  然后我首先尝试使用RazorEngine将模板视图编译为HTML(然后通过某种方式将HTML转换为pdf)

var engineService = RazorEngineService.Create();

            engineService.AddTemplate(cache_name, File.ReadAllText(billAttachmentTemplatePath));
            engineService.Compile(cache_name, modelType: typeof(BillEmail));
            var html = engineService.Run(cache_name, null, email);

            using (var ms = CommonHelper.GenerateStreamFromString(html))
            {
                var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Html);
                email.Attach(new System.Net.Mail.Attachment(ms, contentType));
            }

它会在RazorEngine动态DLL中抛出另一个NullReference:

 System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_bb2b366aaef64f2bbc2997353f88cc9e.Execute()
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)

我想知道是否有人建议在Hangfire流程中从模板生成PDF文件?

1 个答案:

答案 0 :(得分:0)

如果您对商业解决方案持开放态度,可以尝试 Telerik reporting 并以编程方式将其导出为pdf。您定义报告然后调用它以在服务器端生成PDF,最后通过电子邮件将byte []作为电子邮件附件发送。您现在可以使用Hangfire作业开始此过程。

假设您已定义报告的结构,这是一个伪代码,请查看here for more details on how to create your report programatically

public void GenerateAndEmailReport()
{     
    var reportSource = new InstanceReportSource();
    Telerik.Reporting.Report report = new MyReport();

    //populate data into report

    reportSource.ReportDocument = report;

    var reportProcessor = new ReportProcessor();
    reportSource.ReportDocument = report;
    var info = new Hashtable();
    var result= reportProcessor.RenderReport("PDF", reportSource, info);

    byte[]reportBytes = result.DocumentBytes;

    SendEmail(reportBytes, "myreport.pdf"); // a method that takes the bytes and attach it to email. 
}

来自telerik的其他参考资料。