0

So I have a view from which I am making a pdf using Rotativa. I want to send this pdf as a mail attachment. None of the solutions I have found have been usefull. PLease help a brother out. here is the code

public ActionResult SendMail(int? id)
    {
        if (ModelState.IsValid)
        {

            Timetable timetable = db.Timetables.Find(id);
            var pdf = new ViewAsPdf(timetable)
            {
                FileName = "TestPartialViewAsPdf.pdf"
            };
            var students = timetable.Class.Students.ToList();
            List<String> mails = new List<string>();

            foreach (var item in students)
            {
                
                if (Request.Form[item.St_id.ToString()] == null)
                {
                    continue;
                }
                mails.Add(item.St_email);
            }

            foreach (var maili in mails)
            {
                using (MailMessage mail = new MailMessage())
                {
                    mail.From = new MailAddress("razaabbas768@gmail.com");
                    mail.To.Add(maili);
                    mail.Subject = "GMA Timetable";
                    mail.Body = "<h2>Timetable</h2>";
                    mail.IsBodyHtml = true;
                   mail.Attachments.Add(pdf);

                    using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                    {
                        smtp.Credentials = new NetworkCredential("razaabbas768@gmail.com", "password");
                        smtp.EnableSsl = true;
                        smtp.Send(mail);
                    }
                }

            }
            return RedirectToAction("Index", "Classes");

        }
        return RedirectToAction("Home", "Index");
        
    }

EDIT

here is my full controller that contains this action.

Thank you all soo much for the help. Its really appreciated.

public class TimetablesController : Controller
{
    private GMASchoolProjectEntities db = new GMASchoolProjectEntities();

    // GET: Timetables
    public ActionResult Index(int? page)
    {
        var timetables = db.Timetables.Include(t => t.Class).Include(t => t.Cours).Include(t => t.Teacher).OrderBy(t=>t.Ti_id);
        int pageSize = 16;
        int pageNumber = (page ?? 1);
        string[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        //ViewData["days"] = days;
        ViewBag.Days = days.ToArray();
        string[] time = { "9am", "10am", "11am", "12pm", "1pm" };
        ViewBag.Time = time.ToArray();
        return View(timetables.ToPagedList(pageNumber, pageSize));
    }
    public ActionResult Index_classwise(int? id, int? page)
    {
        Class @class = db.Classes.Find(id);
        int pageSize = 6;
        int pageNumber = (page ?? 1);
        var Ctimetables = @class.Timetables.ToList();
        string[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
        string[] time = { "9am", "10am", "11am", "12pm", "1pm" };
        ViewBag.Days = days.ToArray();
        return View("Index",Ctimetables.ToPagedList(pageNumber, pageSize));
    }

    // GET: Timetables/Details/5
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Timetable timetable = db.Timetables.Find(id);
        if (timetable == null)
        {
            return HttpNotFound();
        }
        return View(timetable);
    }

    // GET: Timetables/Create
    public ActionResult Create()
    {
        ViewBag.Ti_cl_fk_id = new SelectList(from cc in db.Classes
                                             where cc.Cl_status == 1
                                             select cc, "Cl_id", "Cl_name");
        ViewBag.Ti_co_fk_id = new SelectList(from co in db.Courses
                                             where co.Co_Status == 1
                                             select co, "Co_id", "Co_name");
        ViewBag.Ti_Te_fk_id = new SelectList(from te in db.Teachers
                                             where te.Te_status == 1
                                             select te, "Te_id", "Te_name");
        return View();
    }

    

    // POST: Timetables/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Ti_id,Ti_day,Ti_start,Ti_end,Ti_cl_fk_id,Ti_co_fk_id,Ti_Te_fk_id")] Timetable timetable)
    {
        if (ModelState.IsValid)
        {
            db.Timetables.Add(timetable);
            db.SaveChanges();
            return RedirectToAction("Index", "Classes");
        }

        ViewBag.Ti_cl_fk_id = new SelectList(db.Classes, "Cl_id", "Cl_name", timetable.Ti_cl_fk_id);
        ViewBag.Ti_co_fk_id = new SelectList(db.Courses, "Co_id", "Co_name", timetable.Ti_co_fk_id);
        ViewBag.Ti_Te_fk_id = new SelectList(db.Teachers, "Te_id", "Te_name", timetable.Ti_Te_fk_id);
        return View(timetable);
    }

    // GET: Timetables/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Timetable timetable = db.Timetables.Find(id);
        if (timetable == null)
        {
            return HttpNotFound();
        }
        ViewBag.Ti_cl_fk_id = new SelectList(db.Classes, "Cl_id", "Cl_name", timetable.Ti_cl_fk_id);
        ViewBag.Ti_co_fk_id = new SelectList(db.Courses, "Co_id", "Co_name", timetable.Ti_co_fk_id);
        ViewBag.Ti_Te_fk_id = new SelectList(db.Teachers, "Te_id", "Te_name", timetable.Ti_Te_fk_id);
        return View(timetable);
    }

    // POST: Timetables/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "Ti_id,Ti_day,Ti_start,Ti_end,Ti_cl_fk_id,Ti_co_fk_id,Ti_Te_fk_id")] Timetable timetable)
    {
        if (ModelState.IsValid)
        {
            db.Entry(timetable).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.Ti_cl_fk_id = new SelectList(db.Classes, "Cl_id", "Cl_name", timetable.Ti_cl_fk_id);
        ViewBag.Ti_co_fk_id = new SelectList(db.Courses, "Co_id", "Co_name", timetable.Ti_co_fk_id);
        ViewBag.Ti_Te_fk_id = new SelectList(db.Teachers, "Te_id", "Te_name", timetable.Ti_Te_fk_id);
        return View(timetable);
    }

    // GET: Timetables/Delete/5
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Timetable timetable = db.Timetables.Find(id);
        if (timetable == null)
        {
            return HttpNotFound();
        }
        return View(timetable);
    }

    // POST: Timetables/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public ActionResult DeleteConfirmed(int id)
    {
        Timetable timetable = db.Timetables.Find(id);
        List<StudentAttendence> atten = timetable.StudentAttendences.ToList();
        foreach (var item in atten)
        {
            db.StudentAttendences.Remove(item);
        }
        db.Timetables.Remove(timetable);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    public ActionResult MarkAttendence(int id)
    {
        Timetable timetable = db.Timetables.Find(id);

        return RedirectToAction("Create", "StudentAttendences", new { id = id });
    }
    public ActionResult ViewAttendence(int id)
    {
        Timetable timetable = db.Timetables.Find(id);

        return RedirectToAction("TimetableWiseAttendence", "StudentAttendences", new { id = id });
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
    [HttpGet]
    public ActionResult SendMail()
    {
        var students = db.Students;
        ViewBag.students = students;
        return View("SendMail");
    }
    [HttpPost]
    public ActionResult SendMail(int? id)
    {
        if (ModelState.IsValid)
        {
            Timetable timetable = db.Timetables.Find(id);
            var pdf = new ViewAsPdf(timetable)
            {
                FileName = "TestPartialViewAsPdf.pdf"
            };
      

            var myPdfAsBytes = pdf.BuildFile(this.ControllerContext);

            
            var students = db.Students.ToList();

            

            List<String> mails = new List<string>();

            foreach (var item in students)
            {
                
                if (Request.Form[item.St_id.ToString()] == null)
                {
                    continue;
                }
                mails.Add(item.St_email);
                

            }

            foreach (var maili in mails)
            {
                using (MailMessage mail = new MailMessage())
                {
                    mail.From = new MailAddress("razaabbas768@gmail.com");
                    mail.To.Add(maili);
                    mail.Subject = "GMA Timetable";
                    mail.Body = "<h2>Timetable</h2>";
                    mail.IsBodyHtml = true;
                    mail.Attachments.Add(new Attachment(new MemoryStream(myPdfAsBytes), "MyFileName.pdf"));

                    using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                    {
                        smtp.Credentials = new NetworkCredential("razaabbas768@gmail.com", "password");
                        smtp.EnableSsl = true;
                        smtp.Send(mail);
                    }
                }

            }
            return RedirectToAction("Index", "Classes");

        }
        return RedirectToAction("Index", "Students");
        
    }

}
  • So, what in the code exactly is not working? Do you get e-mails, but without attachments, no mails at all, ...? – AsheraH Jul 27 '20 at 10:41
  • I am getting the mails alright. the mail.Attachments.Add(pdf); does not accept Rotativa.ViewAsPdf as a parameter. Rather it accepts System.Mail.Attachment. I dont know how to convert it to acceptable datatype. – Syed Raza Abbas SRA Jul 27 '20 at 10:57

1 Answers1

0

You can convert the returned view as pdf to bytes using Rotativa and BuildFile. You then stream it to your mail attachment like so:

public ActionResult SendMail(int? id)
{
    if (ModelState.IsValid)
    {

        Timetable timetable = db.Timetables.Find(id);
        var pdf = new ViewAsPdf(timetable)
        {
            FileName = "TestPartialViewAsPdf.pdf"
        };

        //CONVERT TO BYTES HERE
        var myPdfAsBytes = pdf.BuildFile(this.ControllerContext);

        var students = timetable.Class.Students.ToList();
        List<String> mails = new List<string>();

        foreach (var item in students)
        {
            
            if (Request.Form[item.St_id.ToString()] == null)
            {
                continue;
            }
            mails.Add(item.St_email);
        }

        foreach (var maili in mails)
        {
            using (MailMessage mail = new MailMessage())
            {
                mail.From = new MailAddress("razaabbas768@gmail.com");
                mail.To.Add(maili);
                mail.Subject = "GMA Timetable";
                mail.Body = "<h2>Timetable</h2>";
                mail.IsBodyHtml = true;
                //STREAM THE CONVERTED BYTES AS ATTACHMENT HERE
                mail.Attachments.Add(new Attachment(new MemoryStream(myPdfAsBytes),"MyFileName.pdf"));

                using (SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587))
                {
                    smtp.Credentials = new NetworkCredential("razaabbas768@gmail.com", "password");
                    smtp.EnableSsl = true;
                    smtp.Send(mail);
                }
            }

        }
        return RedirectToAction("Index", "Classes");

    }
    return RedirectToAction("Home", "Index");
    
}
Drewskis
  • 429
  • 6
  • 14
  • Hey @Drewskis I tried this solution earlier. But the issue this solution creates is that it gives me a null reference exception. THat is because my ControllerContext redirects to the page that has the selectlist of people to whom I need to send the mail. While the actual page that needs to be send as pdf attachment is the previous one (the one that has timetable) . Is there any way that I can get my required page as my context? Thanks in advance – Syed Raza Abbas SRA Jul 27 '20 at 13:08
  • Can you provide your full code including where SendMail gets called? You may be able to spoof the controller context as seen in the link below but if you provide more code maybe it can be avoided: https://gist.github.com/2E0PGS/7ef85843464f29aba8335ae204fa56cd – Drewskis Jul 27 '20 at 14:01