How to Embed iTextSharp PDF in View (C# - MVC 5) - c#

Greetings fellow coders!
I've done tons of research on this topic and can't manage to find any resources that truly depict how this process can be done (or if it can be done). So, I'm turning to you all for some advice!
The Issue:
So right now, I have a form that sends the filled out data back to the controller via HttpPost. At this point, I pass that form data to the model function to create the PDF. Now at this point, I have it returning the PDF file if the model function was successful.
PDFMemStream memstream = new PDFMemStream();
CreatePDFinfo formdata = new CreatePDFinfo();
if (ModelState.IsValid)
{
memstream = CreatePDF.Populate_PDFcontent(formdata);
if (memstream.retval.success)
{
// if creating pdf is successful, return file
return File(memstream.mstream, "application/pdf");
}
}
ViewBag.PageTitle = "Cool PDF Project";
ViewBag.TabTitle = "Really Cool PDF Project";
return View(formdata);
I can display this created PDF in a separate tab if I use the code below in the view. This assumes that the current view is called "createPDF". So this part works all fine and dandy.
$('#form').submit(function () {
if ($('#form').valid())
{
window.open('', 'createPDF');
this.target = 'createPDF';
}
});
If I don't use the above code, after the button click, it will remain on the current page and reload the page with only the pdf content in the native browser PDF viewer.
The Needed Solution:
As I stated, everything works perfectly if I wanted the PDF to be populated in at new tab or the existing one. HOWEVER, what I need, is a way to view the PDF on the same page either in a partial view or embedded on the existing page. I could even deal with the PDF being embedded in a new view as long as I could pass the model data to the new view for other sections of that page.
Resources & Articles:
Here's all of the articles and resources I've already looked into and read (so please do not post the same ones):
using ITextSharp to extract and update links in an existing PDF
Displaying a pdf to webpage using iTextSharp?
http://developers.itextpdf.com/content/itext-7-jump-start-tutorial/sharp/chapter-1-introducing-basic-building-blocks
MVC Application to Display embedded PDF documents
https://www.codeproject.com/Questions/890372/How-Can-I-Display-A-Pdf-From-Byte-Array-In-Mvc
https://www.codeproject.com/Articles/66948/Rendering-PDF-views-in-ASP-MVC-using-iTextSharp
C# ASP.NET MVC Create PDF from view Rotativa or iTextSharp?
Convert PartialView Html to String for ITextSharp HtmlParser
How to open a PDF file in an <iframe>?
How to render an ASP.NET MVC View in PDF format
Now some of the articles aren't completely relevant but I included them just in case they may be helpful.
UPDATE:
In case anyone else runs into a similar issue, what I ended up doing was processing the non-PDF related method first, returned a new view with the model data, and then made an AJAX call to a route that creates/generates the PDF. Hopefully that makes sense. Haha. :)
Any suggestions, tips or advice?...

Related

PDFSharp blank pages

Tried to open a pdf result in blank pages. Retry with same pdf displayed all pages with content.
It happen only once & couldn't reproduce it.
My application work with 3 steps.
Open PDF
Add Barcode Image
Save PDF
Source pdf had 2 pages with text content, output pdf had only stamped pdf without content.
I believe something went wrong in following line because number of pages are correct but blank.
PdfDocument document = PdfReader.Open(filePath, PdfDocumentOpenMode.Modify);
I need find reason of failure but don't have any idea what went wrong at first time. I have already gone through following questions but they have different case.
https://stackoverflow.com/a/52453789/9102192
PDFSharp returning blank pages when adding password
Can anyone help me finding root cause for this incident or any guesses ?
I would try to do something like this:
using (PdfDocument pdfDoc = PdfReader.Open("source", PdfDocumentOpenMode.Modify)){
// Logic to insert image into pdf //
pdfDoc.Save("targetPath")
}

iTextSharp | Failing to Output PDF in IE

I recently encountered an issue regarding outputting a PDF generated in iTextSharp into a new window and haven't been able to figure out a way to fix the issue.
This problem only seems to occur in IE, and upon the new window opening, it remains blank and doesn't seem to load the PDF at all. (Where as Chrome and Firefox seem to work just fine)
I'll go through an overview of the process in hopes of providing some assistance to you all:
Step 1:
The User clicks the "Print" button that I have within a View, and this calls the following Javascript to execute:
window.open($("#PrintURL").val(), 'Print_Preview', 'resizable=1');
Step 2:
The URL that is called pulls the appropriate data into a model and then passes that into a partial view, which is passed into a PDFResult, as shown:
//Grabs the Data
var data = reportAgent.GetData();
//Builds a string that contains the Report layout and builds the Report
string html = ControllerContext.RenderPartialAsString("~/Views/Reports/Report.cshtml", data);
return new PDFResult(html, ...);
Step 3:
Within the PDFResult ExecuteResult() method, I build the document that the Report will output, and adjust other parameters, such as PageSize, Headers and Footers.
public override void ExecuteResult(ControllerContext context)
{
//Sets Response to output a PDF
var response = context.HttpContext.Response;
response.ContentType = "application/pdf";
//Generate Document
Document document = new Document();
//Sets Page Size and Styles
//Build Headers and Footers and Add to Document
//Builds the document writer and prepares a Print Dialog upon opening
PdfWriter writer = PdfWriter.GetInstance(document, context.HttpContext.Response.OutputStream);
PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
writer.SetOpenAction(action);
writer.PageEvent = page;
document.Open();
//Iterates through the html string that was passed in and formats the document
document.Close();
}
I cannot seem to figure out why the new window simply remains blank in Internet Explorer, while a majority of other browsers seem to work just fine. (I know I have had this same process work in IE in the past, I'm just stumped currently.)
Any idea/suggestions to improve this process would be greatly appreciated.
UPDATE
I was testing out some of the changes suggested, and when I removed the areas that would build the document and just added the following:
document.Add(new Phrase("TEST"));
which would add just a single line to the PDF and then generate it. I received an "Internet Explorer cannot display the webpage" error, with the option to Diagnose Connection Problems. When clicking the Diagnose Connection Problems option, and it finishes, the PDF is loaded as intended.
Could this be an issue with the PDF not being "ready" when the new window attempts to load it?
(This is in IE8)
I managed to finally solve this issue. It appears that the window was opening prior to the PDF being ready to be displayed. (This was determined by simply refreshing the window and then the PDF would appear properly.)
So rather than opening the window to a specific URL, I generated a window and opened the URL from within the window, which seemed to fix the issue.)

How can I generate a PDF and load the contents of an ASCX asp.net user control?

I have an ASP.NET User control, .ascx and I need to generate a PDF with the contents of the user control. Is this possible, if so can someone point me in the right direction?
Thanks
There are many third-party PDF creation tools out there. One we've used at my work that works well is PdfSharp
As far as outputting the user control's as text, this is what you need to do:
Page page = new Page();
HtmlForm form = new HtmlForm();
[USERCONTROL] uc = (ReportHeaderInfoUC)page.LoadControl("~/UserControls/[NAME OF YOUR USER CONTROL].ascx");
page.Controls.Add(form);
form.Controls.Add(uc);
//call the function on the user control that populates the control and pass in any data needed (if any)
uc.Populate(data);
StringWriter stringWriter = new StringWriter();
this.Server.Execute(page, stringWriter, false);
What you are basically doing here is creating a new WebForm, adding the user control to it and having the server render the output to a stream, which is basically what ASP.NET does for a regular page request.
To write the contents of the outputted user control to a file use:
File.WriteAllText([FILE PATH], stringWriter.ToString());
As long as the user control is only text based, it should not be difficult to output as a pdf with any pdf creation library out there (search for generating pdf, or pdf creation). If your usercontrols have more complex html tags then you basically need to buy a Html 2 Pdf library. I have not been able to find an acceptable free library that supports html to pdf.
You can also build up tables in PDF, but it would be very difficult to convert from html tables to pdf tables generically without buying a library to do that in my experience. You could also code the building of the PDF tables separately from the usercontrol, but again very difficult to combine that function into it.

iTextSharp add pre-existing PDF as a layer to another PDF

I have reports that are being converted into PDFs. Some of these reports have information missing simply because we don't track it. I have created another PDF with the shell of the report and placed input fields controls on it. I would like to know if there is a way to apply the shell PDF to the converted PDF so users can enter information in those blank fields without having to print them out and hand write them? I have done this manually through Adobe Acrobat Pro 9.3 by applying the generated PDF to the shell PDF as a Layer. I have done as much poking around with iTextSharp concerning Layers, but I still haven't found anything that has worked.
Thank you in advanced!
1) Layers won't work with fields. PDF Layers are a part of the page contents. Form fields, as with all annotations, float above the page.
2) Having said that, you can hide and reveal form fields using Acrobat/Reader JavaScript. The "doc" object is usually "this" in field and page entry points, so to show a given field, it's just:
var fld = this.getField("fieldName");
fld.hidden = false;
There are quite a few different places you can add JS to a PDF. Various field events, page events, and document events. You can also set a layer's action to some javaScript. Heck you can set a bookmark's action to be javascript instead of a "go over there" action.
Note that layers are called "Optional Content Groups" (OCGs) in PDF tech-speak. If you really want to create a layer, it looks like it would go something like this:
// layer implements PdfOCG
PdfLayer layer = new PdfLayer("MyLayer", writer);
PdfContentByte cb = getAContentByteFromSomewhere();
cb.beginLayer(layer); // takes PDFOCG object
/* draw stuff to be part of that layer */
cb.endLayer();
There are a number of examples on the iText site corresponding to "iText In Action, 2nd edition" (I don't get paid, the author is a friend). The aforementioned examples can be found here.
This bears repeating: Fields cannot be part of an OCG (layer). They can however be scripted to act like they are.

Generating HTML file which fetch data from SQL in the C# and ASP.NET

I'm new to ASP.NET and now I am creating an HTML file in ASP.NET C# which is stored in an folder. Now when the aspx file is run it will fetch some data and display it in the output. And there is an button. When I click it the HTML file is created.
Now my problem is I want to fetch the same data in the HTML file also to display it and to save it.
I'm creating the HTML file using StreamWriter and writeline in the code-behind. Or is there any other way to convert that aspx output file into an HTML file and save it in the same folder of the project?
protected void Button1_Click(object sender, EventArgs e)
{
string thisdir = Server.MapPath("./New Folder/SalesContract.htm");
StreamWriter sw = new StreamWriter(thisdir, true);
sw.WriteLine("<html>");
sw.WriteLine("<head>");
sw.WriteLine("<title> Sales Invoice</title>");
.............
sw.WriteLine("<b> <label for=lb_seller1 value=" + ds.Tables[0].Rows[0]["po_seller_Name"].ToString() + "/></b><br/>");
........
sw.WriteLine("</body>");
sw.WriteLine("</html>");
sw.Flush();
sw.Close()
}
It is the sample I'm using.
I'm fetching the data to display in the aspx output and it works.
Now I also need to fetch the same data in this file also.
This is a totally non-standard and inefficient way to do this.
The normal way to do it would be to have a standard aspx page, with some sort of repeater control or datagrid on it that displays the required data, and then you can navigate to that page from elsewhere in your web site. You pass the appropriate variables to the page via the querystring/session/whatever, and the page uses those variables to then select the data it should display.
If you are trying to have a permanent and immutable page created for each visitor to that page, then follow the above advice but look at methods for generating the page as a PDF document instead.
It is strongly recommended that you use the standard ASP.NET way of producing a HTML page (Repeater controls etc...), rather than attempting to write HTML yourself - this is, after all, exactly the task that ASP.NET was designed for!
If you want to see the rendered HTML for an ASP.NET page then you can use code similar to the following:
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
this.Render(hw);
return sb.ToString();
You need to make sure that you do this late enough in the page lifecycle for the page processing to have completed (for example during SaveStateComplete.)
I would recommend that you go through some ASP.NET tutorials to get a feeling of the framework, and learn how to use it properly. I know it will take some time to get through the tutorials, but I think the time is well spent.
Microsoft's Learn ASP.NET is one place to start. You could probably find a ton more by googling for them.

Categories

Resources