Generating PDF or XPS documents with Infragistics Documents in ASP.NET MVC applications (Part 2)

Damyan Petev / Monday, March 5, 2012

In this blog we will pick up from where we left off in the previous one. If you have missed it you can read the first part on Generating PDF or XPS documents with Infragistics Documents in ASP.NET MVC. In that post we saw how we can create our report, add various layouts, content and settings. We also have our data now and a method to transform our physical file into a proper form to be bound to the tree. Now we have to turn our data into a client-side tree control.

Adding the jQuery Tree

For the jQuery tree you would need the default CSS and script files just like any of the NetAdvantage for jQuery controls. Since the tree is not the main focus, I will skip most of the explanations. Refer to our Deployment Guide for more information. Here’s just an example snippet of the required resources:

  1.  <!-- CSS -->
  2. <link href="@Url.Content("~/Content/themes/min/ig/jquery.ui.custom.min.css")" rel="stylesheet" type="text/css" />
  3. <link href="@Url.Content("~/Content/themes/base/ig.ui.min.css")" rel="stylesheet" type="text/css" />
  4. <!-- Scripts -->
  5. <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
  6. <script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
  7. <script src="@Url.Content("~/Scripts/ig.ui.min.js")" type="text/javascript"></script>

Next up is providing your data to the View – in the respective controller / action combo (the default one for the purposes of the example) create a View with the that data being model, in our case what is returned by the GetData() method we saw in the previous post:

  1. public ActionResult Index()
  2.  {
  3.      ViewBag.Message = "Select yourself in the company hierarchy tree and get a copy!";
  4.      return View(Infragistics_Documents.Models.Data.GetData());
  5.  }

And finally in you View add the Infragistics MVC namespace and create a tree and bind it to the Model. We would also set the ‘SingleBranchExpand’ property to true, this would allow the tree to only have one branch expanded at a time which would save us a lot of hassle trying to recreate it in our document later on:

  1. @using Infragistics.Web.Mvc
  1. @(Html.
  2.     Infragistics().
  3.     Tree().
  4.     ID("OrgTree").
  5.     SingleBranchExpand(true).
  6.     Bindings(bindings =>
  7.     {
  8.         bindings.
  9.         TextKey("Text").
  10.         ChildDataProperty("Positions").
  11.         Bindings(b1 =>
  12.         {
  13.             b1.
  14.             TextKey("Text").
  15.             ChildDataProperty("Employees").
  16.             Bindings(b2 =>
  17.             {
  18.                 b2.TextKey("FirstName");
  19.             }
  20.           );
  21.         });
  22.     })
  23.     .DataSource(Model).
  24.     DataBind().
  25.     Render()
  26. )

Putting the pieces together

The client

To make everything so far work towards a single goal (delivering a document) we would need to save the user’s interaction in some way, in our case selecting the employee in the tree. Simple and easy implementation will be using hidden fields. Lets have three – having more things saved makes things easier but also makes for possible additional customization added to the final document, just don’t overdo it. Now some of what you would see in the demo project are for the sake of having more examples and might be completely unnecessary. Here an example of what you can use:

  1. <input type="hidden" name="path" value="" />
  2. <button type="submit"> Download document with this tree! </button>

Most importantly – name your hidden field and have your button to be of type submit. Since the client-side control is a fully functional jQuery widget we will rely on its events and event properties to extract and save the data in a very convenient way. All events have default names you can use to attach to and here’s how to do that:

  1. <script type="text/javascript">
  2.     $("#OrgTree").live("igtreeselectionchanged", function (evt, ui) {
  3.         $('input[name="selectedNode"]')[0].value = ui.newNodes[0].data.FirstName;
  4.         $('input[name="path"]')[0].value = ui.newNodes[0].path;
  5.     });
  6. </script>

As you can see we use the user selecting a tree node to save its path and just for the sake of it – the name. Of course you are not limited to just selection, you can use events for collapsing and expanding nodes to record the state of the tree (an attempt on that you can find included in the demo).

The submit button probably gave away the final piece for the client – wrapping all of the above in a from:

  1. @using (Html.BeginForm())
  2. {
  3.     // omitted content
  4. }

The server

Since we have the values in client being saved and posted back to the server, we can now make a controller that would accept them, create the document and send it to the client. Use the names of the inputs as name for parameters. We didn’t define a special URL in our form so the action for the client post would be the same as the current controller’s and should be marked to accept HTTP POST verb. Inside we will provide some handling in case the user doesn’t select anything and call the method to generate the document and send it to the client otherwise. Here is the code:

  1. [HttpPost]
  2. [ActionName("Index")]
  3. public void CreateDoc(string path, string expandedNodes, string selectedNode)
  4. {
  5.     if (path != "")
  6.     {
  7.         //parse the path to int
  8.         int[] newPath = path.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries).ToList().ConvertAll(x => int.Parse(x)).ToArray();
  9.         //and generate a report
  10.         Report report = GenerateDoc(newPath, expandedNodes, selectedNode);
  11.  
  12.         //send for download
  13.         Response.Clear();
  14.         Response.ContentType = "application/octet-stream";
  15.         Response.AppendHeader("content-disposition", "attachement; filename=" + "Document.pdf");
  16.         report.Publish(Response.OutputStream, FileFormat.PDF);
  17.         Response.End();
  18.     }
  19.     else
  20.     {
  21.         //nothing selected, so send the user to proper message and back
  22.         Response.Redirect("/home/about");
  23.     }
  24. }

 

The About view merely contains a message prompting the user to select something and send him back to the default page. The document generation has been taken out in a separate method with most of the code you have seen in Part 1 with a few minor tweaks. Note line 16 which is the process of writing the report in the response outgoing stream as mentioned before, so basically that makes sending it to the client worth about one line –simple as that.

The tree creation itself is also in a separate method as it involves some node creation going down the data based on the path and adding captions, but nothing really special and you can find it in the demo. Once again, this is just one (quick) way to do this – the implementation is really up to you.

Wrapping up

At this point you will have an ASP.NET MVC application with jQuery Tree on the client side and the Infragistics Document Engine producing customized PDF or XPS documents with the quality to keep your users satisfied. What is best described with the result of this igTree:

Document Generation with jQuery tree in APS.NET MVC and the Infragistics Document Engine

being translated to this tree in a PDF document:

Inside a Document generated with the Infragistics Document Engine

To get a quick feel of how you can benefit from all this visit our Infragistics Documents Online Samples and as usual you can download the demo project (keep in mind at least a trial version of NetAdvantage for jQuery is required to build and run it).

Hope this was interesting and helpful. Send a message to dpetev@infragistics.com or @DamyanPetev should you have any questions.