Wednesday, May 20, 2009 9:21 AM
kazimanzurrashid
ASP.NET MVC – Poll Result, jQuery UI MVC Component Demo and More Feedback Required
Few days back I ran a Poll to gather the feedback on ASP.NET MVC View Components that I am planning to build building. Though it is certainly not possible to get everyone’s vote of the ASP.NET MVC Community, but I think the result has enough votes to represents the whole community:
Which View Engine do you use in ASP.NET MVC (Total votes 276)?
- Webform (185 votes, 67%)
- Spark (60 votes, 22%)
- NHaml (16 votes, 6%)
- NVelocity (6 votes, 2%)
- Brail (4 votes 1%)
- Others (5 Votes, 2%)
What kind of UI Components do you prefer for Webform view engine? (Total votes 186)?
- UI components as HtmlHelper methods (108 votes, 58%)
- UI components as lightweight controls similar to mvc future assembly (38 votes, 20%)
- Any of the above (40 votes, 22%)
Which Javascript framework your ASP.NET MVC UI component should depend? (Total votes 214)?
- jQuery (185 votes, 86%)
- ExtJS (11 votes, 5%)
- MS ASP.NET AJAX (3 votes, 1%)
- Can depend any of the above (8 votes, 4%)
- Do not bother if it has multiple dependency (7 votes, 3%)
As you can see the Webform+HtmlHelper+jQuery is far ahead from its competitor. Now, let us asses the options that we have to create UI components that extends the HtmlHelper. In this post I will use the jQuery UI Slider for discussing the options. If you are not familiar with jQuery UI Slider, I would suggest to visit the previous link, the slider has properties like value, min, max, step, range and events start, stop change, slide etc. Lets assume that the method we will have in the HtmlHelper will create the necessary html elements and emits required javascripts in the page.
Option#1 Create Regular Methods
We can create regular methods like the ASP.NET MVC Framework, for example:
public static class HtmlHelperExtension
{
public static void Slider(this HtmlHelper htmlHelper, string id, int value, int min, int max, object htmlAttributes)
{
// Implementation
}
}
And few more overloads, the number of parameter will vary based upon the complexity of the object that we are building:
//Range
public static void Slider(this HtmlHelper htmlHelper, string id, int value1, int value2, int min, int max, object htmlAttributes)
{
// Implementation
}
public static void Slider(this HtmlHelper htmlHelper, string id, int value)
{
// Implementation
}
So, in the view we will be able to use it like the following:
<% Html.Slider("mySlider", 10, 20, 0, 100, new { style = "border: #000 1px solid" }); %>
<% Html.Slider("mySlider", 10, 0, 100, null); %>
<% Html.Slider("mySlider", 10, 20, 0, 100, null); %>
<% Html.Slider("mySlider", 10); %>
Option#2 Create Simple Fluent Syntax
We can create a slider object similar to the following:
public class jQuerySlider
{
private readonly HtmlHelper _htmlHelper;
private string _id;
private RouteValueDictionary _htmlAttributes;
private int _value;
private int[] _values;
private int _minimum;
private int _maximum;
public jQuerySlider(HtmlHelper htmlHelper)
{
_htmlHelper = htmlHelper;
}
public jQuerySlider Id(string elementId)
{
_id = elementId;
return this;
}
public jQuerySlider HtmlAttributes(object attributes)
{
_htmlAttributes = new RouteValueDictionary(attributes);
return this;
}
public jQuerySlider Value(int sliderValue)
{
_value = sliderValue;
return this;
}
// Range
public jQuerySlider Values(int slider1Value, int slider2Value)
{
_values = new int[2];
_values[0] = slider1Value;
_values[2] = slider1Value;
return this;
}
public jQuerySlider Minimum(int value)
{
_minimum = value;
return this;
}
public jQuerySlider Maximum(int value)
{
_maximum = value;
return this;
}
public void Render()
{
//Write html and register script
}
}
And create an extension method of HtmlHelper:
public static jQuerySlider Slider(this HtmlHelper helper)
{
return new jQuerySlider(helper);
}
Now, we will be able to use it in the view like:
<% Html.Slider()
.Id("mySlider")
.HtmlAttributes(new { style = "border:#000 1px solid" })
.Values(10, 20)
.Minimum(0)
.Maximum(100)
.Render(); %>
<% Html.Slider()
.Id("mySlider")
.Value(10)
.Minimum(0)
.Maximum(100)
.Render(); %>
<% Html.Slider()
.Id("mySlider")
.Value(10)
.Render(); %>
A bit verbose, but lot more readable comparing to the regular methods (option #1), but the problem with this approach is, it is really easy to write:
<% Html.Slider()
.Id("mySlider")
.Value(10)
.Value(20)
.Value(30)
.Render(); %>
And VS will always show the method names no matter how many times it is called:

This makes the syntax a bit confusing and ambiguous.
Option#3 Create Progressive Fluent Syntax
This solves the exact problem that I have just mentioned. Rather than returning the same object in the methods, it returns different interface that is applicable in that context. For example:
As you can see, once a method is called it does not appears in the auto complete list, also the next available methods in that context are shown. I have implemented the jQuery UI Accordion, Tab, ProgressBar, Slider and Theme Switcher (DatePicker and Dialog are under development) following this approach. You can find the fully functional version:
[Live version]
[Download Demo]
This option also has a drawback, it does not support method overlapping like the option #2, which means, we always have to call the methods in the exact same order and it becomes a bit painful when we want to change a specific value that is a few level deep. For example, if we want to change only the Steps of the Slider we have to use:
<% Html.jQuery().Slider()
.Id("mySlider")
.NoExtraHtmlAttributes()
.DoNotAnimate()
.UseDefaultOrientation()
.NoRange()
.Value(0)
.UseDefaultMinimum()
.UseDefaultMaximum()
.Steps(5)
.Render(); %>
Instead of:
<% Html.jQuery().Slider()
.Id("mySlider")
.Steps(5)
.Render(); %>
Though I prefer it over the above two, but it completely depends upon you, which way you want to shape up the API. So dear readers, please download the demo, do play with it and leave your opinion in this poll.
Filed under: Asp.net, ASPNETMVC, ASP.NET MVC, jQuery UI, jQuery