【问题标题】:How to get ControllerContext to build PDF using Rotativa in BackgroundJob with Hangfire如何在带有 Hangfire 的 BackgroundJob 中使用 Rotativa 获取 ControllerContext 以构建 PDF
【发布时间】:2020-10-27 12:38:20
【问题描述】:

我必须在我的后台应用程序中发送邮件,为此我使用 Hangfire,但我必须在每封邮件及其收件人中附加一个文档,要附加的文档信息位于我用 rotativa 转换的表格。

我担心的是,当我想将文档转换为 byte[] 时,我总是知道 HttpContextnull,这显然是因为当一切都在后台时没有触发操作的 HTTP 请求。

这是我的实际代码:

var Avis_views = new ViewAsPdf("~/Views/AvisAutomatique/ExportPdfDebit.cshtml", printa)
{
    PageMargins = new Rotativa.Options.Margins(0, 0, 0, 0),
    MinimumFontSize = 14,
    /*ageHeight=60,*/
    PageOrientation = Rotativa.Options.Orientation.Portrait,
    PageSize = Rotativa.Options.Size.A4,
};

var fileName = "DEBITADVISE_" + Numcpt + "_" + _GetTransDateTime() + ".pdf";
//var path = Path.Combine(@"C:\DocumentPdf\", fileName);
byte[] abc =  Avis_views.BuildFile(quotesController.ControllerContext);
//System.IO.File.WriteAllBytes(path, abc);
MemoryStream ms = new MemoryStream(abc);

sendemail(email, fileName, abc, emailc);

有人可以帮我从我的控制器初始化 httpcontext 吗?

【问题讨论】:

  • 为什么你认为你需要一个 HttpContext?如果这是一个后台进程,就不会有 HttpContext。以独立于 HttpContext 的方式编写代码。
  • 是的,在这种情况下你是对的,如何替换这行代码 // byte[] abc = Avis_views.BuildFile(quotesController.ControllerContext) // thks
  • 我不知道Avis_views.BuildFile 做了什么,也不知道为什么它需要控制器上下文。
  • Avis_Views.Buildfile 获取 rotativa 文件的字节,我只需要获取文件的字节
  • 那么为什么需要控制器上下文?

标签: c# asp.net asp.net-mvc rotativa


【解决方案1】:

Rotativa lib 中的一个问题似乎是它必须采用控制器上下文,github.com/webgio/Rotativa/pull/88

并且您将无法将上下文传递给您列出的hangfire后台进程。

解决方法(如果文件不是太大)可能是您的hangfire 进程调用您网站上的 URL,该 URL 执行电子邮件发送代码,而不是在 hangfire 后台进程中执行 Rotativa 和电子邮件发送。

【讨论】:

  • 你好老板,问题是我正在将数据模型传递给视图并使用 rotativa 进行转换
【解决方案2】:

我是Rotativa的作者,也是rotativa.io云服务的拥有者。

在 rotativa 的 SaaS 版本中,您可以使用 Nuget 库,该库可让您从剃刀视图构建 PDF,而无需参考 Asp.net:

https://rotativa.io/site/blog/instructions/2020/07/31/create-pdf-in-net-core-without-aspnet.html

【讨论】:

  • 谢谢@Giorgio Bozio 先生,我要试试,告诉我
  • 您好 @Giorgio Bozio 先生,我使用了 RotativaHQ 并按照 tuto 操作,它工作正常,我收到了文件的字节,我是否可以完全访问我的文件,他们会阻止我吗使用免费版谢谢
  • 您好 @Giorgio 先生,我想添加这个,我已经尝试过使用 httprequest,比如单击链接并调用有效的操作,但是在后台作业调用该函数时,我收到了这个错误:如果没有可用的活动 HttpContext 实例,则无法创建控制器上下文
  • H @Sylla 您是否按照说明使用 RotativaIO.NetCore?
  • 你好 @Giorgio 先生,我使用 Asp.net mvc 这就是我安装 HQ 的原因,或者即使我不使用 asp.net 核心,他也可以工作???
【解决方案3】:

您可以按照 Giogio Bozio 的建议检查云服务,或者,如果您打算使用当前的 Rotativa DLL,您可以尝试我在评论中建议的解决方案。

您的代码应如下所示(您提供的代码中嵌入了示例解决方案):

var Avis_views = new ViewAsPdf("~/Views/AvisAutomatique/ExportPdfDebit.cshtml", printa)
{
    PageMargins = new Rotativa.Options.Margins(0, 0, 0, 0),
    MinimumFontSize = 14,
    /*ageHeight=60,*/
    PageOrientation = Rotativa.Options.Orientation.Portrait,
    PageSize = Rotativa.Options.Size.A4,
};

var fileName = "DEBITADVISE_" + Numcpt + "_" + _GetTransDateTime() + ".pdf";
//var path = Path.Combine(@"C:\DocumentPdf\", fileName);

// Create an instance of your controller class (in example, I guess you are using mentioned quotesController)
QuotesController controllerInstance = new QuotesController();

// Generate RouteData based in your controller (even if you are not using on in this situation, you can reference an existent one)
RouteData route = new RouteData();
// Simply change "MyAction" and "QuotesController" for the name of real action name and controller, respectively
route.Values.Add("action", "MyAction");
route.Values.Add("controller", "QuotesController");

// Generate controller context, to use in the next step
ControllerContext newContext = new ControllerContext(new HttpContextWrapper(System.Web.HttpContext.Current), route, controllerInstance);

byte[] abc =  Avis_views.BuildFile(newContext); // Here you send the generated controller context
//System.IO.File.WriteAllBytes(path, abc);
MemoryStream ms = new MemoryStream(abc);

sendemail(email, fileName, abc, emailc);

请检查它是否适合您,并且不要忘记包含所需的参考资料:

using System.Web;
using System.Web.Routing;
using System.Web.Mvc;

【讨论】:

  • 您好 @Dave Miller 先生,我试过了,但同样的问题,httcontext 仍然为空
  • 嗨@Sylla。你的意思是 System.Web.HttpContext.Current 是空的,不是吗?
  • 是的@Dave Miller
  • 抱歉@Sylla,之前不能参加。然后,我能看到实现这一目标的唯一机会是,一方面,按照 Giogio Bozio 所说的使用 RotativaHQ 的说明,另一方面,创建一个使用具有此逻辑的 MVC 应用程序的 Web 服务(它是有点乏味,但这是另一种解决方法)。我看到您正在选择 Rotativa SaaS 版本,祝您好运!
【解决方案4】:

在尝试使用 rotativa 一周后,我用 Itextsharp 资助了另一个解决方案,我是如何做到的: 1-首先安装包 ItextSharp 和 ItextSharp XMLWorker
2- 我在 html 页面中设计了我的模板,并将 css 放在
文件夹中(@"C:\Templates\Credit.html"; @"C:\Templates\pdfview.css";)
3-用这个方法读取html和css

public string RenderViewToString(string viewPath)
    {
        var file = new FileInfo(viewPath);
        using (StreamReader streamReader = file.OpenText())
        {
            string viewLine = "";
            var result = string.Empty;
            while ((viewLine = streamReader.ReadLine()) != null)
            {
                result = result + viewLine;
            }
            return result;
        }
    }

并使用此方法转换为pdf:

 public byte[] GetPDF(string param1,string param2,etc...)
    {
        
        byte[] bPDF = null;
        try
        {
            pHTML = pHTML.Replace("{{parameter form the html file}}", param1);
            pHTML = pHTML.Replace("{{parameter form the html file}}", param2);
            
            MemoryStream ms = new MemoryStream();
            TextReader txtReader = new StringReader(pHTML.ToString());

            
            var image = @"C:\Templates\avis.jpg";
            iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(image);
            jpg.SpacingBefore = 10f;
            jpg.ScaleToFit(50, 50);
            jpg.Alignment =iTextSharp.text.Image.ALIGN_RIGHT;
           

            
            doc.Open();
            doc.Add(jpg);
            using (var cssMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(csstemp)))
            {
                using (var htmlMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(pHTML)))
                {
                    XMLWorkerHelper.GetInstance().ParseXHtml(oPdfWriter, doc, htmlMemoryStream, cssMemoryStream);
                }
            }
            //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;
        }
        catch (Exception ex)
        {
            var mess = ex.StackTrace;
            var mess2 = ex.Message;
        }

        return bPDF;


    }

感谢您希望对某人有所帮助

【讨论】:

  • 嗨,@Sylla。很高兴知道它现在正在工作。您可以标记此回复的答案,因为它似乎终于解决了您的问题。
  • 请按照此链接中给出的步骤操作:meta.stackexchange.com/questions/5234/…
猜你喜欢
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-06
相关资源
最近更新 更多