In my previous blog I provided an overview of the MVC
Extensions (HTML Helpers) and creating a custom extension. If you haven’t look
at my previous blog, I recommend going through that blog.
· self-referential, where the new context is equivalent to the last context
· terminated through the return of a void context.
.OrderBy (t => t.Value.Length)
.Select (t => t.Value.ToUpper());
As you see all the methods (Where, OrderBy, Select) are
chained together thus providing a seamless interface to the developers. There
is no limitation on the number of methods you can chain.
We can incorporate this fluent interface in our custom Label HTML Extension. With the fluent interface our call to the label will be transformed as follows:
.Text("First Name")
)
With the fluent interface the properties will be transposed
to the methods and these methods will be chained together.
this.target = target;
return this;
}
As you see in the above code, at the end the method returns
the current object, which is Label object.
public static Label FluentLabel(this HtmlHelper helper)
{
return new Label();
}
}
private string target, text;
public Label Target(string target)
{
this.target = target;
return this;
}
this.text = text;
return this;
}
public override string ToString()
{
return String.Format("<label for='{0}'>{1}</label>Fluent", target, text); ;
}
}
.Text("First Name")
)
In this blog I will show how to create a custom MVC
Extensions using the Fluent Interface, which is the gateway for creating
complex HTML Helpers.
Fluent API
The elegant way to create a complex HTML Extensions is to
use the Fluent API approach. Below is the quote from Wikipedia on the Fluent
Interface
In software engineering, a fluent interface (as first coined by Eric
Evans and Martin Fowler) is an implementation of an object oriented API that
aims to provide for more readable code.
A fluent interface is normally implemented by using method chaining to
relay the instruction context of a subsequent call (but a fluent interface
entails more than just method chaining [1]). Generally, the context is
·
defined
through the return value of a called method· self-referential, where the new context is equivalent to the last context
· terminated through the return of a void context.
The key to the fluent interface is method chaining. The
fluent interface was heavily used in the .NET framework. Below is an example of
using the fluent interface
IEnumerable<string>
query = translations
.Where (t => t.Key.Contains
("a")).OrderBy (t => t.Value.Length)
.Select (t => t.Value.ToUpper());
We can incorporate this fluent interface in our custom Label HTML Extension. With the fluent interface our call to the label will be transformed as follows:
@(Html.FluentLabel()
.Target("firstName").Text("First Name")
)
Method Chaining
Pattern
Method Chaining is a technique in which every method returns
the current object, which it is part of, thus allowing the calls to be chained
together in a single statement. In our custom extension Target and Text methods
are stacked on another and if needed we can continue this cascading to any
number of methods. Below is the Target method’s code which demonstrates this
method chaining pattern.
public Label Target(string target)
{this.target = target;
return this;
}
Fluent API in Action
Below is the complete code of our custom Label HTML Helper
using fluent interface with methods Target and Text chaining together to form a
cohesively unit
public static class LabelExtensions
{public static Label FluentLabel(this HtmlHelper helper)
{
return new Label();
}
}
public class Label
{private string target, text;
public Label Target(string target)
{
this.target = target;
return this;
}
public Label Text(string text)
{this.text = text;
return this;
}
public override string ToString()
{
return String.Format("<label for='{0}'>{1}</label>Fluent", target, text); ;
}
}
This above custom Label extension can be used in the View as
follows:
@(Html.FluentLabel()
.Target("firstName").Text("First Name")
)
As you see the Fluent interface provides an easy
infrastructure for building complex MVC Extensions.
If we are building a library of MVC Extensions, such as
Juime (JQuery UI MVC Extensions), we need more than fluent interface. We have
to couple this fluent interface with builder pattern. In my next blog I will
walk you through the builder pattern and how it can be applied to build MVC
Extensions.
Or one can save all the typing, string fomatting and type designing and use the wonderful HtmlTags library: http://www.nuget.org/packages/HtmlTags/
ReplyDeleteDaniel, Microsoft has TagBuilder object which is similar to your HtmlTags.
Deletehttp://www.asp.net/mvc/tutorials/older-versions/views/using-the-tagbuilder-class-to-build-html-helpers-cs
Anyway my intent in this blog is to focus on creating the fluent extensions and not on how to generate the Html string.