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
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.

Why have you used
public static string UnorderedList(this HtmlHelper helper, object items)
rather than
public static string UnorderedList(this HtmlHelper helper, IEnumerable items) ?
Surely your method catches the wrong type in the test/at run time, whereas using generics, we can stop anything that doesn’t implement IEnumerable being passed into the method.
@David – Good point, I should have used generics here instead of making an assumption about the type and casting.
Hi, have you had any luck using ToAttributeList() in your extension methods in vb.net? I always get an error saying ToAttributeList is not a member of VB$AnonymousType_0(Of String) and i have no idea why…
Cheers!
Great! Very helpful!
Thank you, thank you, thank you, a helpful article with VB code!
very helpful steve, thanks. I have been watching/reading your tutorials to learn MVC and you do a good job at laying out the basics of the MVC framework.
Did you realize that the SubmitButton HTMLHelper have been removed?
To quote Phil Haack:
“Yeah, we are trying to keep the helpers somewhat minimalist. Not only that, we’ve received feedback from some people that many of our helpers are unnecessary. “I know HTML, why do I need a SubmitButton helper?”.
We figured that since input buttons generally are not used to render user input, the helper method has marginal value. After all, with the VS HTML editor, you get intellisense when you type
. It tells you which attributes are available. Our helper doesn’t.
On the other hand, I’ve seen several threads where people were upset that this was gone. Is this a real problem?
The thing we want to avoid is having a helper for every html element. That would make no sense: Html.Div.
We want to come up with a design rationale for helpers. Maybe we have one for all the common form elements, not just the ones that show user input. That’s a possibility in which case we would include SubmitButton.”
Please keep your post up to date Stephen. Your kind of postings is what newcomers to this awesome way of doing things are looking at and so far you have cause quite a few confusions to me, and don’t know how many others.
For one, most of the ASP.NET data bound controls have a rich site of event post backs to hook up. MVC says: no dice! You can’t rely on the event dispatch loop of asp.net. In fact, this is the whole point of going MVC – to create a simple, well separated delineation between the presentation and the BL. If you have all these states and post back logic pieces all in the code behind you really have a tightly coupled application.good Article
Nice Post! Very useful code is given. This code will help me a lot. Thanks.
ew I tried to mock a call to a Linq to SQL query, but I am struggling.
watching and putting into action the moves Joe is showing here. I now am driving straight and long and now working on my irons, hybrid and fairway woods. I was almost going to give up on this sport
Legal accreditation | College Accreditation & Bachelors Degree Accreditation
Well, all I have to say is thanks Joe. I am in your debt. Thanks Masters Degree Accreditation | Diploma program accrediation
Online Criminal Justice accreditation
I must say, good HTML helper.
Very useful code is given. This code will help me a lot. Thanks.
vge It looks like DataContextExtensions.cs line 45 of the Save method should pass the primaryKeyName through to Update.
selam hi This sounds fascinating sıcak sohbet I’m going to read that tracing articlekısa aşk şiirleri when I have a moment.
Wow. erotik film izle is
şifalı bitkiler zayıflama de
çet sohbet fer
netlog ger
müzik dinle err
şarkı dinle
cüneyt arkın filmleri kk
isyan sözleri fer
hikayeler er
islami çet ff
adet sancısına ne iyi gelir hh
escort bayanlar der
bedava chat dd
chat odaları der
liseli kızlar derf
kızlarla sohbet fder
kızlarla chat
sohbet errASDF
As the users of HD Camcorders like Sony, Canon, Panasonic, this HD Converter is necessary to help us convert hd Video easily and quickly. The Converter for HD provides several practical editing functions to help you achieve ideal output effect. Trim function is to cut videos into clips which you can just convert and transfer to your player. Crop function helps you remove black bars around the movie. You could use Effect function to adjust video brightness, contrast, saturation and more parameters. More powerful and considerate functions are waiting for you to explore.
TS Converter l TOD Converter l TRP Converter l H.264 Converter