.net and other musings

Ben Lovell, an agile developer living in the UK.

Category: Architecture

ASP.NET Development Landscape

With all the System.Web.Mvc goodness flying around at the moment, the Microsoft or nothing shops (you know, the ones that flat-out can’t adopt a technology unless it comes from the borg) might finally get a taste of how web development should be done. Unfortunately for the aforementioned reason, Monorail has never be an option for those developers.

The one thing that really excites me about MSMVC is the periphery of concepts that will be introduced by way of association: deep testability, SRP, DIP and SoC. Traditionally these practices aren’t promoted (or I might go so far as say easily achieved) heavily in the .NET technologies and frameworks coming out of Microsoft. As we’re focusing on ASP.NET at the moment, sure, they’re possible to adhere to whether you’re using ASP.NET in the presentation layer or not, but ASP.NET doesn’t promote them the same way the MVC framework will.

I can’t help but wonder how different the landscape might be now if MSMVC was released with .NET 1.0 instead of webforms?

Advertisements

Dependency injection with Monorail and Windsor

Dependency Injection (or IoC) is a practice I apply when designing software. It enables enforcement of the Single Responsibility Principle and also has the added side effect of producing more testable code.

Scott Bellware has posted an excellent write-up on dependency patterns and it got me thinking about my favoured approach with dependency injection and how the Castle Windsor container provides that for us. I favour constructor based DI as it enforces the fact that your class must be wired up during initialisation. It makes your dependencies highly visible and as Scott mentions – goes some way to producing a self-documenting API.

Some of the common alternatives, or perhaps complimentary approaches include resolving dependencies from the container or service locator hidden in the constructor (dirty), or the provision of property setters for your dependent interfaces. Of course providing getters (or at least public getters) is a no-no as you would be exposing your dependencies to consumers thus violating encapsulation. But I guess this goes without saying?

Thankfully, Monorail controllers and their dependencies can be wired up using constructor based DI via RailsFacility and Windsor integration. Take the following example:

dependencies

ContactController in the diagram above is a simple Monorail controller that depends on the IContactService to carry out most of its work. Stemming from there the IContactService implementation has dependencies on IContactRepository and an external library (from NSpectre) interface IValidatorFactory which is created using the Windsor factory facility and some custom factory code, but more on that later… As you can see from the model, the dependencies are injected via constructor arguments.

Using the RailsFacility is fairly simple, rather than me explaining it I’ll point you to the docs here. Once you’ve got the facility and container set up, you simple declare your controllers and their dependent components via configuration:

<component id="contact.controller" type="Campaigns.Controllers.ContactController, Campaigns.Controllers">
      <parameters>
        <mailTo>benjamin.lovell@gmail.com</mailTo>
        <subject>Contact message from Website</subject>
      </parameters>
    </component>

I’ve explicitly declared some of the required values for the ContactController constructor above. Just as reminder the signature for ContactController  constructor:

public ContactController(IContactService contactService, string mailTo, string subject)

When the ContactController is wired up by windsor the IContactService contactService argument is resolved to the following service configured in my components.config file:

<component id="contact-service"
               service="Campaigns.Core.IContactService, Campaigns.Core"
               type="Campaigns.Services.ContactService, Campaigns.Services">
    </component>

Of course, ContactService also joins in the fun and has its dependencies injected via the same means:

<component id="contact-repository"
               service="Campaigns.Core.IContactRepository, Campaigns.Core"
               type="Campaigns.Repository.ContactRepository, Campaigns.Repository" />

Windsor detects that the ContactService constructor takes a IContactRepository argument and resolves this automatically.

Now for the keen-eyed among you, and going back to my point earlier regarding the IValidatorFactory dependency… This is resolved using the natty Windsor factory facility, the best explanation of which is here. In my configuration I state that IValidatorFactory dependencies should be resolved via my custom factory code:

using NSpectre.Core;
using NSpectre.Core.Configuration;
using NSpectre.Core.Implementation;

namespace Campaigns.Core
{
    /// <summary>
    /// Factory for NSpectre validators
    /// </summary>
    public class NSpectreFactory : INSpectreFactory
    {
        #region Fields

        private readonly string xmlEmbeddedResourcePath;
        private readonly bool saveGeneratedCode = false;
        private readonly string path;

        #endregion

        #region Constructors

        /// <summary>
        /// Initialises the factory with the embedded resource path.
        /// </summary>
        /// <param name="xmlEmbeddedResourcePath">The path to the embedded resource.</param>
        /// <param name="saveGeneratedCode">Save the generated code</param>
        /// <param name="path">The path to save the code to</param>
        public NSpectreFactory(string xmlEmbeddedResourcePath, bool saveGeneratedCode, string path) : this(xmlEmbeddedResourcePath)
        {
            this.saveGeneratedCode = saveGeneratedCode;
            this.path = path;
        }

        /// <summary>
        /// Initialises the factory with the path to the NSpectre configuration embedded resource.
        /// </summary>
        /// <param name="xmlEmbeddedResourcePath"></param>
        public NSpectreFactory(string xmlEmbeddedResourcePath)
        {
            this.xmlEmbeddedResourcePath = xmlEmbeddedResourcePath;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the path to the configuration embedded resource.
        /// </summary>
        public string XmlEmbeddedResourcePath
        {
            get { return xmlEmbeddedResourcePath; }
        }

        /// <summary>
        /// Gets a flag indicating whether NSpectre should save the generated code.
        /// </summary>
        public bool SaveGeneratedCode
        {
            get { return saveGeneratedCode; }
        }

        /// <summary>
        /// Gets the path to save the generated code to.
        /// </summary>
        public string Path
        {
            get { return path; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Creates the validator factory
        /// </summary>
        /// <returns>The validator factory, initialised</returns>
        public IValidatorFactory CreateFactory()
        {
            IConfigurationReader reader = new EmbbeddedXmlResourceConfigurationReader(xmlEmbeddedResourcePath, new NullLogger());
            Initialiser initialiser = new Initialiser();

            if (SaveGeneratedCode)
                return initialiser.CreateValidatorFactory(reader, saveGeneratedCode, path);
            else
                return initialiser.CreateValidatorFactory(reader);
        }

        #endregion
    }
}

The custom factory is hooked up using the following configuration:

<component id="nspectre.factory" 
               service="Campaigns.Core.INSpectreFactory, Campaigns.Core" 
               type="Campaigns.Core.NSpectreFactory, Campaigns.Core">
      <parameters>
        <xmlEmbeddedResourcePath>Campaigns.Core.Model.NSpectreValidations.xml, Campaigns.Core</xmlEmbeddedResourcePath>
      </parameters>
    </component>

    <component id="nspectre.default" 
               type="NSpectre.Core.IValidatorFactory, NSpectre.Core"
               factoryId="nspectre.factory"
               factoryCreate="CreateFactory" />

You really notice the effectiveness of this approach when adding new controllers to your project. You simply add the controller code, define its dependencies in the constructor and add the configuration for the controller to your controllers.config file and everything is resolved and injected for you at runtime. Very nice indeed, I’m sure you will agree!

Testing is made easy by providing dynamic mocks. To make this an even nicer experience take a look at the AutoMockingContainer from the nice folks at Eleutian!

To wrap up I have to say: Castle really does kick the llama’s ass.

BackgroundMotion sample application

I found BackgroundMotion via Andrew Peter’s blog – created in partnership with Microsoft as a “best practice” example application. I’ve had a look at the source code and at first glance it’s quite a nicely architected solution… Certainly better than some of the starter kits coming out of Microsoft (anyone remember Petshop!?). Anyway it features all of the following:

  • Use of a domain-driven design techniques. Repository and Unit of Work abstractions over LINQ to SQL
  • Model-level validation using the Validation Block
  • Dependency injection using Composite Web Block
  • Using Lucene.NET to index a domain model
  • Using MVP with declarative data-binding in the presentation layer

Nice to see Lucene.NET being employed. As is NUnit. I’ll have a closer look when I get a chance. Expect some comments shortly.