Separation of concerns in Input Builders
Note: We have moved on to use UIMaps as described in this blog post.
In our ASP.Net MVC application we want to separate the presentation code associated with HTML views from the act of binding data to HTML controls. We also want to get more of the UI control generation under test. This is our latest refinement towards those goals.
Html page for Address:
<div>
<%= Model.Street
.WithLabel("Street:")
.Width("400px") %>
</div>
<div>
<%= Model.City
.WithLabel("City:") %>
</div>
<div>
<%= Model.States
.WithDefault("Select", "")
.WithLabel("State:") %>
</div>
<div>
<%= Model.ZipCode
.WithLabel("Zip:")
.Width("50px") %>-<%=
Model.ZipPlus
.Width("50px")%>
</div>
Here we only set css and other view related attributes. Now our HTML views are more concerned with how to display the data rather than what to display. Our model uses FluentWebControls to build the HTML inputs:
public class AddressInputProvider
{
private readonly IRepository _repository;
private Address _address;
public AddressInputProvider(IRepository repository)
{
_repository = repository;
}
public void SetAddress(Address address)
{
_address = address;
}
public TextBoxData Street
{
get
{
return Fluent.TextBoxFor(_address, x => x.Street)
.WithId((AddressModel address) => address.Street);
}
}
public TextBoxData City
{
get
{
return Fluent.TextBoxFor(_address, x => x.City)
.WithId((AddressModel address) => address.City);
}
}
public DropDownListData States
{
get
{
return Fluent.DropDownListFor<State, AddressModel, string>(
_repository.GetAll<State>(),
state => state.Name,
state => state.StateCode,
x => x.State)
.WithSelectedValue(() => _address.State);
}
}
public TextBoxData ZipCode
{
get
{
return Fluent.TextBoxFor(_address, x => x.ZipCode)
.WithId((AddressModel address) => address.ZipCode);
}
}
public TextBoxData ZipPlus
{
get
{
return Fluent.TextBoxFor(_address, x => x.ZipPlus)
.WithId((AddressModel address) => address.ZipPlus);
}
}
}
Now we can test the AddressInputBuilder, including the HTML control types and their properties in unit tests. We can eliminate mapping Domain objects to a Model before building the view. As FluentWebControls can bind against the model to get validation information, we only have to define the validation in one place – just in our Domain object or however we choose to do that. Other benefit is that it reduces our reliance on UI tests.
co-authored with Clinton Sheppard
[...] to VoteSeparation of concerns in Input Builders (3/5/2010)Friday, March 05, 2010 from shashankshettyIn our ASP.Net MVC application we want to separate the [...]
ASP.NET MVC Archived Blog Posts, Page 1
March 7, 2010 at 9:03 pm
[...] 16, 2010 by handcraftsman In a recent posting we outlined a novel idea for separating how we want web UI controls to look from where they get [...]
Separation of Concerns in Input Builders 2.0 « Clinton’s Blog
March 16, 2010 at 5:05 pm