Generating an Image of a PDF Page

I recently completed a project that required a thumbnail image automatically be generated from the first page of every PDF file that is uploaded to the system.  I was rather surprised to find that there was no drop in solution for such a thing.  There are many libraries out there that can create a PDF file from HTML content or an image, but no standalone libraries that could go from PDF to an image.  After testing out a couple of methods, I was able to find what I believe to be the easiest and least invasive method to implement it in a web application..

What You Will Need

To generate images from PDF in your project, you will need a couple of things.

Ghostscript, a set of libraries for working with a PDF.  You will need to download the version specific to your environment (32 bit/64 bit).  You can download those here.

GhostscriptSharp, a wrapper for using the Ghostscript libraries in .NET.  You can download it here.  It is written in C#, so if you are using VB.NET you will need to create a code sub-directory in your Web.config to use the file in your project.

Setup

You will need to do a couple of things to get the Ghostscript components to function before you write any code.  First, you need to extract the gsdll file to a location on your system.  (Either gsdll32.dll or gsdll64.dll depending on your CPU.)

Then, you need to modify GhostscriptSharp.cs to specify the path to the Ghostscript library that you extracted before.  Look for this code on line 12 of the GhostscriptSharp.cs file:

#region Hooks into Ghostscript DLL

[DllImport("gsdll64.dll", EntryPoint = "gsapi_new_instance")]

private static extern int CreateAPIInstance(out IntPtr pinstance, IntPtr caller_handle);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_init_with_args")]

private static extern int InitAPI(IntPtr instance, int argc, string[] argv);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_exit")]

private static extern int ExitAPI(IntPtr instance);

[DllImport("gsdll64.dll", EntryPoint = "gsapi_delete_instance")]

private static extern void DeleteAPIInstance(IntPtr instance);

#endregion

You will need to change the paths in the DllImport constructors to the location of the file on your machine.  The DllImportAttribute only accepts a constant string, so you cannot pass a variable with the path or using a Web.config value.  This prevents you from using Server.MapPath to generate the path to your project’s bin folder, which is also unfortunate.

The Code

The actual implementation of the image generation from PDF is very simple once you have reached this point.  You just need to make a call to the GhostscriptWrapper.GeneratePageThumb method with the path to the PDF, and the path where the image should be saved.  You also specify the page number you want to generate from and the height and width of the final image.  A call to GeneratePageThumb might look like this:

// Creates a 100 x 100 thumbnail of page 1.
GhostscriptWrapper.GeneratePageThumb(pdfFileName, outputFileName, 1, 100, 100);

You will also need to import the GhostscriptSharp namespace in your code file.  That is all that there is to it!  After running your application, you will see the image file in the specified path.

Its important to note that GeneratePageThumb is a shortcut method that will only generate a JPG image.  If you need to have more control over the output of your image, then you will need to use the GenerateOutput method and pass in a GhostscriptSettings object that contains all of your required values.  The GhostscriptSharp link above provides more detailed examples if you need them.

Thanks for reading!  If you have any troubles with the process, feel free to leave a comment below.

From the Bookmarks Bar – July 19, 2013

This week the bookmarks bar has some design and licensing links in addition to a couple of development related links.

Choose a License

Struggling to choose an open source license for your intellectual property?  Answer a couple of questions about your project and this site handles the hard part for you.

Redesigning a Flight Search Application

Rarely do we get detailed look at the redesign of such a data rich application.  We’ve all used a flight search site at one point or another and know how complicated they can be.  Here is Cleartrip’s development log of the process.

Comments in Modern Software Development

The opinion on the usage of comments has changed over time.  Comments used to be absolutely entirely necessary to understand a block of code, but many developers have since turned to better naming and segmentation to take the place of comments.  Here are some additional things to think about regarding comments.

WebAPI in ASP.NET MVC 4

ASP.NET MVC may not seem like the ideal choice for a small WebAPI project, but you can make it work.  Here is a good tutorial on the setup process.

Have some great links from your bookmarks bar that you like?  Post them in the comments below!  Thanks for reading.

System.Web.WebPages conflict between ASP.NET MVC 3 and ASP.NET MVC 4

After installing ASP.NET MVC 4, you may notice that you are unable to load projects that used previous versions of ASP.NET MVC. You may see an error similar to the following:

The type ‘System.Web.Mvc.ModelClientValidationRule’ exists in both ‘c:\Program Files (x86)\Microsoft ASP.NET\ASP.NET MVC 3\Assemblies\System.Web.Mvc.dll’ and ‘c:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v2.0\Assemblies\System.Web.WebPages.dll’

This error occurs because prior to MVC 4, projects did not specify which version of ASP.NET Web Pages to use, since there was only one. Luckily, the fix for this is as simple as updating the project file to the proper reference of System.Web.WebPages. Many developers have not ever needed to modify a project file directly, since the default Visual Studio configuration is often sufficient. This can make editing a project file an intimidating task, so I have assembled detailed steps to solve the problem.

From the Solution Explorer, right click on the project and click “Unload Project” from the context menu.

The "Unload Project" menu item in Visual Studio 2010.

The “Unload Project” menu item in Visual Studio 2010.

You should see that the project is now marked with (unavailable). Right click on the project again and you should be able to select a new item, “Edit {Your Project Name}.csproj”. The extension will be displayed as .vbproj for VB.NET projects.

The "Edit Project" menu item in Visual Studio 2010.

The “Edit Project” menu item in Visual Studio 2010.

An XML configuration file will open. This contains all of the information that tells Visual Studio how to run your project. Scroll down (or search the file) until you find the following line:

<Reference Include="System.Web.WebPages"/>

Replace that entire line with this:

<Reference Include="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>

Save the changes to the project file. Right click the project name in the Solution Explorer again. This time, select “Reload Project”. Your project will reopen in Visual Studio and should now build and run properly.

In simple terms, what we have done here is update the Reference tag to include version information, which resolves the conflict for Visual Studio.  It now knows which version of System.Web.WebPages you intend to use for your project.

Thanks for reading.  Still having trouble resolving the error?  Feel free to leave me a comment below!

An in depth look at ASP.NET MVC’s TempData

Ask around about using TempData in ASP.NET MVC and you’ll get plenty of opinions, but few answers to real questions. “It’s contrary to the MVC pattern,” the more respectful responses will say, others will simply “answer” your question with, “Just don’t use it.” It can be a frustrating wall to encounter when you are simply looking for information to evaluate it as an option for your application or when you need to support code that already uses it.

Few technologies actually deserve that “do not use” label for all situations. The amount of technology elitism that is spread around forums and the internet is staggering. As developers, we have all found small applications for less commonly used technology, even if it is just that sparingly used script or internal web site. There are pros and cons to every technology, and any developer worth their weight in dirt should be able to recognize that.

So, OK, end rant. The point is that despite internet opinion, there are some valid uses for TempData. A wizard based process comes to mind. There are times when you just don’t want to post unused data back to the server every time. It’s a cumbersome process and leaves you responsible for validating what comes back from the client every time, whether you’ve already validated it or not.

What is TempData?

TempData is essentially managed session storage. ASP.NET persists your objects on the session between a single request and then removes them afterward, unless you say otherwise. See the code snippet below for a quick sample:

[HttpPost]
public ActionResult WizardStep1(WizardStep1Model model)
{
     if (ModelState.IsValid)
     {
          TempData["Step1"] = model;
          // OR TempData.Add("Step1", model); works fine as well.
          return RedirectToAction("WizardStep2");
     }

     return View(model);
}

In the WizardStep1 action, we save the model from step 1 to TempData if it is valid, and then we move on to step 2. TempData is essentially a dictionary with a key of string and a value of object, so we can use most of the methods that we would normally use for a Dictionary.

Retreving from and keeping TempData

Let’s consider a three step wizard process. Step 1 is as shown above. We start getting data from the user and move on to Step 2. During Step 2, we gather even more data and move on to step 3 where we (finally!) save everything to the database.

In order to get our data from steps 1 through 3 (cue Brian McKnight), we will need some mechanism to keep the data from step 1 while also adding the data from step 2, since it is only persisted for one request. This is where the Keep method comes in.

[HttpPost]
public ActionResult WizardStep2(WizardStep2Model model)
{
     // We use the same key from when we set the data to get it back...
     WizardStep1Model step1 = (WizardStep1Model)TempData["Step1"];
     // BUT, we can also use ContainsKey or TryGetValue in cases
     // where the data might be null...
     if (step1 == null)
     {
          // The user may have skipped step 1, so we go back.	
          // We could save the step 2 data to TempData if we wanted to.
          return RedirectToAction("WizardStep1");
     }

     // We need to tell TempData to keep the Step 1 model for one more request.<br />	
     TempData.Keep("Step1");
     if (ModelState.IsValid)
     {
          // And, if Step 2 is valid, we'll save it as well.	
          TempData["Step2"] = model;	
          return RedirectToAction("WizardStep3");
     }	

     return View(model);
}

We’ll need to keep the data for Step 1 whether the Step 2 model is valid or not, so we do that outside of the if block for ModelState.IsValid.

It is important to note that TempData only persists for one request. The following GET request following the RedirectToAction qualifies as a request. This means that in the get method for each step, we need to keep the TempData so it is there when we post back. Here is how this would work on the redirect to Step 3.

public ActionResult WizardStep3()
{
     TempData.Keep();
     return View();
}

Notice on the call to TempData.Keep in WizardStep2 that we provided the key that we used to store the Step 1 data to TempData. That marks only that object for retention in TempData, meaning that all others that are not marked will be disposed. In WizardStep3, we have both Step 1 and Step 2′s data in TempData. We can call TempData.Keep with no parameters to mark all objects in TempData for retention.

When we post to WizardStep3, we can retreive both Step 1 and Step 2′s data from TempData, using a similar method to Step 2. There we can save them all to a database at the same time using Entity Framework or any other database persistence.

Why TempData over Session?

You can see from the example above that once the user is finished with the wizard process, that we will no longer need the data from those forms. If you were to save this data to the session, it would stay there until you removed it manually, abandoned the session, or the session expired. Like TempData, the session has its benefits, but in this case it is easier to tell TempData on the off chance that we need to keep the data, rather than to always tell the session to get rid of it.

Conclusion

The truth is that many of the complaints about TempData are valid. It is a loophole outside of the MVC pattern and it is a volatile approach to persisting data. The problem is that despite the views of many opinionated developers, no one pattern is the solution to every problem. If anything else, I hope you have the information to decide whether using TempData is right for you.

Thanks for reading. Feel free to leave any questions or comments.

ASP.NET MVC Validation Messages using jQuery UI Tooltips

Traditionally in ASP.NET you add a single Validation Summary above your form that describes the errors that the user has made, or add validation messages next to each control in the form to grab the user’s attention to each particular field.  The example below from the default MVC 4 application illustrates this.

Default Validation Behavior

The default validation behavior in the ASP.NET MVC 4 internet application.

The problem comes when trying to format a form with a large number of fields in a way that is pleasing to the user and also does not use much space on the screen.  jQuery UI tooltips are an alternative option.  The user would see a general message that some errors have occurred on the form or a style change to indicate the fields that are problematic.  This could be a red border around the field, or even an asterisk.  When the user clicks that field to change the data, they are presented with the full error message in a tooltip.  It works well in limited space and it’s flashy!

What You Will Need

This particular walk through uses a strongly-typed Razor view in an ASP.NET MVC 4 project.  Specfically, the Login view from the default “Internet Application” project generated by Visual Studio.  MVC 3 will work fine as well.  If your project does not include jQuery UI, you will need that as well.  The default project does have jQuery UI already included, but not the tooltip libraries, so I just included the newest version from jQuery’s CDN.

Setting Up the Validator

Most commonly, forms in ASP.NET MVC use the Html.ValidationMessageFor method to generate a validation message based on the model field that is passed in.  This causes a problem with jQuery UI tooltips because the ValidationMessageFor method generates span elements and other HTML around the message for formatting purposes.  What we need to use here is the ValidateFor method, which will attach all of our validation data to the input field.  We can still set all of our information in the model as we usually do, but with out all of the extra HTML.  Here are my modifications to the User Name and Password fields to use the ValidateFor method.

<li>
     @Html.LabelFor(m => m.UserName)
     @Html.TextBoxFor(m => m.UserName)
     @{ Html.ValidateFor(m => m.UserName); }
</li>
<li>
     @Html.LabelFor(m => m.Password)
     @Html.PasswordFor(m => m.Password)
     @{ Html.ValidateFor(m => m.Password); }
</li>

One thing should jump out at you right away, and that  is the usage of the ValidateFor method on lines 4 and 9.  ValidateFor is a void method that has no return value, so we need to call it inside of a code block instead of directly like we call Html.TextBoxFor.  A semicolon is necessary as well to terminate the statement.

Adding on a jQuery UI Tooltip

Attaching the jQuery UI tooltip to the control is a piece of cake.  All you need to do is add this snippet of JavaScript to your log in page:

<script type="text/javascript">
    $(function () {
        $(document).tooltip({
            items: ".input-validation-error",
            content: function () {
                return $(this).attr('data-val-required');
            }
        });
    });
</script>

We attach the tooltip only to fields that have the “input-validation-error” class. This allows us to only show the error if there is something wrong with the data that the user has entered. If the data for a field is OK, the user will never see the tooltip.  Our custom content function grabs the “data-val-required” attribute from the input tag to display as the tooltip mesage, which contains the validation message that you set in your model.

Validation with jQuery UI Tooltip

Validation with jQuery UI Tooltip

Here’s our new and improved (and much more compact) log in form!  You can see that we have the red borders to tell us which fields need updating, but the tooltips will hide unless the user focuses on the field.  In this case, the password validation message will show when the user switches to that input, and the User Name validation will hide.

The possibilities for styling and positioning the tooltip with jQuery UI are endless.  For example, you could add a bright red alert box and you could position it anywhere in reference to the field; above, below, or to the side.

It’s really that easy.  Please feel free to leave a comment if you have any questions.

Avoid HTML Escaping in an ASP.NET MVC WebGrid Column Format

I ran into an issue with the new ASP.NET MVC WebGrid.  I had difficulty finding any information out there on a good way to do this, so I thought I would post my solution.  The WebGrid easily generates paged and sorted tables automatically. You can find more information on the ASP.NET MVC WebGrid here.  In my case, I am listing some data for the user and I want to show any new rows in bold to make it more noticeable. Adding any HTML tags to the format property as a string will result in the tags being escaped. See the following example:

@grid.GetHtml(
        columns: grid.Columns(
            grid.Column("Text", format: (item) => item.New ? item.Text : "<strong>" + item.Text + "</strong>")
        )
    )

Notice that item.New is a Boolean value.  This results in the following encoded HTML output within the table cell:

<strong>Sample Item Text</strong>

Not exactly the intended effect.  However, if you pass in a new object of type MvcHtmlString with the string in its constructor:

@grid.GetHtml(
        columns: grid.Columns(
            grid.Column("Text", format: (item) => item.New ? item.Text : new MvcHtmlString("<strong>" + item.Text + "</strong>"))
        )
    )

Voila!  This will result in the properly bolded text:

Sample Item Text

This method will work for any of the other Html Helpers as well, though my example specifically references WebGrid.  In other cases, the Html.Raw method can be used to print HTML, but inside of the grid column it will still be escaped.  I’ve tested multiple ways of adding the grid column format using “@:”, but none of the documented methods seem to work within a ternary operator.