Click here to Skip to main content
15,884,388 members
Articles / Programming Languages / C#
Tip/Trick

Html.RatingFor: Extending the MVC HtmlHelper

Rate me:
Please Sign up or sign in to vote.
4.80/5 (8 votes)
16 Dec 2013CPOL1 min read 18K   4   2
Html.RatingFor: Extending the MVC HtmlHelper

Introduction

When working on a web application, I was in need to add a rating for a product. That rating will be between 1 and 5 and will always be an int. So my model has a property like public int Rating {get;set;}. I decided to add 5 radio buttons, and each will hold the corresponding rating value.

But then (as always happens), the requirement changed. We didn't want to have only 1 rating property, but 5. So adding 5 radios for each was something that I didn't want to happen.

In order to solve this problem, I created an extension method for the HtmlHelper class that we normally use in our MVC applications. As you may notice, in the method I created all the logic for adding the set of radio buttons needed for the rating process.

C#
public static MvcHtmlString RatingFor<tmodel,>(
    this HtmlHelper<tmodel> htmlHelper, Expression<func<tmodel,>>
    expression, int from, int to, object htmlAttributes = null)
{
    var builder = new StringBuilder();

    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

    var model = metadata.Model;
            var name = ExpressionHelper.GetExpressionText(expression);

    var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

    var fullName = 
    htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

    int direction = 1;
    if (from > to)
        direction = -1;

    for (var i = from; direction == 1 ? i <= to : i >= to; i += direction)
    {
        var tagBuilder = new TagBuilder("input");
        tagBuilder.MergeAttributes(attributes);
        tagBuilder.MergeAttribute("type", "radio");
        tagBuilder.MergeAttribute("name", fullName, true);
        tagBuilder.MergeAttribute("value", 
        i.ToString(CultureInfo.InvariantCulture));
        //If model has a value we need to select it
        if (model != null && model.Equals(i))
        {
            tagBuilder.MergeAttribute("checked", "checked");
        }
        tagBuilder.GenerateId(fullName);

        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }
        tagBuilder.MergeAttributes(htmlHelper.
        GetUnobtrusiveValidationAttributes(name, metadata));

        builder.AppendLine(tagBuilder.ToString(TagRenderMode.SelfClosing));
    }

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

One important part of this code is:

C#
if (model != null && model.Equals(i))
{
 tagBuilder.MergeAttribute("checked", "checked");
}

where we assign the value of the property if it is already set. This is useful when you use this method on an Edit process.

Now on your view, instead of having to create all that radio buttons manually, you can have something like this:

C#
@Html.RatingFor(model => model.Rating, 1, 5)

in order to add a rating from 1 to 5.

Hopefully, you will find this useful. If you have created another useful helper, it would be nice if you share it with the community. :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer e-nnovare
Mexico Mexico
Jorge is an enthusiast web developer who love to learn something new every day.

Comments and Discussions

 
QuestionThe Code Pin
Oscar R. Onorato14-Nov-14 15:08
Oscar R. Onorato14-Nov-14 15:08 
GeneralNot an article Pin
StianSandberg15-Dec-13 3:27
StianSandberg15-Dec-13 3:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.