I was glad to see an open-source project using the MVP pattern for web forms on the  OSS market.  Either the MVP or MVC patterns is a good solution for ASP.NET because it doesn’t rely on the page to utilize the logic; rather, we can separate the  presentation logic versus the view logic/binding.  I felt I wanted to add something to this project, and in comes my first enhancement (created through a fork): webformsmvpextensions.

The first enhancement was model injection capabilities.  This feature incorporates a new namespace: WebFormsMvp.Injection, that contains several key components.  The default logic uses a [ModelInjection] attribute to specify what type of injection to perform.  There are two options:

  • DI container injection, which requires the use of a separate model injector.  I’ll cover this in a later post.
  • Local container injection, which uses a lookup class to do the instantiation.

Take, for example, the following class:

public class LookupAttributedTestModel

{
    [ModelInjection(LookupType = typeof(KeysTestInjector))]
    public List<string> Keys { get; set; }

    [ModelInjection(LookupType = typeof(ValuesTestInjector))]
    public List<object> Values { get; set; }
}

Notice the ModelInjection definition; it defines the type of an injector to use to inject values.  This injector defines the IModelInjector interface to push values into the underlying List<string>.  Additionally, we specify the type here directly, which is only used for lookup-based injection.  The injectors to inject the values look like:

public class KeysTestInjector : IModelInjector

{
   public object Inject(string key, ModelInjectionSettings settings)
   {
       return new List<string> { “1”, “2”, “3” };
   }
}

public class ValuesTestInjector : IModelInjector
{
    public object Inject(string key, ModelInjectionSettings settings)
    {
         return new List<object> { 1, 2, “Three” };
    }
}

Because the injector knows of the underlying type, it simply returns that type to the caller; this can be dangerous to assume.  Fortunately, ModelInjectionSettings contains the model and property information being injected, so you can make the right determination as to the type to return.  At the time the PresenterBinder begins to build the presenter instance, the binder also passes the view to it.  The IView<TModel> implementation also passes the model, and as such, at this point, the extensions framework begins to do its DI magic.  It loops through each property, looking for the attribute type in question.  For the matching properties, each definition of the model is examined, and any lookup injectors are instantiated, have its Inject method called, and the values are passed through reflection to the property.

For our example, the Keys property is examined; the framework finds the [ModelInjection] attribute with a KeysTestInjector type.  This type is instantiated, the Inject method is called, returning the generic List<string>.  This list is passed to the property via reflection, and the finished presenter returns to the caller has the Keys property with supplied values (and any other injections as well).  Thus, when the view is served, the model is properly instantiated at that time.

Make sure you enable injection by setting ModelInjectors.IsEnabled = true; in the global.asax file, or within the specific ASPX page you want to use the feature for.

You can download the forked code at: http://webformsmvp.codeplex.com/SourceControl/network/Forks/bmains/WebFormsMvpExtensions

Let me know what you think.  I’ll explain some of the other extensibility points of the initial development process.