'Rotativa .cshtml file as Header and Footer
I have a PDF report from my ASP.NET MVC Project and I'm using Rotativa to generate the PDF, What I want to achieve is to have Header and Footer in my PDF using Header.cshtml and Footer.cshtml file (Razor file). because I need to display data from Database.
You may download the complete project at this link https://wetransfer.com/downloads/421708e46380e7ab4eb6f0de3c1a6cf620220303203032/7f0512
In my Controller, I have this code to display my PDF report
using MyWebReport.Models;
using Rotativa;
using Rotativa.Options;
using System.Collections.Generic;
using System.Web.Mvc;
namespace MyWebReport.Controllers
{
public class HomeController : Controller
{
public ActionResult Report()
{
var report = new List<ReportData>();
var myreport = new MyReport();
report.Add(new ReportData { Header = "This my Header", Footer = "This is footer", Body = "This is Body" });
myreport.ReportDatas = report;
string customSwitches = "--header-html \"{0}\" " + Url.Action("Header", "Home", myreport, Request.Url.Scheme) +
"--footer-html \"{1}\" " + Url.Action("Footer", "Home", myreport, Request.Url.Scheme) +
"--footer-spacing \"10\" " +
"--footer-font-size \"10\" " +
"--header-font-size \"10\" ";
return new PartialViewAsPdf(myreport)
{
PageMargins = new Margins(10, 10, 10, 10),
PageOrientation = Orientation.Portrait,
PageSize = Rotativa.Options.Size.A4,
CustomSwitches = customSwitches
};
}
public ActionResult Header()
{
var report = new List<ReportData>();
var myreport = new MyReport();
report.Add(new ReportData { Header = "This my Header", Footer = "This is footer", Body = "This is Body" });
myreport.ReportDatas = report;
return View(myreport);
}
public ActionResult Footer()
{
var report = new List<ReportData>();
var myreport = new MyReport();
report.Add(new ReportData { Header = "This my Header", Footer = "This is footer", Body = "This is Body" });
myreport.ReportDatas = report;
return View(myreport);
}
public ActionResult Index()
{
return View();
}
}
}
Model:
using System.Collections.Generic;
namespace MyWebReport.Models
{
public class MyReport
{
public List<ReportData> ReportDatas { get; set; }
}
public class ReportData
{
public string Header { get; set; }
public string Body { get; set; }
public string Footer { get; set; }
}
}
Report View Report.cshtml
@model MyWebReport.Models.MyReport
@{
ViewData["Report"] = "View";
}
<html>
<body style="background-color:white">
<div class="container" style="width: 800px; height: 500px">
<div class="row">
<table class="table table-sm table-bordered" style="font-size: 14px; font-weight:bold">
@{
foreach (var item in Model.ReportDatas)
{
<tr style="line-height:10px">
<td style="text-align: center; width: 10%;"><p>@item.Body</p></td>
</tr>
}
}
</table>
</div>
</div>
</body>
</html>
Footer.cshtml
@model MyWebReport.Models.MyReport
<html>
<body style="background-color:white">
<div class="container" style="width: 800px; height: 500px">
<div class="row">
<table class="table table-sm table-bordered" style="font-size: 14px; font-weight:bold">
@{
foreach (var item in Model.ReportDatas)
{
<tr style="line-height:10px">
<td style="text-align: center; width: 10%;"><p>@item.Footer</p></td>
</tr>
}
}
</table>
</div>
</div>
</body>
</html>
Header.cshtml
@model MyWebReport.Models.MyReport
<html>
<body style="background-color:white">
<div class="container" style="width: 800px; height: 500px">
<div class="row">
<table class="table table-sm table-bordered" style="font-size: 14px; font-weight:bold">
@{
foreach (var item in Model.ReportDatas)
{
<tr style="line-height:10px">
<td style="text-align: center; width: 10%;"><p>@item.Header</p></td>
</tr>
}
}
</table>
</div>
</div>
</body>
</html>
Solution 1:[1]
Apart form the error you are receiving, as well as you can notice in your code, you are trying to use an Razor view directly as HTML header, which won't work as you expect in the end, because the code inside the view won't be rendered. You should use an HTML file instead, or, if you want to post some database info (as you exposed), you might call the action to render the Razor view before it is displayed.
Modify the custom switches for Rotativa, using the code to call the action (supose it is called Header as you posted in your code, in Home controller), for example:
string customSwitches =
"--header-html " + Url.Action("Header", "Home", myreport, Request.Url.Scheme) +
" --footer-html " + Url.Action("Footer", "Home", myreport, Request.Url.Scheme) +
" --footer-spacing 10" +
" --footer-font-size 10" +
" --header-font-size 10";
Remember that you are already passing the model to the Header and Footer actions on the previous sentence. Unless you have any special requirement, it should be enough to populate the model once, in your main action (Report, in this case). So your code for these actions could be as follows:
public ActionResult Header(MyReport myReport)
{
return View(myReport);
}
public ActionResult Footer(MyReport myReport)
{
return View(myReport);
}
Moreover, you do not need to use \"{0}\" and \"{1}\" in the custom switches (header and footer lines) or the escaped quotes (footer spacing and fonts lines), please remove them, and change the sentences to look like the code for custom switches suggested before, and be aware not to remove all the spaces between the commands (notice the space in the first character position of each string line in the sample code).
Even with these changes, your header and footer do not display anyway. This is because of the margins, check that if you remove the line PageMargins = new Margins(20, 20, 20, 20),, header and footer will appear on the page. Just try with other values in this options, and play also with footer spacing to get to the point that fullfills your needs. That should do the trick.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |

