Tuesday, June 18, 2013

Create HtmlHelper Ordered and UnOrderedList

ASP.NET MVC  – Create New HTML Helpers with Extension Methods Order and UnOrdered List

In this tip, I show you how you can create two new HTML Helpers that you can use within an ASP.NET MVC View. I show you how you can use extension methods to create new HTML Helpers for displaying bulleted and numbered lists.
When building a View for an ASP.NET MVC application, you can take advantage of HTML Helpers to render standard HTML tags. For example, instead of typing this:
<input name="inpSubmit" type="submit" value="Click Here!" />
You can type this:
<%= Html.SubmitButton("inpSubmit", "Click Here!") %>
Over the long run, HTML Helpers can save you a lot time. But what if there isn’t an HTML Helper for a tag that you want to render? For example, imagine that you want to display a bulleted list of database records in a View. The HtmlHelper class doesn’t include a method that lets you render a bulleted list. Don’t give up. If the HTML Helper doesn’t include a method that you need, just extend it!
You can add new functionality to the HtmlHelper class by creating new extension methods. An extension method looks just like a normal instance method. However, unlike a normal instance method, you add extension methods to a class by defining the methods in a completely different class.
In Visual Basic .NET, you create extension methods by creating a module and decorating the extension methods with a special attribute. In C#, you define extension methods in a static class and use the keyword this to indicate the class being extended.
Here’s how you can add extension methods to the HtmlHelper class to display both ordered and unordered list of database records:
Listing 1 – ListExtensions.vb (VB.NET)
 1: Imports System
 2: Imports System.Collections
 3: Imports System.Text
 4: Imports System.Web
 5: Imports System.Web.Mvc
 6: Imports System.Runtime.CompilerServices
 7:
 8:
 9: Namespace HtmlHelpers
 10:
 11:     Public Module ListExtensions
 12:
 13:         <Extension()> _
 14:         Public Function OrderedList(ByVal HtmlHelper As HtmlHelper, ByVal items As Object) As String
 15:             Return "<ol>" + ListExtensions.GetListItems(items) + "</ol>"
 16:         End Function
 17:
 18:         <Extension()> _
 19:         Public Function UnorderedList(ByVal HtmlHelper As HtmlHelper, ByVal items As Object) As String
 20:             Return "<ul>" + ListExtensions.GetListItems(items) + "</ul>"
 21:         End Function
 22:
 23:
 24:         Private Function GetListItems(ByVal items As Object) As String
 25:             If items Is Nothing Then
 26:                 Throw New ArgumentNullException("items")
 27:             End If
 28:             If Not TypeOf items Is IEnumerable Then
 29:                 Throw New InvalidCastException("items must be IEnumerable")
 30:             End If
 31:
 32:             Dim EnumItems As IEnumerable = CType(items, IEnumerable)
 33:             Dim builder As New StringBuilder()
 34:             For Each item As Object In EnumItems
 35:                 builder.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(item.ToString()))
 36:             Next
 37:             Return builder.ToString()
 38:         End Function
 39:
 40:     End Module
 41: End Namespace
Listing 1 – ListExtensions.cs (C#)
 1: using System;
 2: using System.Collections;
 3: using System.Text;
 4: using System.Web;
 5: using System.Web.Mvc;
 6:
 7: namespace BulletedListHelper.HtmlHelpers
 8: {
 9:     public static class ListExtensions
 10:     {
 11:         public static string OrderedList(this HtmlHelper helper, Object items)
 12:         {
 13:             return "<ol>" + ListExtensions.GetListItems(items) + "</ol>";
 14:         }
 15:
 16:         public static string UnorderedList(this HtmlHelper helper, Object items)
 17:         {
 18:             return "<ul>" + ListExtensions.GetListItems(items) + "</ul>";
 19:         }
 20:
 21:
 22:         private static string GetListItems(Object items)
 23:         {
 24:             if (items == null)
 25:                 throw new ArgumentNullException("items");
 26:             if (items is IEnumerable == false)
 27:                 throw new InvalidCastException("items must be IEnumerable");
 28:
 29:             var enumItems = (IEnumerable)items;
 30:             var builder = new StringBuilder();
 31:             foreach (Object item in enumItems)
 32:                 builder.AppendFormat("<li>{0}</li>", HttpUtility.HtmlEncode(item.ToString()));
 33:             return builder.ToString();
 34:         }
 35:
 36:     }
 37: }
The ListExtensions class has two public methods: OrderedList() and UnorderedList(). You pass a collection of items to either method to display either a numbered or bulleted list of items. Notice that these methods return strings. Really, an HTML Helper method is nothing more than a method that renders a formatted string to the browser.
After you create the extension methods, you can use the methods in a View like this:
Listing 2 – Index.aspx
 1: <%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="BulletedListHelper.Index" %>
 2: <%@ Import Namespace="BulletedListHelper.HtmlHelpers" %>
 3:
 4: <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
 5:
 6:
 7:    <h1>Movies (Ordered)</h1>
 8:
 9:    <%= Html.OrderedList(ViewData.Model) %>
 10:
 11:
 12:    <h1>Movies (Unordered)</h1>
 13:
 14:
 15:    <%= Html.UnorderedList(ViewData.Model) %>
 16:
 17:
 18: </asp:Content>
Notice that the BulletedList.HtmlHelpers namespace gets imported at the top of the file. The method Html.OrderedList() is used to render a numbered list and the method Html.UnorderedList() is used to render a bulleted list. Notice that these methods are being called on the HtmlHelper exposed by the Html property of the View just like any other extension method. When you open this View in a browser, you get the page in Figure 1:
Figure 1 – Index.aspx Rendered with Custom HTML Helpers
image
Finally, the Index() method exposed by the HomeController in Listing 3 illustrates how you can pass a collection of movie records to the Index.aspx View. The movie records are retrieved by taking advantage of a Linq to SQL query.
Listing 3 – HomeController.vb (VB.NET)
 1: Public Class HomeController
 2:     Inherits System.Web.Mvc.Controller
 3:
 4:     Private db As New MoviesDataContext()
 5:
 6:     Function Index()
 7:         Dim movies = From m In db.Movies Select m.Title
 8:         Return View(movies)
 9:     End Function
 10:
 11:
 12: End Class
Listing 3 – HomeController.cs (C#)
 1: using System;
 2: using System.Collections.Generic;
 3: using System.Linq;
 4: using System.Web;
 5: using System.Web.Mvc;
 6: using BulletedListHelper.Models;
 7:
 8: namespace BulletedListHelper.Controllers
 9: {
 10:     public class HomeController : Controller
 11:     {
 12:
 13:         private MoviesDataContext db = new MoviesDataContext();
 14:
 15:         public ActionResult Index()
 16:         {
 17:             var movies = from m in db.Movies select m.Title;
 18:             return View(movies);
 19:         }
 20:
 21:     }
 22: }
You can use this approach to render just about anything within an ASP.NET MVC View. For example, you can use a similar approach to create TreeViews, Menus, tabstrips, whatever.

No comments:

Post a Comment