1

I am having the hardest time figuring out how to create a pdf and attach it to an automated email. I thought it wouldn't be that hard but have quickly found out that it is much more complex than I imagined. Anyways, what I am doing is I have an order form, and when the customer fills out an order and submits it, I want it to generate a PDF for that order and attach it to an automated confirmation email. I am currently using Rotativa to generate the pdf and if I just ran the action result for generating it, it works perfectly fine which looks something like this:

public ActionResult ProcessOrder(int? id)
{
   string orderNum = "FulfillmentOrder" + orderDetail.OrderID + ".pdf";
   var pdf = new ActionAsPdf("OrderReportPDF", new { id = orderDetail.OrderID }) { FileName = orderNum };
   return pdf;
}

When I added the function to send an automated email after the order form was submitted, that works perfectly fine with just the email by itself. But I can't seem to figure out how to generate the pdf and attach it to the email. The report view that gets the data from the order form is called "OrderReportPDF". My order form is called "Checkout", but the action result I use for this is called "Process Order". I've taken out the code in this function that is for the order form as it is not applicable. The section of my code for sending the email after the form is submitted is:

public ActionResult ProcessOrder(int? id)
{
   //Send a confirmation email
   var msgTitle = "Order Confirmation #" + orderDetail.OrderID;
   var recipient = JohnDoe;
   var fileAttach = //This is where I can't figure out how to attach//
   var fileList = new string[] { fileAttach };
   var errorMessage = "";
   var OrderConfirmation = "Your order has been placed and is pending review." +
                           " Attached is a copy of your order.";
            
  try
  {
    // Initialize WebMail helper
    WebMail.SmtpServer = "abc.net";
    WebMail.SmtpPort = 555;
    WebMail.UserName = recipient;
    WebMail.Password = "12345";
    WebMail.From = "orders@samplecode.com";

    // Send email
    WebMail.Send(to: "orders@samplecode.com",
    subject: msgTitle,
    body: OrderConfirmation,
    filesToAttach: fileList
    );
  }
  catch (Exception ex)
  {
    errorMessage = ex.Message;
  }
  //5. Remove item cart session
       Session.Remove(strCart);
       return View("OrderSuccess");
}

I have been able to find very few articles on this issue using Rotativa and the ones I have found don't work for what I'm doing. Maybe Rotativa won't work for this, I'm hoping it does because I've designed my pdf report it generates from it, and not sure if doing it another way will screw up my formatting of it or not. As you can see at the bottom of the code, I return the view to an "OrderSuccess" page. When I try to implement the first code into the second code, it won't let me "return pdf" to execute the ActionAsPdf that generates the pdf when I do the "return View("OrderSuccess")". It only lets me do one or the other. If anybody knows how I can accomplish this, I need some help. I appreciate any suggestions or feedback. I'm pretty new to this so please be patient with me if I don't understand something.

Richard Wilson
  • 297
  • 4
  • 17
Kip M.
  • 43
  • 8
  • When you call `ActionAsPdf`, it's going to create a file based on the `FileName` you set. Now when you set your `fileAttach` variable it needs to reference the path you set when you called `ActionAsPdf`. Basically, `ActionAsPdf` is going to create a PDF file and you need to use this full file path when you set the `fileAttach` variable. – quaabaam Sep 15 '22 at 17:37
  • @quaabaam I get that, but how do I do the ActionAsPdf within my code? Because if I did the ActionAsPdf, then return pdf, yes it will generate the pdf, but it won't let me do the return View if I do that. I've tried doing the ActionAsPdf without doing "return pdf" but it doesn't create the pdf. – Kip M. Sep 15 '22 at 18:28
  • Did you see this https://stackoverflow.com/questions/32181904/save-pdf-file-as-a-byte-array-or-stream-using-rotativa/32183045 – Scott Mildenberger Sep 15 '22 at 18:31
  • @ScottMildenberger I hadn't seen that, but I definitely just tried it out and it didn't work. It saved the order info and everything, but it didn't send the email or create the pdf. This thing is really driving me nuts. I have no clue why this is so complicated. I would imagine this is an incredibly common function people use on websites when ordering something or taking a test or whatever it is where they'd submit a form and get a confirmation email with a pdf attached. – Kip M. Sep 15 '22 at 19:05
  • @ScottMildenberger's comment should get you where you want to go. Since the PDF is created in the cloud, after you create the PDF in the cloud you need to download it to your server and _then_ attach that download to the WebMail attachments. If you follow the link of the accepted answer [How to save Rotativa PDF on server](https://stackoverflow.com/questions/26608729/how-to-save-rotativa-pdf-on-server#answer-28347657) from ScottMildenberger's comment you will see how to download it to your server. – quaabaam Sep 15 '22 at 19:34
  • I tried numerous times to incorporate it into my code but I couldn't get it to attach. I did however come across another article https://stackoverflow.com/questions/63113282/convert-rotativa-viewaspdf-to-system-mail-attachment . I scrapped the WebMail Helper I was using and tried the System.Net MailMessage and after I plugged everything in it shockingly worked like a charm! It sent the email and the pdf. Thank you all very much for the help. You got me pointed in the right direction! – Kip M. Sep 15 '22 at 20:37

1 Answers1

1

Here is the updated code that fixed my problem and created the pdf, then attached it to an automated email once the order form was submitted:

 public ActionResult ProcessOrder(int? id)
 {
    //1. Generate pdf file of order placed
    string orderNum = "FulfillmentOrder" + orderDetail.OrderID + ".pdf";
    var actionResult = new Rotativa.ActionAsPdf("OrderReportPDF", new { id = orderDetail.OrderID }) { FileName = orderNum };
    var PdfAsBytes = actionResult.BuildFile(this.ControllerContext);

    //2. Send confirmation email
    var msgTitle = "Order Confirmation #" + orderDetail.OrderID;
    var OrderConfirmation = "Your order has been placed and is pending review.<br />" +
                            " Attached is a copy of your order." +

    using (MailMessage mail = new MailMessage())
    {
       mail.From = new MailAddress("orders@samplecode.com");
       mail.To.Add("orders@samplecode.com");
       mail.Subject = msgTitle;
       mail.Body = OrderConfirmation;
       mail.IsBodyHtml = true;
       //STREAM THE CONVERTED BYTES AS ATTACHMENT HERE
       mail.Attachments.Add(new Attachment(new MemoryStream(PdfAsBytes), orderNum));

       using (SmtpClient smtp = new SmtpClient("abc.net", 555))
       {
           smtp.Credentials = new NetworkCredential("orders@samplecode.com", "password!");
           smtp.EnableSsl = true;
           smtp.Send(mail);
       }
     }
     //3. Remove item cart session
     Session.Remove(strCart);
     return View("OrderSuccess");
  }

Thank you again to the people that helped and got me pointed in the right direction! Also, a quick shout out to @Drewskis who posted this answer in convert Rotativa.ViewAsPdf to System.Mail.Attachment where I was able to use it to solve my issue!

Kip M.
  • 43
  • 8