the last few months of my time have been spent on polishing up bistro. We have come a long way, and have been very happy with what we've seen. The system is now in full use at my day job, and (for the most part) everyone is happy. Of course, status quo boring, and there are always new request that come up. I started talking about the first of these in my previous post about validation. Once implemented, that set us down an interesting direction, as we realized that while bistro never wanted to have a formally defined "model", the reality is that a model still exists, and applications need to interact with it.

The core concept for "model" definition in bistro becomes one of mapping and inference. The idea is that your controller tier, ideally, is a thin wrapper, whose sole purpose in life is to ferry data back and forth between your view and your model, applying some transformations along the way. so, let's say i have this model, controller and view:

 
    // our model
    class Person
    {
        public string firstName, lastName;
    }
 
    // our controller
    [Bind("/entityTest")]
    public class EntityController : AbstractController
    {
        [FormField, Request]
        public string
            firstName,
            lastName;
 
        [Request]
        public Person person;
 
        [Request]
        string validationMessage;
 
        public override void DoProcessRequest(IExecutionContext context)
        {
            if (String.IsNullOrEmpty(firstName) || String.IsNullOrEmpty(lastName))
            {
                validationMessage = "first and last name are required";
                return;
            }
 
            person = new Person() { firstName = this.firstName, lastName = this.lastName };
        }
    }
 
<-- and the view -->
{% if validationMessage %}
    {{ validationMessage }}
{% endif %]
<form method="post">
    <p>First name <input name="firstName" value="{{firstName}}" /></p>
    <p>Last name <input name="lastName" value="{{lastName}}" /></p>
    <p><input type="submit" value="Submit" /></p>
</form>

This is all fairly straightforward. I have an entity of type Person, with fields first and last name, i have a controller that gets those fields from a form, tries to populate them, and if there are validation issues, doesn't do anything, except complain about validation.

So let's start with that - validation. I already talked about a theoretical approach to the problem. Well, in that time the theoretical has become the practical, and here's how we'd do the validation:

First, we implement the new IValidatable interface. It just says that an object (note, not just a controller) can be validated by the bistro validation mechanism, and that the object needs to be able to accept the results of that validation:

 
    // our controller
    [Bind("/entityTest")]
    public class EntityController : AbstractController, IValidatable {
        public List<IValidationResult> Messages { get; set; }
        public bool IsValid { get; set; }
    ...
    }
 

Next, we build a class that will hold the validation rules:

 
    public class SimpleValidator: Validator<EntityController>
    {
        protected override void Define()
        {
            Define(
                Value(c => c.firstName).IsRequired("First Name is required"))
            .And(
                Value(c => c.lastName).IsRequired("First Name is required"));
        }
    }
 

Fairly straightfoward (the Bistro.Extensions.Validation.Common namespace defines a series of extension methods that provide a fairly complete range of validation rules, plus you can define your own). Finally we have to tell the controller who is going to perform the validation, and modify our template to expose the validation rules:

 
    // our controller
    [Bind("/entityTest")]
    [ValidateWith(typeof(SimpleValidator))]
    public class EntityController : AbstractController, IValidatable {
    ...
    }
 
<-- and the view -->
{% if Messages %}
    <ul>
    {% for m in Messages %}
        <li>{{m.Message}}</li>
    {% endfor %}
    </ul>
{% endif %]
<form method="post">
    <p>First name <input name="firstName" value="{{firstName}}" /></p>
    <p>Last name <input name="lastName" value="{{lastName}}" /></p>
    <p><input type="submit" value="Submit" /></p>
</form>

With all that in place, we can now modify the DoProcess method do not worry about the validation rules themselves:

 
    public class EntityController : AbstractController
    {
        ...
 
        public override void DoProcessRequest(IExecutionContext context)
        {
            if (!IsValid)
                return;
 
            person = new Person() { firstName = this.firstName, lastName = this.lastName };
        }
    }
 

Cool. Now we've been able to define our validation rules externally to the controller, and simplified the work the controller has to do. An added benefit of this (that I won't cover much here) is the validation rules are now discoverable externally. The new BistroIntegration branch comes with a set of ndjango tags that read the validation rules, and expose them directly in the html as jquery validators, mapping bistro validators over (pretty cool stuff, really - expect a separate blog post and a dimecast on the matter in the next few weeks).

With that out of the way, we're still left with two unpleasant aspects. First of all, we still have a bunch of code dealing with populating the Person entity with data. In a more complex scenario, we'll also have to deal with populating the controller from the entity, in addition to the other way around (an add/edit screen is a perfect example). Second of all, our rules about what is or isn't required for the entity, are defined on the controller, and if i have another controller that deals with it for whatever reason, i'll have to duplicate those, or risk inconsistent data. The solution to both is simple: make bistro aware of the existance of some poco whose fields the controller is linked to:

 
    class SimpleMapper: EntityMapper<EntityController, Person>
    {
        public SimpleMapper()
        {
            Map(x => x.firstName).To(y => y.firstName)
                .Map(x => x.lastName).To(y => y.lastName);
        }
    }
 

and then tell bistro about it

 
    // our controller
    [Bind("/entityTest")]
    [MapsWith(typeof(SimpleMapper))]
    public class EntityController : AbstractController, IValidatable, IMappable {
        public IEntityMapper Mapper { get; set;}
        public override void DoProcessRequest(IExecutionContext context)
        {
            if (!IsValid)
                return;
 
            person = new Person();
            Mapper.Map(this, entity);
        }
        ...
    }
 

*Cue tv announcer voice* buuut wait, there's more! Why go through manually lining up fields that have the same name and type? Let's do this instead:

 
    class SimpleMapper: EntityMapper<EntityController, Person>
    {
        public SimpleMapper() { Infer(); }
    }
 

And if we need a bit more control, we can do this:

 
    class SimpleMapper: EntityMapper<EntityController, Person>
    {
        public SimpleMapper()
        {
            Infer()
                .Except(x => x.extra)
                .Map(x => x.thirdField).To(y => y.baz);
        }
    }
 

The Infer method will automatically build a mapping for fields that have the same name and assignable types, removing the need to spell everything out. Now that we have our mapping, our final trick is possible. If bistro knows how to move data from EntityController.firstName to Person.firstName, and vice-versa, doesn't it stand to reason that we could do the same thing to validation rules? So the final trick is this: define the validation rules on the entity, rather than the controller:

 
    public class SimpleValidator: Validator<Person>
    {
        protected override void Define()
        {
            Define(
                Value(c => c.firstName).IsRequired("First Name is required"))
            .And(
                Value(c => c.lastName).IsRequired("First Name is required"));
        }
    }
 
    [ValidateWith(typeof(SimpleEntityValidator))]
    public class Person: IValidatable
    {
        ...
 
        public List<IValidationResult> Messages { get; set; }
        public bool IsValid { get; set; }
    }
 

and then use the field mapping to also map over validation rules from the entity to the controller:

 
    class EntityControllerValidator: Validator<EntityController>
    {
        protected override void Define() { ByMapping(); }
    }
 
    [Bind("/entityTest")]
    [ValidateWith(typeof(EntityControllerValidator))]
    [MapsWith(typeof(SimpleMapper))]
    public class EntityController : AbstractController, IMappable, IValidatable
    ...
 

which is exactly what "ByMapping" does.

Whew. That's a lot of stuff. Let's step back for a second and see what we ended up with. We now have a type Person, a controller EntityController, and a mapping between them, that tells bistro how to move data from one to the other, without imposing restrictions on the form on the model class. Additionally, we've defined a series of validation rules on the entity, that we can then also expose to the controller, and subsequently to the UI. Cool, huh?

There are of course a few usability things that we'll be ironing out over the next few weeks (like there are a few more classes that you end up having to define than i like, so that may be replaced with attributes for more common scenarios), but the core concept remains the same. Model mapping and validation are now core concepts of bistro, and an interesting solution to a classic problem.

And, as always, we want your feedback! So if something makes sense, or something doesn't, either let me know here, or shoot the bistro-dev list an email.