On the Road to iTextFileResult: Getting the Results from System.Web.MVC.WebFormViewEngine

I’m in the process of building a new ActionResult for ASP.NET MVC. This new ActionResult will allow you to transform data into a PDF, RTF, or HTML (it uses iTextSharp behind the scenes, and yes, I have a working prototype right now that isn’t all that useful yet.. and you have to know way too much in order to use it as of this time).

Essentially what I want to do is use any view engine that the programmer chooses and convert the resulting html, xml, or regular string data into a file that gets pushed to the browser. All this works for all of the alternative engines, but the default engines doesn’t work… so, without further adieu

Challenge #1: WebFormViewEngine ignores the TextStream you give it

Actually this might be the only challenge here. I tried numerous solutions.. none of which worked. I finally cracked open the MVC source code and determined that I needed to inherit form their class and do some overriding… In my API I created BufferedViewPage, and BufferedViewPage<T> so I could intercept the RenderView code. Here’s a copy of my current (in progress) version of BufferedViewPage:

   1: public class BufferedViewPage : ViewPage, IBufferWebFormView
   2: {
   3:     public TextWriter Writer { get; set; }
   4:  
   5:     public override void RenderView(ViewContext viewContext)
   6:     {
   7:         ViewContext = viewContext;
   8:         InitHelpers();
   9:         // Tracing requires Page IDs to be unique.
  10:         ID = Guid.NewGuid().ToString();
  11:         var wfv = viewContext.View as WebFormView;
  12:         var page = (wfv!=null?wfv.ViewPath:""); // View should always be WebFormView
  13:  
  14:         if (viewContext.ViewData["____writer"] != null)
  15:         {
  16:             Writer = viewContext.ViewData["____writer"] as TextWriter;
  17:         }
  18:         ProcessRequest(new HttpContext(new simpleWR(page, viewContext.HttpContext, viewContext.HttpContext.Response.Output)));
  19:         if (Writer != null)
  20:             this.Render(new HtmlTextWriter(Writer));
  21:  
  22:     }
  23: }

You will see that I’m injecting a new writer into the ViewData (I’ll eventuually come up with a better mechanism, but it works for now). My code for the most part copies what the standard WebFormViewPage does except that you’ll see that if the page is a WebFormView it runs Render after running ProcessRequest. I’m not sure if this is problematic or not, but it works! Before I release the actual library I will probably clean this up quite a bit (this is mainly an exercise in helping anyone who wants to use the WebFormViewEngine, but somehow capture the result and do something else with it..

BTW, the part of the code here you don’t see is that before I render I make sure buffering is on and then I clear the response text after generating this (which clearing the response was about the only thing I could do.. that generated data in HttpContext.Current.Response.Output is lost to you… at least I couldn’t find a way to get at it…)

Print | posted on Thursday, September 10, 2009 10:27 AM
Comments have been closed on this topic.