NoSQL – How a Movement Gives You Speed

In the past, developing web applications meant using SQL. For those relying on relational data, this was no problem. But for those with massive amounts of data, this was like steering a barge – a bulky solution, creating drag-on queries when the intended goal was speed and availability. As Whiteboard looks at the architecture of a site, we have many options from which to choose.

With the oppression of limited Databases came a rebellion, and with that rebellion came a movement. In this case, the NoSQL movement, which arrived with a myriad of motivated programmers caused a pendulum swung that cranked out new opportunities…most of them open-source.

Those opportunities have clever names, and were created by a host of wild enthusiasts to handle a huge quantity of data, especially when the data’s nature does not require a relational model. They are Mongo, Cassandra, Riak, Redis, Couch and Neo4J to name a few.

Cassandra (Apache Cassandra), for example, is a NoSQL solution that was initially developed by the people of Facebook as a hybrid database management system that allows for tunable consistency goals. This means that a query may provide different results from different angles, but it is widely available to users – and fast.

Which brings us to CAP Theorem:

In computer science, the CAP Theorem says that it is impossible for a distributed computer system to achieve these three guarantees at once:

A. Consistency (C) – all nodes and queries see the exact same data at the same time.
B. Availability (A)– 100% uptime.
C. Partition tolerance (P) – the system keeps going even when message loss occurs in part of the system.

To try all three would be like placing child seats in a race car, which of course is built for speed, not a daily shopping trip. To try, you would need to dial down your speed, therefore defeating the purpose of having a race car.

Cap Theorem suggests that to gain A, one may need to sacrifice C. To gain C, one may need to sacrifice A and so on…
Example:

  • SQL allows C and P, but decreases A.
  • Riak focuses on C
  • Mongo gives A and P while, some say, decreases C.

These are debatable assertions, and often dependent on the programmer who is turning the knobs. But even Birmingham’s own MongoDB claims weakness, as its focus is on flexibility, power, speed, and ease of use, while sometimes sacrificing “fine-grained control and tuning, and overly powerful functionality.” Still, it is the rock star of the NoSQL movement and is now being used by SquareSpace, Craig’s List and MTV.

We often use CouchDB, at Whiteboard-IT. Jacob Kaplan-Moss, author of “The Definitive Guide to Django,” claimed here,“Django may be built for the Web, but CouchDB is built of the Web.” As the web is our native environment, CouchDB is the most natural tool for us to use.

The NoSQL movement is has great momentum, though it has earlier roots. Lotus Notes, for example, was forced to write their own database in 1985, which they called NSF (Notes Storage File). Founding member and former CEO, Tim Halvorsen was NoSQL when NoSQL wasn’t cool. He says,

“…we created it from scratch.  At the time, I looked at some of the databases out there (e.g. dBase, etc), and they were all too limited for what we needed.  So, we wrote our own.  Its a “document database”, not a relational database, with each “document” (aka record) having a variable number of fields.  No schema – each record was self-contained, but they could also be indexed (which any database must be capable of).”

History was made and even CouchDB is based on the work accomplished by Lotus Notes.

So – there are many options from which to choose, and if your web designer goes to SQL straight away, it might give reason to ask if others have been considered. Depending on your requirements, you may have another need…the need for speed.

 

 


Ajax your ASP.NET MVC Application with Pathbinder

Gracefully Degrading AJAX Page Loading

The goal of this article is to demonstrate a technique for enabling AJAX loading of content for ASP.NET MVC web applications. The technique uses Pathbinder. It gradefully degrades so that in browsers without JavaScript, the users will navigate pages as normal. The method of making this happen involves translating internal site links to have a ‘#’ in front of the href path on pageload and then using AJAX to load these pages into the content area of the page without reloading the entire page. For users who do not have JavaScript enabled, the links will work like normal links. On the server-side, we must respond to AJAX requests by rendering the page without its master page. For normal requests, we will render the page with its master page.

Pathbinder

Pathbinder is a jQuery framework packaged with couchapp.  It was inspired by sammy.js.  Pathbinder makes it easy to respond to changes in URL paths with JavaScript event handlers.  Why is this relevant as changes to URLs usually reload the page? URL Paths refer to ‘#’ portions of the URL. The part of the URL following the ‘#’ is used to store the state of a page and changes without reloading the page. When a user clicks on a link to ‘#/foo’, the path in the URL will change but the page will not reload.  Pathbinder will trigger events registered for this URL path to allow the application to modify the page.

The HTML

Say Hello

The JavaScript

// Register event 'hello-world' to be triggered on '#main' when URL path changes to #/hello-world
// note that the '#' should not be included in the URL path when registering the event
$(“#main”).pathbinder(“hello-world”, “/hello-world”);

// Bind an event handler to the event 'hello-world'
$(“#main”).bind(“hello-world”, function() {
	$("#main").html(“<p>Hello World</p>”);
});

Altering Standard Link to Load Pages with AJAX

Now that we have a basic understanding of pathbinder, it is time to write the JavaScript that will change the regular links on
a page into AJAX links. We will write a function called handleAnchor that will perform three tasks: bind an event-handler named
after the anchor’s href to the ‘#main’ content area that AJAX loads the page into the content area, register the event in pathbinder
on the ‘#main’ content area, and alter the anchor’s href to have a ‘#’ infront of the url in the href attribute.

   var handleAnchor = function(indx, anchor) {
      var href = $(anchor).attr('href');

      if (!href) { return; }

      $("#main").bind(href, function() {
        $.ajax({
          url: href,
          success: function(data, textStatus) {
            $("#main").html(data);
          }
        });
      });

      $("#main").pathbinder(href, href);

      $(anchor).attr('href', '#'+href);
  };

  $('a').each(handleAnchor);


Review of ASP.NET MVC in Action

I recently read ASP.NET MVC in Action by Jeffrey Palermo, Ben Scheirman, and Jimmy Bogard. The publication is an excellent introduction to the the ASP.NET MVC framework. The authors provide excellent background on the problems facing the MS development community and the solutions that ASP.NET MVC has offered to these problems. These problems include the general ineptitude of the view engines with which traditional ASP development and even webforms development were driven.

ASP.NET MVC is the clear answer to seperation of concerns that webforms attempted to give us with the code-behind files. The introductory chapter will get the beginner up and running quickly. The diagrams illustrate the points that the concise text makes. Even those without any experience with an MVC framework will find the directions and explanations well-thought-out and easy to follow.

Beyond the introductory content, I was genuinely impressed with the depth that the authors dove into the community and the framework. Phil Haack’s route debugger, a piece of code intimately familiar to those of us who have been following the development of the framework since its early days, is mentioned and code based upon it is provided. The authors discuss such advanced techniques as creating a custom controller factory, a must for those of us who employ dependency injection.

Each new concept is introduced with illustrative code examples. I was particularlly impressed with Chapter 9: Ajax in ASP.NET MVC. A note on unobtrusive Javascript reads:

You might notice throughout this chapter that I prefer unobtrusive Javascript. This means that the functionality of the page degrades gracefully in the absence of Javascript.

This shows careful attention by the authors to provide guidance on best practices. You will find this type of detail throughout the book. This is very refreshing because the Microsoft development community has lagged behind other communities in following wise guidelines and setting sensible best-practices.

The new Microsoft embrace of open-source is also made obvious as the authors present jQuery code in the AJAX chapter.

Chapter 10, hosting and deployment, is a testament to the thoroughness with which the framework is covered. Deploying on IIS6 and earlier, something that can be quite tricky, is covered well. The configuration option of using .aspx extensions as well as the option to use URL rewriting are covered. URL rewriting can be quite difficult, but the authors provide examples to bring it all together.

The ASP.NET MVC framework is a breath of fresh-air for the Microsoft development world. It is a sensible, logical framework that allows extensibility. ASP.NET MVC and WCF are the two best frameworks that Microsoft has ever produced, in my opinion.

ASP.NET MVC in Action will guide you from your first project through advanced topics such as AJAX and deploying on suboptimal (read IIS6) hosting environments. The writing style is clear and concise. Diagrams and code examples are abundant. I recommend it for anyone looking for a great resource for learning about or becoming a better user of the ASP.NET MVC framework.


ASP.NET MVC Domain Driven Design Deux

Series Navigation

  1. Setup
  2. Mapping and Entity Equality

Entity Equality

We’ve got some more housekeeping to do on our Entity object before proceeding.  Because entities are comparable based upon Id, a standard use of the == operator will produce undesirable results. When using an ORM, this is particularly important. You will often have instances of objects, especially objects in child relationships, that are the same as, but not reference equal to, one another.

Test Cases for Desired Entity Equality Behavior

I’m a believer in documentation via test cases, so here are my test cases that demonstrate the desired behavior:


[TestFixture]
public class EntityEqualityContext
{
[Test]
public void TwoTransientEntitiesShouldNotBeEqual()
{
var entity1 = new TestEntity();
var entity2 = new TestEntity();

Assert.AreNotEqual(entity1, entity2, “Different transient entities should not be equal.”);
}

[Test]
public void TwoReferencesToSameTransientEntityShouldBeEqual()
{
var entity1 = new TestEntity();
var entity2 = entity1;

Assert.AreEqual(entity1, entity2, “Two references to the same transient entity should be equal.”);
}

[Test]
public void EntitiesWithSameIdShouldBeEqual()
{
var entity1 = new TestEntity();
var entity2 = new TestEntity();

entity1.SetId(1);
entity2.SetId(1);

Assert.AreEqual(entity1, entity2, “Entities with same id should be equal.”);
}

[Test]
public void EntitiesWithDifferentIdShouldNotBeEqual()
{
var entity1 = new TestEntity();
var entity2 = new TestEntity();

entity1.SetId(1);
entity2.SetId(2);

Assert.AreNotEqual(entity1, entity2, “Entities with different ids should not be equal.”);
}

[Test]
public void EntityShouldNotEqualTransientEntity()
{
var entity1 = new TestEntity();
entity1.SetId(1);

var entity2 = new TestEntity();

Assert.AreNotEqual(entity1, entity2, “Entity and transient entity should not be equal.”);
}

[Test]
public void EntitiesWithSameIdButDifferentTypesShouldNotBeEqual()
{
var entity1 = new TestEntity();
var entity2 = new OtherEntity();

entity1.SetId(1);
entity2.SetId(1);

Assert.AreNotEqual(entity1, entity2, “Entities of different types should not be equal even if they have the same id.”);
}

///

/// A test entity class created so that we can excercise
/// the functionality of the entity equaltiy members.
///

 

public class TestEntity : Entity
{
private int id;

public override int Id
{
get { return id; }
}

public void SetId(int id)
{
this.id = id;
}
}

public class OtherEntity : Entity
{
private int id;

public override int Id
{
get { return id; }
}

public void SetId(int id)
{
this.id = id;
}
}
}

Summarized, these tests say that entities with id of “0” should only be equal if they are the same object.  This is reference equality.  Entities with an id should be equal if their ids are equal and they are of the same type.  This is identity equality.

Entity with Equaltiy Members


public abstract class Entity: IEquatable
{
private int id;
private int transientHashCode;

public virtual int Id { get { return id; } }

public override bool Equals(object obj)
{
return Equals(obj as Entity);
}

public virtual bool Equals(Entity obj)
{
if (obj == null) return false;

if (IsTransient)
{
return ReferenceEquals(this, obj);
}

return obj.Id == Id && obj.GetType() == GetType();
}

public override int GetHashCode()
{
if (IsTransient)
{
if (transientHashCode == 0)
{
transientHashCode = base.GetHashCode();
}
return transientHashCode;
}
return id;
}

private bool IsTransient
{
get { return Id == 0; }
}
}

For more information about why insuring that your entity equality is in order, please see The NHibernate FAQ.

As this is a blog example, we will need a class to represent posts.

The Post Class


public class Post : Entity, IEquatable
{
public virtual string Title { get; set; }

public virtual string Body { get; set; }

///

/// Indicates whether the current object is equal to another object of the same type.
///

 

///
/// true if the current object is equal to the parameter; otherwise, false.
///
////// An object to compare with this object.
/// public virtual bool Equals(Post other)
{
return base.Equals(other);
}
}

In the future, we will add other properties like a collection of comments.  For now, we will keep it simple in order to demonstrate the fluent mapping.

What’s the Deal with the Virtual Members

NHibernate makes use of proxies for advanced features like lazy loading.  The default proxy factory uses Castle’s DynamicProxy. DynamicProxy generates inheritance based proxies; therefore, it can only work if members are marked as virtual so that it can override them.  There are other proxy choices; however, I will not be covering them. Making members virtual is a small price to pay for the convenience in my opinion.

Mapping the Post Entity to the Database

Generating the mappings for your entities could not be easier with fluent NHibernates automapper.

Here is a simple utility class to add to the Service project:


public class DomainMapper
{
private readonly IPersistenceConfigurer persistenceConfigurer;

public DomainMapper(IPersistenceConfigurer persistenceConfigurer)
{
this.persistenceConfigurer = persistenceConfigurer;
}

public void Configure(Configuration configuration)
{
Fluently.Configure(configuration).Mappings(mapping => mapping.AutoMappings.Add(GetMapper())).Database(
persistenceConfigurer).BuildSessionFactory();
}

protected virtual AutoPersistenceModel GetMapper()
{
var persistenceModel = new AutoPersistenceModel(typeof (Entity).Assembly)
.Where(type => !type.IsAbstract && typeof (Entity).IsAssignableFrom(type))
.WithConvention(convention =>
{
convention.IdConvention =
id => id.Access.AsReadOnlyPropertyThroughCamelCaseField().GeneratedBy.HiLo(100.ToString());
convention.IsBaseType = type => type == typeof (Entity);
convention.DefaultStringLength = 255;
});
return persistenceModel;
}
}

I like to use HiLo for the id convention and avoid using Native Identity.  For more information about the identity generators available using NHibernate, please see Vadi’s Rants.

The DefaultStringLength is just a personal preference.  The default is 100 if you do not specify a convention.

The IsBaseType is necessary so fluent NHibernate does not create joined table entities from everything that inherits from Entity.

In the Blog.Service.Test project, add this utility class:


public class TestDomainMapper: DomainMapper
{
public TestDomainMapper() : base(SQLiteConfiguration.Standard.InMemory().ShowSql())
{
}
}

This class simply inherits from DomainMapper and provides a SQLite in memory database as the persistence configuration.  Using an in-memory database for our tests will make them run much faster.  As the project grows, it is advisable to also run your integration tests vs the actual database that you will be using; however, running them against an in-memory database during standard development saves time and is very convenient.

In my first post, I attempted to make a thorough list of the tools that would be used in the project.  I neglected at least one though: SQLite.  I may have neglected more, so do not be surprised if we have to add more binaries throughout the series to our libraries directory.  System.Data.SQLite can be downloaded here.  Add it to trunk/libraries/sqlite and reference it from the Blog.Service.Test project.

Fluent NHibernate provides a useful helper for integration tests: PersistenceSpecification<T>.  Here is what the initial Post integration test looks like:


[TestFixture]
public class MappingIntegrationContext
{
protected ISession Session { get; private set; }

[SetUp]
public void BeforeEachTest()
{
var configuration = new Configuration();
new TestDomainMapper().Configure(configuration);

var sessionFactory = configuration.BuildSessionFactory();
Session = sessionFactory.OpenSession();

IDbConnection connection = Session.Connection;

string[] scripts = configuration.GenerateSchemaCreationScript(Dialect.GetDialect(configuration.Properties));
scripts.ToList().ForEach(script =>
{
var cmd = connection.CreateCommand();
cmd.CommandText = script;
cmd.ExecuteNonQuery();
});

Session.Flush();
}

[Test]
public void PostIntegrationTest()
{
new PersistenceSpecification(Session)
.CheckProperty(x => x.Title, “A Test Post”)
.CheckProperty(x => x.Body, “This is where the content of my post will be. Yay.”)
.VerifyTheMappings();
}
}

This is a good start, but obviously as our domain model grows and we need more test classes, this SetUp can be abstracted into its own base class that other test classes can inherit from.


public abstract class FixtureBase
{
[SetUp]
public void BeforeEachTest()
{
var configuration = new Configuration();
new TestDomainMapper().Configure(configuration);

var sessionFactory = configuration.BuildSessionFactory();
Session = sessionFactory.OpenSession();

IDbConnection connection = Session.Connection;

string[] scripts = configuration.GenerateSchemaCreationScript(Dialect.GetDialect(configuration.Properties));
scripts.ToList().ForEach(script =>
{
var cmd = connection.CreateCommand();
cmd.CommandText = script;
cmd.ExecuteNonQuery();
});

Session.Flush();
}

protected ISession Session { get; private set; }
}

Now the noise of the SetUp method can be taken out of the MappingIntegrationContext and we have a reusable base class for future test classes.

Implementing IRepository

Next, we will implement our repository.  NHibernate.Burrow AppBlock makes this trivial.  Reference NHibernate.Burrow.AppBlock from the Blog.Service assembly.


using System.Collections.Generic;
using Blog.Domain;
using NHibernate.Burrow.AppBlock.DAOBases;

namespace Blog.Service
{
public class Repository: GenericDAO, IRepository where T : Entity
{
///

/// Find an entity by unique identifier.
///

 

///Unique identifier of the entity. /// Entity if found, null otherwise.
public T Find(int id)
{
return base.Get(id);
}

///

/// Find all entities.
///

 

/// Sequence of entities found.
public new IEnumerable FindAll()
{
return base.FindAll();
}

///

/// Save (insert or update as appropriate) on next commit of the unit of work.
///

 

///Entity to be saved. public new void Save(T entity)
{
base.Save(entity);
}

///

/// Delete on next commit of the unit of work.
///

 

///Entity to be deleted. public new void Delete(T entity)
{
base.Delete(entity);
}
}
}

For the basic functionality, AppBlock provides everything that we need.

Update: Some of you want the sample project that I am working from, so I will add a zip of it soon.

In the next post, we will wire up the Inversion of Control in our MVC app and create a controller for Post CRUD.

kick it on DotNetKicks.com

ASP.NET MVC Domain Driven Design

Series Navigation

  1. Setup
  2. Mapping and Entity Equality

Introduction

In this series of posts, I will detail how I set up projects using the principles of domain driven design in ASP.NET MVC.

The tools and libraries we will use are as follows:

The sample app will be the canonical blog example. This series will be light on the discussion of the theory of DDD and heavy on the nuts and bolts of asp.net MVC implementation.

Project Structure

Create a new directory for the project.  I’m calling mine DDDSample. Following subversion convention, create a trunk and branches folder inside of DDDSample. Inside of trunk, create three directories: src, tools, and libraries.

The ‘src’ directory is where our code will go. The ‘tools’ directory will have NUnit and in the future, NAnt. The ‘libraries’ directory will contain the third party binaries that the project references.

Gathering the Libraries and Tools

1) Download the latest binary of fluent nhibernate from http://fluentnhibernate.org/downloads. Put the fluent nhibernate binaries in trunk/libraries/fluent-nhibernate.

2) Download NHibernate.Burrow from http://sourceforge.net/project/showfiles.php?group_id=216446. Put the burrow binaries in trunk/libraries/nhibernate.burrow. Important Note: Sometimes the latest version of NHibernate.Burrow will not have been built against the same version of NHibernate as fluent nhibernate was. Therefore, it is important that you be able to build NHibernate.Burrow, and the rest of the libraries that follow, from source.  NHibernate.Burrow is a part of NHContrib. The NHContrib svn repository is located at https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk. There is a build script in the root directory of the NHibernate.Burrow subdirectory of the project. To rebuild with a different version of NHibernate, just replace the NHibernate dll in NHibernate.Burrow/lib/NHibernate with the binary of NHibernate from the fluent nhibernate.

3) Download NUnit from http://www.nunit.org/index.php?p=download.  Get the zip distribution. Unzip the entire contents into trunk/tools/nunit. It is important that you include the full NHibernate distribution with your project so when we add an automated build tool later it will be able to run the unit tests without assuming that every developer has installed the correct version of NUnit from msi.

4) Download Moq from http://code.google.com/p/moq/downloads/list. Put the binaries in trunk/libraries/moq.

5) Download MVCContrib from http://www.codeplex.com/MVCContrib. Put the binaries in trunk/libraries/mvccontrib.

As an added measure of safety against change, I like to reference the MVC libraries themselves from binaries I store in my svn repository instead of from source.  You don’t have to do this, but if you choose to, I put System.Web.Mvc, System.Web.Routing, and System.Web.Abstractions in trunk/libraries/mvc.

Your completed project structure should look like this:

Creating the Projects

Our mvc project and class libraries will go in trunk/src.

Create an asp.net MVC project.  For this sample, I’m calling mine Blog.Web.

Create two class libraries: Blog.Domain and Blog.Service. Blog.Domain is where our POCO (Plain Old C# Objects) entities and our repository interfaces will reside. Blog.Service is where the business logic that ties the application together will live.

Reference Blog.Domain and Blog.Service from Blog.Web. Reference Blog.Domain from Blog.Service.

Create a new solution folder (right click on project, hover over add, choose new solution folder) called Test. This is where our test projects will go.

Create three class libraries: Blog.Web.Test, Blog.Domain.Test, and Blog.Service.Test.  In each of these projects reference NUnit.Framework from /trunk/tools/nunit.

More test projects may be needed later for separating unit tests from integration tests, but this is how I like to start with one unit test project for each of my projects.

The solution should now look like this:

Entity Base Class

In the domain, create an object to be the base class for entities. An entity is an object that has an identity.

namespace Blog.Domain
{
public abstract class Entity
{
private int id;

public virtual int Id { get { return id; } }
}
}

There is no way to set the id property of the Entity base class. This is by design. Our persistence layer will use NHiberante generators to generate the identity values when we save new entities to the database.

Repositories

Just what are repositories? Repositories are an abstraction of the way we manage aggregates. Repositories should correspond only to aggregate roots.  An aggregate is a cluster of objects that are treated as a unit.  The aggregate root is the root object of the unit.

In Domain Driven Design, the repository interfaces are a part of the domain, but the implementations are not.

Generic Repository of Entities

All entity repositories will need some base functionality, so we define IRepository<T> with some basic methods that we expect any repository to need.

using System.Collections.Generic;

namespace Blog.Domain
{
///

 

/// Repository of entities.
///

 

 

public interface IRepositorywhere T : Entity
{
///

 

/// Find an entity by unique identifier.
///

 

 

///Unique identifier of the entity. /// Entity if found, null otherwise.
T Find(int id);

///

 

/// Find all entities.
///

 

 

/// Sequence of entities found.
IEnumerable FindAll();

///

 

/// Save (insert or update as appropriate) on next commit of the unit of work.
///

 

 

///Entity to be saved. void Save(T entity);

///

 

/// Delete on next commit of the unit of work.
///

 

 

///Entity to be deleted. void Delete(T entity);
}
}

Conclusions

In this post we have done a lot of nuts and bolts work. The amount of setup required may seem daunting, but as stated earlier, the third party tools and libraries will pay dividends in the long-run.

In the next post, we will create a Post entity, create a concrete implementation of IRepository<Post> using NHibernate, map Post to a database using Fluent NHibernate, and test our persistence model.

kick it on DotNetKicks.com

MVC Forms With Validation Open-Sourced

I’ve set up a Google code repository here for the ASP.NET MVC Forms With Validation framework I discussed in this post.

I have made some alterations to it since the post that I will review in a later posting.

Briefly, the major changes are as follows:

  1. Multiple fieldsets are now supported in the forms.
  2. I have taken the first steps towards supporting objects that contain child objects.  A 1-1 relationship is supported in the current revision. A new fieldset is generated for each child object.
  3. Strategies have been revamped so that they no longer are mapped to types.  Now a strategy is allowed to return null if it does not want to handle a property descriptor passed to it. If it returns null, the next strategy in the list will be tried.

Check it out. Tell me what you think. I am accepting patches and if you want to be a contributor, contact me through the contact form on this blog.

kick it on DotNetKicks.com


Forms Framework with Validation for ASP.NET MVC

Update: This project has been open-sourced.  See details in this post.

Another Update: This article was written using asp.net MVC preview 4. The better option now is to use MVCContrib’s validators or the MVCContrib fluent html project in general with IDataErrorInfo. I leave this post here as a reference. Also, if you wish to have a more Django style forms framework, this would be a great starting point. The code is freely available for anyone who wishes to use it.

One thing that is notably missing from ASP.NET MVC is a good way to handle forms and their validation.  To resolve this issue, I started on a simple forms framework this weekend.

The end goal

I don’t particularly like the action filter to handle the insertion of the model as a parameter.  I would prefer it be done via windsor and interceptors; however, for the first go round I have decided to keep the castle stack out of this. The technique could easily be adapted to use MVC Contrib’s WindsorControllerFactory and interceptors so that attributes do not have to be on every action you wish to use a form helper with. More on that later.

For those of you who want to skip the reading and get straight to the code, download the sample project. Look at the /Home/Contact page. Note: the sample project depends on MVC Preview 4.

The Components

  • Field – A field is the smallest unit of input and validation in a form.
  • Widget – A widget is an abstraction of HTML template text for input.
  • FormBase – Base class for form helpers.
  • ModelForm – A form auto created from a POCO model.

Widget

A widget has a name, a value, and some attributes. The name and value properties are by default shortcuts to the name and value attributes of the widget’s attribute collection.  However, this behavior is overridable in subclasses. A widget also has a way of rendering itself as XHTML.

Field

A field has a name, a value, and a widget. By default a field is required, and it has a publicly exposed validate method so that it can be asked to validate its value. It also has the ability to output itself as XHTML.

FormBase

FormBase, the base class for forms contains a collection of fields, a method to validate the fields, and a method to load the values of fields from a name value collection. The latter facilitates the loading of data from a browser request.

The first concrete implementation of FormBase I created was ModelForm. A ModelForm accepts a generic type argument and in its constructor takes an object of that type. It uses this object to generate fields for the form. The generation logic is implemented using the strategy pattern so that it is easily customizable.

Here is the strategy interface

The ModelForm registers default strategies

The constructor allows you to pass in your own strategies

With that, we have everything we need to make a form from a POCO.

Model Action Filter

One of the neatest things ASP.NET MVC does is allow you to make controllers with parameters that will be filled in from the request.

I wanted to be able to do this with my form classes as well.

For the first go round, I decided not to use what I would prefer: Windsor and Interceptors.  Instead I integrated the MVC way by using their action filters.

The filters give us everything we need to set the values for a parameter.  We have access to the parameters through the ActionMethod.GetParmaeters() method and we can set the parameters via the ActionParameters dictionary.

Here is the action filter

FormFactory is a simple helper class that uses a strategy pattern to create forms based upon the type passed in and a NameValueCollection.

Settings filterContext.Action

Now, this action will work!

Rendering the Form in a View

I provided three canonical methods for rendering the form:

AsDiv – renders the form with each field wrapped in a div
AsTable – render the form with each field as a table row
AsList – render the form with each field as a list item of an unordered list

I also provided a AsCustom method that allows you to specify an XElement to wrap the form fields inside of and an XElement to use as the parent for the children generated by the field instances.

If you want even more flexibility, the rendering is completely overridable by subclassing.

Rendering the form is as simple as passing it to a view and calling AsDiv() or your preferred alternative.

All output is valid XHTML.  Invalid fields receive an error class.

Rendered

Validation

Download the Sample Project
Note: the sample project depends on MVC Preview 4.

kick it on DotNetKicks.com