Tamzoid
Tamzoid

Reputation: 29

How to add dynamic header to generated PDF document

Im using TuesPechkin to ceate Pdfs from dynamic Html. The body is easy as it can take a Html string, the header & footer however only take Urls. I have them stored locally atm as html, I can bring them in to the document, but without any dynamic content.

Is there a way to use Razor or similar to bring a value in like this -

var document = new HtmlToPdfDocument
{
    GlobalSettings = new GlobalSettings(),
    Objects = 
    {
        new ObjectSettings 
        { 
            HtmlText = "<p>Some Html</p>",
            Footer = new FooterSetting { PageUrl = "file://C:/file.cshtml?Name=name" }
        }
    }
};

Html looking something like

<html>
    <p>Name: @Request["name"]</p>
</html>

The project is just a class library so I believe it's missing some aspects needed to run razor?

Thanks in advance for any input.

Upvotes: 0

Views: 2440

Answers (2)

Alex
Alex

Reputation: 1

I know it is an old question. But I spend a couple of days to figure out how to make TuesPechkin headers truly dynamic. As I have a very long data table which spreads to several PDF pages, I need to have header, which has column headers repeated on every page. But because first page has a summary on the top of the page and the table data starts below the summary, I need to alter header that is shown on very first page. HtmlUrl in HeaderSettings is an URL, which is the same on every page of generated PDF, so I need workaround which is not documented on TuesPechkin software.

PDF generation:

using TuesPechkin;
...
private static StandardConverter _converter;
...

string headerHtml = $"http://127.0.0.1/api/GetPdfHeader?"+
   $"accountId={AccountId}&accName={AccountHolderName}" +
   $"&dateGen={DateGenerated}&range={DateRange}"+
   $"&tagFilter={FilterVal}&filters={FiltersUsed}";
string html = ""; // main page content (long HTML table) is here
            // 
//Configure the converter
if (_converter == null)
{
   _converter = new ThreadSafeConverter(
      new RemotingToolset<PdfToolset>(new WinAnyCPUEmbeddedDeployment(
         new TempFolderDeployment())));
}
var header = new HeaderSettings()
{
   HtmlUrl = headerHtml.Replace(" ", "%20")
};
byte[] pdfBytes = _converter.Convert(new HtmlToPdfDocument {
   GlobalSettings = global,
   Objects = {
      new ObjectSettings { HtmlText = html, HeaderSettings = header }
   }
});
// Use these PDF bytes array to save PDF or pass it back to your code

Header is generated by an HTTP call. Implementation:

     public System.Net.Http.HttpResponseMessage GetPdfHeader(string accountId, string accName, 
string dateGen, string range, string tagFilter, string filters)
  {
     var request = this.Request;
     var queryString = request.RequestUri.ParseQueryString();
     int page = 0;
     if (queryString!=null && queryString["page"] != null)
     {
        page = System.Convert.ToInt32(queryString["page"]);
        int totalPages = System.Convert.ToInt32(queryString["topage"]);
     }

     string html = ""; // Generate HTML for header here
     // Update html with passed parameters accountId, accName, dateGen etc.

     if (page == 1)
     {
        // remove table header on first page
        html = UpdateHtml(html); // modify
     }

     var resp = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK)
     {
        Content = new System.Net.Http.StringContent(html, Encoding.UTF8, "text/html")
     };
     return resp;
  }

Note, that inside we have a "page" variable, passed with every HTTP request, which can be used in custom HTML generation. This code will be called every time a new page is added to PDF when TuesPechkin generates it. For example if you have 5 pages, it will be called 5 times. It also has "topage" parameter which stands for totalPages.

Upvotes: 0

Nic
Nic

Reputation: 12846

You can try rendering the razor code to a string, then saving it as a file and finally export the file to PDF.

Sometime like this:

Razor to String

public string RenderRazorViewToString(string viewName, object model)
{
    ViewData.Model = model;
    using (var sw = new StringWriter())
    {
        var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);
        viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
        return sw.GetStringBuilder().ToString();
    }
}

Export to PDF

public void MyPDFExport()
{
    string url = @"d:\Foo.html";
    string html = RenderRazorViewToString("File", "myName");
    System.IO.File.WriteAllBytes(url, System.Text.Encoding.ASCII.GetBytes(html));

    var document = new HtmlToPdfDocument
    {
        GlobalSettings = new GlobalSettings(),
        Objects = 
        {
            new ObjectSettings 
            { 
                HtmlText = "<p>Some Html</p>",
                FooterSettings = new FooterSettings { HtmlUrl = url }
            }
        }
    };
    IConverter converter =
        new ThreadSafeConverter(
            new RemotingToolset<PdfToolset>(
                new Win32EmbeddedDeployment(
                    new TempFolderDeployment())));

    byte[] result = converter.Convert(document);
}

View File.cshtml

@model string

<html>
    <p>Name: @Model</p>
</html>

Upvotes: 1

Related Questions