Tired of looking for errors in log files? Use OneTrueError - Automated exception management in .NET.

First draft of my alternative HTML helpers

I’m getting closer to a first release of my ASP.NET MVC contribution project called Griffin.MvcContrib. I’ve just committed my first draft of the alternative HTML helpers. I’ve focused on helpers for Form tags in this commit. If you are wondering what’s wrong with the original helpers, please see my previous blog entry about using extension as an important part of a framework.

Here are some new features that my HTML providers add:

Extensible

By using extension methods there is no way to extend the functionality in them. I’ve solved this in two ways. First and foremost there aren’t any extension methods. My HtmlHelper class is just a facade that tries to use the DependencyResolver to find the proper generators. It will also create the default implementations if no extended ones are found.

To extend one of the helpers, simply derive it and make the changes you like. The following sample with add a “title” attribute to all text areas (which then can be picked up by a jquery script to create a nice tool tip)

    public class MyCustomTextAreaGenerator : TextAreaGenerator
    {
        public MyCustomTextAreaGenerator(ViewContext viewContext) : base(viewContext)
        {
        }

        protected override IEnumerable<NestedTagBuilder> GenerateTags()
        {
            var generatedTags = base.GenerateTags().ToArray();
            generatedTags[0].MergeAttribute("title", "You are so dirty!");
            return generatedTags;
        }
    }

and then register it in your current inversion of control container. Here is a sample for autofac:

containerBuilder
    .RegisterType<MyCustomTextAreaGenerator>()
    .AsImplementedInterfaces();

The following generators do currently exist:

  • CheckBoxGenerator
  • RadioButtonGenerator
  • SelectGenerator
  • TextAreaGenerator
  • TextBoxGenerator

Post processing generated HTML tags

You can also add more generic adapters which can be used to transform the generated HTML tags. The sample project which is included in github shows you how to:

  • create watermarks for textboxes
  • Add tooltips
  • Transform all age fields into UI sliders

Here is the watermark example:

    public class WatermarkAdapter : IFormItemAdapter
    {
        public void Process(FormItemAdapterContext context)
        {
            // there is a "Watermark" metadata but it cannot currently be set.
            // unless you are using a custom metadata provider like the one in the localization demo.
            if (string.IsNullOrEmpty(context.Metadata.Description) || !context.TagBuilder.Attributes.ContainsKey("class") || !context.TagBuilder.Attributes["class"].Contains("watermark"))
                return;

            context.TagBuilder.MergeAttribute("title", "Watermark:" + context.Metadata.Description);
        }
    }

And the jquery script creating the actual watermark (uses the jquery watermark plugin):

function watermark() {
    $('[title*="Watermark:"]').each(function () {
        $(this).watermark($(this).attr('title').substr(10));
        $(this).removeAttr('title');
    });
}

Enum galore

Are you using enums? Sure you do. The html helpers in Griffin.MvcContrib can generate lists, checkboxes and radio buttons automatically for them.

The following code:

@Html2.CheckBoxesFor(model => model.InputType) <br />
@Html2.RadioButtonsFor(model => model.InputType) <br />
@Html2.DropdownFor(model => model.InputType) <br />

Generates the following HTML:

HTML generated by enum html helpers

Lets format that dropdown

Dropdowns are something else that I’ve tried to improve. You can use formatters to determine how the select lists should be generated.

The following example are using a custom formatter which has been made to transform user objects:

@Html2.DropdownFor(model => model.CurrentUser, Select.From<UserFormatter>(Model.Users))

And the actual formatter:

    public class UserFormatter : ISelectItemFormatter
    {
        public SelectListItem Generate(object itm)
        {
            var item = (User)itm;
            return new SelectListItem
            {
                Text = string.Format("{0} {1}", item.FirstName, item.LastName),
                Value = item.Id.ToString()
            };
        }
    }

There are to formatters built into MvcContrib:

  • IdTitle
  • IdName

They uses reflection to find the proper properties.

Summary

All mentioned helpers should work without any problems. But I’m not done with the helpers yet. This post is most about me wanting feedback. Have I made any stupid mistakes? Do you have any suggestions how I can improve the code?

Please take a look at the sample project

The actual source code for all helpers can be found here

This entry was posted in Uncategorized and tagged , . Bookmark the permalink.
  • http://arturdr.ru Shaddix

    Will it be somehow integrated with Html.EditorFor/DisplayFor stuff?

    So I could just say that some ViewModel’s field should be rendered with .CheckboxesFor and then simply generate an editor for the whole model with @Html.EditorForModel();

  • Timothy Sturm

    Sample project link is dead