Posted by Mark Baylor on 2/19/2009 12:42 AM

Sometimes no matter how hard you search you can’t find a viable solution for a problem. After almost giving up and using the infamous IFRAME, I finally found a good solution so users can save a generated PDF by the correct filename.

History

I built an invoicing application to provide downloadable invoices for our dealer base, and security is of the utmost importance because of the sensitivity of financial data. We needed to find a solution for displaying invoices to said dealers, and make sure it was easy for them to print and save the data.

What we have now for an invoicing system

We decided to go for the downloadable PDF after several other more seemingly viable attempts failed. We tried using Crystal Reports to generate invoices on the fly, but to no avail as the views that have been written run very slowly. We also tried just harvesting data and creating an ASP.NET page to display the data straight on the page without any additional tools. The invoicing data became overly complicated and there were far too many gotchas with business rules to go that route. Rewriting the business rules was just not an option in the timeframe that we were given.

Where we eventually want the invoicing system to go

In the future when we are not moving 100 MPH all the time, there are several options that would make more sense. Datamarts would work great as the data would be optimized for quicker viewing and we can mold the data in any way we would like. We could then throw a Microsoft SQL Reporting Services front end on the data and use it on the web. This would require someone to deeply understand the data and rewrite a report, but it would provide for a better experience online.

Decision on a technology to provide PDFs

We ultimately decided to generate PDFs daily and keep them on a separate server. This offload would:

  • help keep bloat down on the frontend server as we will have thousands of PDF invoices
  • allow for a strong security model. With sensitive financial documents we could not have the files within the web root. By keeping them separate we could use a few .NET technologies to check security and go and grab the file
  • allow for quick file load. All of the slow processing work would be done ahead of time so the dealer would not feel the pain

Initial technologies I tried for PDF handling

I really thought this was going to be easy, so I quickly dove into coding.

Take 1

I decided I would use the Server.TransferFile method in .NET. It would give me control of the response object, and would give me the security I needed as I could use code to check if a dealer had permissions, and then go and get the file using a UNC.  It all worked out great.  I was actually loading it into a modal popup box and the functionality was perfect…until I tried to save the document.  It always came back with the same filename: “pdf.pdf”  That wasn’t going to work as dealers were going to be saving a lot of these invoices.  That would mean having to type in the invoice number manually.  I knew we would have a barrage of complaints right when we launched.

When you display the file inline, the file takes on the “pdf.pdf” filename.  When you use the attachment functionality in the response header it will work as expected.  You can save the file or open the file with the correct filename.

Take 2

I had remembered how an old CMS system I was using called Ektron was using an IFRAME to display files.  There was a save button in the main page, and the file would load in the IFRAME.  I scratched my head when I saw this functionality.  I was irritated at the way it functioned because I hadn’t seem an IFRAME in ages.

Turns out I had to resort to this at first.  By doing this, you can set the frame to load the file with a content header of inline, but also provide a button that uses the content header of attachment.  In this way there was an alternate way of saving the file, as to not irritate dealers.

I couldn’t sleep at night using this technology.  It seemed so 90s.  I thought to myself that I would go with this unless another solution presented itself.

Final technology I went with for PDF handling

Luckily a solution did present itself: the HttpHandler.  ASP.NET has an ashx extension that does not inherit all of the classes that a standard aspx page does.  This means faster speed, and I could make some modifications to the web.config to handle files in a more intelligent way.

I was able to use a wildcard *.ashx in the web.config.  Whenever there was a request for <invoiceNumber>.ashx, I was able to go to the handler, use the value in the wildcard, and pull back the invoice.  The beauty of this is that when you save the file, it uses the page name as the filename.  This filename uses the invoice number that is passed in.

Voila, a usable solution.

Conclusion

Although not the most world class system, I find that actually using world class solutions seems far and few between.  Every infrastructure is different, and in this case this was the best, most efficient solution.  PDFs come up very quickly, a security model is in place, and the whole system has a peppy feel to it.

Comments (22)
Tags: | Categories: Code

Comments

About baylorstudios.

baylorstudios is a small web design studio based in West Bend, WI with Mark Baylor at the wheel.  This blog focuses on the trials and tribulations of being a web developer and the problems that must be overcome to create a website.