Thursday, November 18, 2010

Creating Custom HTML Helpers Using the TagBuilder Class

Using the TagBuilder Class
The TagBuilder class is a utility class included in the ASP.NET MVC framework that you can use when building HTML helpers.

Here’s a list of the methods of the TagBuilder class:
  • AddCssClass()—Enables you to add a new class=”” attribute to a tag.
  • GenerateId()—Enables you to add an id attribute to a tag. This method automatically replaces periods in the id. (By default, periods are replaced by underscores.)
  • MergeAttribute()—Enables you to add attributes to a tag. There are multiple overloads of this method.
  • SetInnerText()—Enables you to set the inner text of the tag. The inner text is HTML-encoded automatically.
  • ToString()—Enables you to render the tag. You can specify whether you want to create a normal tag, a start tag, an end tag, or a self-closing tag.
The TagBuilder class has four important properties:
  • Attributes—Represents all the attributes of the tag.
  • IdAttributeDotReplacement—Represents the character used by the GenerateId() method to replace periods. (The default is an underscore.)
  • InnerHTML—Represents the inner contents of the tag. Assigning a string to this property does not HTML-encode the string.
  • TagName—Represents the name of the tag.
You don’t actually need to use the TagBuilder class. You could use a StringBuilder class instead. However, the TagBuilder class makes your life a little easier.

The helper in Listing below, the Html.ImageLink() helper, is created with a TagBuilder. The Html.ImageLink() helper renders an image link.

using System.Web.Mvc;
using System.Web.Routing;
namespace Helpers
{
    public static class ImageLinkHelper
    {
        public static string ImageLink(this HtmlHelper helper, string actionName,
        string imageUrl, string alternateText)
        {
            return ImageLink(helper, actionName, imageUrl, alternateText, null,
            null, null);
        }

        public static string ImageLink(this HtmlHelper helper, string actionName,
        string imageUrl, string alternateText, object routeValues)
        {
            return ImageLink(helper, actionName, imageUrl, alternateText,
            routeValues, null, null);
        }

        public static string ImageLink(this HtmlHelper helper, string actionName,
        string imageUrl, string alternateText, object routeValues, object
        linkHtmlAttributes, object imageHtmlAttributes)
        {
            var urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
            var url = urlHelper.Action(actionName, routeValues);
            // Create link
            var linkTagBuilder = new TagBuilder("a");
            linkTagBuilder.MergeAttribute("href", url);
            linkTagBuilder.MergeAttributes(new RouteValueDictionary
            (linkHtmlAttributes));
            // Create image
            var imageTagBuilder = new TagBuilder("img");

            imageTagBuilder.MergeAttribute("src", urlHelper.Content(imageUrl));
            imageTagBuilder.MergeAttribute("alt", urlHelper.Encode(alternateText));
            imageTagBuilder.MergeAttributes(new RouteValueDictionary
            (imageHtmlAttributes));
            // Add image to link
            linkTagBuilder.InnerHtml = imageTagBuilder.ToString
            (TagRenderMode.SelfClosing);
            return linkTagBuilder.ToString();
        }
    }
}

The Html.ImageLink() helper in Listing above has three overloads. The helper accepts the following parameters:

  • actionName—The controller action to invoke
  • imageUrl—The URL of the image to display
  • alternateText—The alt text to display for the image
  • routeValues—The set of route values to pass to the controller action
  • linkHtmlAttributes—The set of HTML attributes to apply to the link
  • imageHtmlAttribute—The set of HTML attributes to apply to the image
For example, you can render a delete link by calling the Html.ImageLink() helper like this:

<%= Html.ImageLink("Delete", "~/Content/Delete.png", "Delete Account", new {AccountId=2}, null, new {border=0}) %>

Don’t forget to import namespace
<%@ Import Namespace="Helpers" %>

Two instances of the TagBuilder class are used in Listing. The first TagBuilder builds up the <a> link tag. The second TagBuilder builds up the <img> image tag.

Notice that an instance of the UrlHelper class is created. Two methods of this class are called. First, the UrlHelper.Action() method generates the link to the controller action.
Second, the UrlHelper.Content() method converts an application relative path into a full relative path. For example, if your application is named MyApplication, the UrlHelper.Content() method would convert the application relative path ”~/Content/Delete.png” into the relative path ”/MyApplication/Content/Delete.png”.

Wednesday, November 17, 2010

Creating Custom HTML Helpers MVC

Before, moving forward recall the concept of Extension Method. Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the “this” modifier. Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive.

For more information about Extension Methods visit my article  http://akshatsharma80.blogspot.com/2010/11/extension-methods.html

Now, let’s come to the point “Custom HTML Helpers”, The ASP.NET MVC framework ships with a limited number of HTML helpers. Fortunately, creating new HTML helpers is an easy process. You create a new HTML helper by creating an extension method on the HtmlHelper class. For example,

using System;
using System.Web.Mvc;
namespace Helpers
{
    public static class SubmitButtonHelper
    {
        /// <summary>
        /// Renders an HTML form submit button
        /// </summary>
        public static string SubmitButton(this HtmlHelper helper, string buttonText)
        {
            return String.Format("<input type=\"submit\" value=\"{0}\" />",
            buttonText);
        }
    }
}

Contains a new Html.SubmitButton() helper that renders an HTML form submit button. Above listing contains an extension method named SubmitButton(). The SubmitButton() helper simply returns a string that represents an HTML <input type=”submit” /> tag. Because the SubmitButton() method extends the HtmlHelper class, this method appears as a method of the HtmlHelper class in Intellisense.


The view in Listing below uses the new Html.SubmitButton() helper to render the submit button for a form. Make sure that you import the namespace associated with your helper,

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Customer>" %>
<%@ Import Namespace="Helpers" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <% using (Html.BeginForm()) {%>
    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="FirstName">
                FirstName:</label>
            <%= Html.TextBox("FirstName") %>
        </p>
        <p>
            <label for="LastName">
                LastName:</label>
            <%= Html.TextBox("LastName") %>
        </p>
        <p>
            <%= Html.SubmitButton("Create Customer") %>
        </p>
    </fieldset>
    <% } %>
</asp:Content>

Extension methods

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. For client code written in C# and Visual Basic, there is no apparent difference between calling an extension method and the methods that are actually defined in a type.
Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the “this” modifier. Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive.
The following example shows an extension method defined for the System.String class. Note that it is defined inside a non-nested, non-generic static class:

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }  
}

The WordCount extension method can be brought into scope with this using directive:

using ExtensionMethods;

And it can be called from an application by using this syntax:

string s = "Hello Extension Methods";
int i = s.WordCount();

Points to remember
When using an extension method to extend a type whose source code you cannot change, you run the risk that a change in the implementation of the type will cause your extension method to break.
If you do implement extension methods for a given type, remember the following two points:
·      An extension method will never be called if it has the same signature as a method defined in the type.
·      Extension methods are brought into scope at the namespace level. For example, if you have multiple static classes that contain extension methods in a single namespace named Extensions, they will all be brought into scope by the using Extensions; directive.

Monday, November 15, 2010

Split Comma Separated Values in Columns

Declare @Temp Table(ColumnA VarChar(40), ColumnB VarChar(400))

insert into @Temp Values('AA.ProjectBuildTower','2222, 3333, 4444, 5555')
insert into @Temp Values('BB.ProjectBuildFence','X900, 6789, 9000, 9876')

Declare @Output Table(Header VarChar(40), Data VarChar(20))

While Exists(Select * From @Temp Where CharIndex(',', ColumnB) > 0)   
      Begin       
            insert into @output(Header, Data)       
            Select ColumnA, Left(ColumnB, CharIndex(',', ColumnB)-1)       
            From   @Temp       
            Where  CharIndex(',', ColumnB) > 0       
           
            Update @Temp       
            Set    ColumnB = LTrim(Right(ColumnB, Len(ColumnB)-CharIndex(',', ColumnB)))   
      End

Insert Into @Output(Header, Data)
Select ColumnA, ColumnB From   @Temp
Select * From @Output Order By Header, Data

Select ColumnA, ColumnB From   @Temp