ASP.NET MVC PDF Generation View

by Woodrowg 5. February 2010 10:25

The feeling had not got any better, and now sitting there in the post mortem the feeling I had had ever since I committing the crime was bubbling to the surface. Why had I done it? At the time I could have given you a thousand good reasons, but now with hindsight, I knew they were all lies. Laying on the table was the body of evidence against me, and as we began to dissect it I knew that I alone had killed MVC.

OK enough of the melodramatics; In my last project I created PDF rendering logic in my controller, in hindsight it was ugly horrid to manage and really against the idea of MVC. So let us just keep View and Controller logic separate in the future, OK. Here is my solution feel free to make a better one. I never said the solution was the best, in fact I won’t even go so far as to say that it is good. But it’s better than what I did for my last project and better than anything I found in Google under “asp.net mvc pdf view”.

Let’s start with the controller. Nothing special here just select a list of items from the datacontext and pass them to a view, as it should be. 

public ActionResult Index(String filetype)        {

Foo.Models.FooDataContext dc = new Foo.Models.FooDataContext();     
List<Bar> results = (from b in dc.Bar select b).ToList();  
switch (filetype)
            {               
    case "PDF":
                   
       return View("PDF", results);
               
   
case "TXT":
                   
       return View("TXT", results);
                 
    default:
                   
       return View();          
           
}
}

I then went into the view directory and created a Webform called PDF.aspx, yes a web form not a MVC view page, why? you ask, well that way i get a code behind page that i can abuse and I am to lazy to create them myself.  

Firstly delete the .aspx.design.cs file, it’s gonna break anyway.

Remove all the junk from the page except the header line and change it thus.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="PDF.aspx.cs" Inherits="Foo.Views.Dictionary.PDF<IEnumerable<Foo.Models.Bar>>" %> 

With me so far, good.Now change the line

public partial class PDF : System.Web.UI.Page
to
public partial class PDF<TModel> : System.Web.Mvc.ViewPage<IEnumerable<Models.Bar>>

excellent smithers.

Remove the
protected void Page_Load(object sender, EventArgs e) who needs that anyway.

And add 
public override void  RenderView(ViewContext viewContext){}

In theory this should now run and do nothing, maybe return a blank page but apart from that nada.

Add this code to the RenderView method.

viewContext.HttpContext.Response.ContentType = "application/pdf";
viewContext.HttpContext.Response.AddHeader("Content-Disposition", "attachment;Filename=Test.Pdf");           
MemoryStream m = PDF_Doc();
           
viewContext.HttpContext.Response.OutputStream.Write(m.GetBuffer(), 0, m.GetBuffer().Length);
           
viewContext.HttpContext.Response.OutputStream.Flush();
           
viewContext.HttpContext.Response.OutputStream.Close();
           
m.Close();

and create a method now that does your PDF generation. Just make sure you keep it in this .cs file. That way all your view logic is contained in real view and there is nothing floating around.This was mine

private MemoryStream PDF_Doc()        {            
MemoryStream m = new MemoryStream();
           
Document document = new Document(PageSize.A4, 20, 20, 20, 20);
           
Font[] fonts = new Font[2];
           
fonts[0] = FontFactory.GetFont("HELVETICA", 8.0f);
           
fonts[1] = FontFactory.GetFont("HELVETICA", 10.0f);
           
try
            {                
PdfWriter writer = PdfWriter.GetInstance(document, m);
               
writer.SetPdfVersion(PdfWriter.PDF_VERSION_1_7);
               
writer.CloseStream = false;
               
Phrase footPhraseImg = new Phrase("Page: ", fonts[0]);
               
HeaderFooter footer = new HeaderFooter(footPhraseImg, true);
               
footer.Border = Rectangle.NO_BORDER;
               
document.Footer = footer;
               
document.AddHeader("Header", "BAR");
               
document.Open();
               
HTMLWorker worker = new HTMLWorker(document);
                
foreach (Models.Bar bar in Model)
               
{
                   
document.Add(new Paragraph(bar.Text));
               
}
                          
}
           
catch (DocumentException ex)
            {               
Console.Error.WriteLine(ex.StackTrace);
               
Console.Error.WriteLine(ex.Message);
            }           
document.Close();
           
return m;
        }

As you can see i can now do the same sort of thing for the TXT view, or an excel view, you name it.

In conclusion there is nothing special about a PDF that makes it a controller, so why do people create controllers with PDF generation logic in them. Doing it in the controller will likely work fine for a small application but as soon as it gets to working in a team or with more than one output view ( I mean pdf, word, excel, txt ) the controller will become a mess and bang MVC is dead. I seem to not be the only one who commits this crime, in fact I have yet to find an example on the net that does not pollute the controller with horrid view generation code.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Adventures with Code

Google Caffeine - SEO is about to be shaken up

by Woodrowg 10. August 2009 09:18

There are some interesting features that Google is trying to put online with the hope of killing off any chance of Bing becoming a competition.
A more real-time search, that will be nice but will put a lot of SEO pages at risk. I guess there is going to have to be a major rethink as to the use of landing pages in the future. I doubt anyone will be able to keep all their SEO pages up to date.


I have been campaigning for a search function which takes into account the age of the page you are looking at. I find that as a developer I due roughly 60 – 100 searches a day, half the results can be thrown out as they are over 1 year old. Maybe Google will hold its crown with these new features. In some ways I hope so. But I think what will happen in the end is that new engines will appear that will search specifically and not generically. I would love a search engine that was to do with development and only development. Why not? It could be community driven and we could keep Mr Wong at bay. If anyone has got any VC left over, Lets talk business!!!!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Adventures with Code

ASP.NET MVC V2 Preview 1 Released

by Woodrowg 5. August 2009 06:44

Must visit ScottGu's blog

http://weblogs.asp.net/scottgu/default.aspx

The new MVC version 2 is in beta and is doing alot of very nice stuff with data annotations.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Adventures with Code

External Caching Providers - Performance through outsourcing

by Woodrowg 10. July 2009 08:49

Ok so you have got this great website which you have spent a high percentage of last 6 months writing. It goes live and becomes the next twitter. The pages are small but the graphical designer has made it a thing of beauty and therein lies the problem. Its chewing bandwidth and it is looking like you are going to have to get 4 new servers for the data center just to deliver out the static images, not to mention the old horse of a load balancer that is getting asthma trying to keep up with demand. Plus half your customers are from across the pond which would mean possibly setting up a new co-location just to get a reasonable display time over there.

Where to turn and quick without killing the budget, I have had similar issues in the past believe it or not but I had already planned for them and as a boy scout being prepared is always good. Content delivery networks seem like a last resort but if you plan well from the beginning a switch to a CDN can be painless and an almost enjoyable experience.

We use Akamai but there are a number of providers out there all of which provide a good service. In regards to planning I can only give you one hint. If you are putting your images in a directory called Images in your project I will have to show you the error of your ways.

From the start of a project always plan to have your images on its on subdomain. “What!” I hear you cry, its own sub-domain, but why. By having your own sub domain you have a really nice way to separate your dynamic from your static content. At the beginning you will be able to set up some servers in your own farm running Lighttpd of similar lightweight webserver, yes on linux I know but sometimes you have to bite the sour apple.

The other good think about separate domains is in theory you can maintain your graphics in their own source code environment which means your graphic designers can have their own SCM system and processes, which works really well in bigger teams. When it comes to the time to upgrade to a CDN it can be as simple as creating an account, doing a little config and then repointing your subdomain to the CDN. Some CDNS load the content on demand from a library server, which would be your old image server, and only access the stuff that is actually being used. Which of course saves you the effort of maintaining all the images online via FTP or something similar. I have seen this architecture in action and trust me, it makes sense to get this in on the ground floor.

If you are planning on being big think big!
No I don’t use a CDN for my blog, but maybe one day I might have too!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Adventures with Code

SSPI Context - Erm what have i done wrong

by Woodrowg 3. July 2009 05:49

Having trouble with you SSPI context, Gettting errors like „Cannot generate SSPI context” in visual studio when your laptop is not at work. Look no further the answer is simple.

Do you remember that you wanted to connect from the database from another machine and you turned on TCP/IP in the SQL server configuration tool most likely about the same time you started having issues. There is your problem if you are no longer on the network it can’t get the SSPI context. Just make sure that the Protocol for the alias name you are using is set to named pipes and the problem will go away.

Don’t start messing around with the accounts under which the server starts that will only cause more headaches. You could however at a push just turn off tcp/ip but then what fun would that be ;-)

 http://support.microsoft.com/kb/811889/en-us

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Adventures with Code

Design Patterns in Practice

by Woodrowg 22. May 2009 08:42

I have not been a person that like banding around with techno terms and trying to confuse people. I would not even call myself a geek, I like computers but I have a Fiancée and a life away from the screens (Yes I find two is a minimum as a developer). I have been working in development from almost 10 years now and I have work on many projects in many languages, during this time I have collected a number of experiences and some, like design patterns become part of the Toolkit. What is a toolkit you ask, in my definition a tool is bits of information that is

a.) Worth remembering
b.) You will need again in the future
c.) Will help you be a better person (or at least programmer)

This is not my concept I read it in Steven Kings “On Writing” and was happy to find a concept that was so truly universal. My toolkit contains the tools that I have gathered over the years that have been learned via bad experiences, good experiences and looking at the work of those gifted with greatness. I take each tool out to use sometimes, clean it off a bit and put it back in the kit.

A design pattern is in simplistic terms, a standard solution to a common architectural problem in software development. In essence however we see patterns every day, a red sign means danger. That is a pattern that is so ingrained that you don’t even need to read the text on the sign to know that there is something to be careful of. If you wanted to create a sign to warn people, chances are it would be red! There is no need for you to come up with a pink one, and if you did, in the long term it might have been the wrong decision. 

I like patterns as they are nothing to do with computer languages or frameworks as such and therefore you don’t have to get into a Java .Net debate. You can happily sit with a programmer of another language drinking beer and discussing patterns till the cows come home. Should you ever been in the unfortunate position to have maintain something for someone else, if they have used design patterns you will get to terms with the code a lot more quickly.

This is worth looking at for more info. I’m not Wikipedia you know ;-)
http://en.wikipedia.org/wiki/Design_Patterns_(book).

Good article:

http://www.developerfusion.com/article/8307/aspnet-patterns-every-developer-should-know/

For those of you who know about it, sorry for covering old ground.
For those that have just got a masters degree in information technology, “You take the red pill and you stay in Wonderland and I show you how deep the rabbit-hole goes!”

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Adventures with Code

Issues with APP_Resources

by Woodrowg 15. May 2009 05:34

It was about midnight as I finally completed the last open issues before the first round of customer acceptance testing. With a click of a button the I put my faith in Publish website, with a good feeling that I would be in bed before the cat came home.

ALAS this was not to be. The website wouldn't start, it hung and seemed to be dying a horrid death. After turning off the error pages which in my tired state to about 20 mins to realize would help, I was faced with this

The resource class for this page was not found.

strange I thought, and publisher again. Same issue. Started looking around the web and found something about changes to the file can cause problems and that it needed to recompile. OK try a clean build. Same issue.

OK think, I opened my FTP client and navigated to the site and the lights came on. Strange the whole App_LocalResources Folder was missing. After 'bingin' around I found some references to this.  

Seems that the .RESX files are not being copied as part of the build and to change this you must change the build type to content.

http://forums.asp.net/t/1245742.aspx for example.

I guess its just one of those things but sometimes these little gotchas get you when you least expect it.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Adventures with Code

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen

About the author

Gary, the last of the unbloged is finaly giving up and will try as often as posible to add anything interesting he finds to this site. especially stuff like ASP.net MVC and things to make people smile