Thursday 30 May 2013

Asp.net Mvc Image Helpers (Part 2)

Image helper with server side image re-size

In this second part we will continue on from part 1 and add a second option to our image controller that enables us to have the server re-size the image before sending it to the client.

First you need to install Image Resizer http://imageresizing.net/ through nuget, (Tools->Manage Nuget Packages), by searching "imageresizer". We will be using this package to re size the images.

Once the image resizer is installed in your mvc project we can add a new method to the Image Controller.

 public ActionResult ImageResize(string image, int width, int height)  
 {  
   var imagesPath = Server.MapPath("/Images");  
   var imageLocation = Path.Combine(imagesPath, image);  
   
   var settings = new ResizeSettings  
   {  
     Format = "jpg",  
     Mode = FitMode.Stretch,  
     Width = width,  
     Height = height,  
     Scale = ScaleMode.Both  
   };  
   
   var outStream = new MemoryStream();  
   ImageBuilder.Current.Build(System.IO.File.ReadAllBytes(imageLocation), outStream, settings);  
   var resizedImage = outStream.ToArray();  
   
   return File(resizedImage, "image/jpeg");  
 }  

In this we map the path as before and then re-size the image and pass it in to a memory stream so we can return the image to the client. There are plenty of options for image resizer see this page for more.

Next we need to add an overload to our html helper extension that allows us to specify image dimensions.

 public static MvcHtmlString Image(this HtmlHelper helper, string image, string alternate, int width, int height)  
 {  
   var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);  
   var url = urlHelper.Action("ImageResize", "Image", new {image, width, height});  
   
   var builder = new TagBuilder("img");

   builder.MergeAttribute("src", url);
   builder.MergeAttribute("alt", alternate);

   return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing)); 
 }  

As before this uses a URL helper to generate the URL then generates a img tag using a Tag Builder before returning it as a MvcHtmlString.

To use this in razor just type:
 @Html.Image("test.jpg", "Example Image", 50, 50)  


In the next part of the series we will look at setting up an image helper that uses jQuery lazy load to load the images.

Links
Source Code

Part 1

Wednesday 29 May 2013

Asp.net Mvc Image Helpers (Part 1)

In this series I will look at adding a few image helpers to the mvc html helper to simplify adding images to a view.


Simple Image Helper & Image Controller

The first helper is just a simple helper that displays an image tag with the source value set to point at a image controller that returns an image. To do this first create a new controller called "ImageController" this will be used to hold all our image related actions.

Add the method:
 public ActionResult Image(string image)  
 {  
   var imagesPath = Server.MapPath("/Images");  
   var imageLocation = Path.Combine(imagesPath, image);  
   
   return File(imageLocation, "image/jpeg");  
 }  

This will find an image that is inside the "/Images" folder and return it as a "image/jpeg".At this point you should be able to draw an image from this controller by adding the following code to a view:

 <img src="@Url.Action("Image", "Image", new {image = "test.jpg"})" alt="Test Image"/>  
and as long as you have an image called test.jpg in your images folder it should get rendered. 
If you need a test image feel free to use this amazing test image!
While this works just fine its a fair amount to write every time you want to draw an image, so to solve this we can create a html helper that just takes the image name and alternate text. something like "@Html.Image("test.jpg", "Alternate text")"

To do this we need to extend the Html helper to include a method for image, so that we can easily create images and not need to worry about calling @Url.Action() each time we want to render an image.

Create a new static class called "HtmlHelperExtensions"


 public static class HtmlHelperExtensions  
 {  
   public static MvcHtmlString Image(this HtmlHelper helper, string image, string alternative)  
   {  
     var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);  
     var url = urlHelper.Action("Image", "Image", new {image});  
   
     var builder = new TagBuilder("img");

     builder.MergeAttribute("src", url);
     builder.MergeAttribute("alt", alternative);

     return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing)); 
   }  
 }  

In this class first we create a static method and have the first parameter as "this HtmlHelper helper" to specify that it is an extension to the HtmlHelper class.

next we use a URL Helper to generate the URL for the image controller action without having to specify it. We then format this in to the <img> tag and return it as an MvcHtmlString so it is properly formatted.

At this point you need to either add an @using statement and specify the namespace where HtmlHelperExtensions is or add it to the web.config inside your views folder so that razor knows where to find it without specifying it in every view you want to use it in. To do this open the razor web.config (the one in the views folder).

In the web.config you should see a <namespaces> element with some <add namespace... elements inside it inside of a <system.web.webPages.razor> element. In here we need to add the namespace that the htmlhelperextensions class is inside. For me that is "SimpleImageHelper.HtmlHelpers" so i need to add:
 <add namespace="SimpleImageHelper.HtmlHelpers"/>  


This should enable you to type
 @Html.Image("test.jpg", "Example Image")  

in a view and an image will be created, if the image does not display it can be helpful to view the source of the page to try and get a clue as to where the process is going wrong.

In the next part we will look at creating an image helper that will re size the image on the server before sending it to the client.


Links:


Source Code