Oct 22 2009

Learning Bourne – Tiered CRUD Part I

Category: AlexRobson @ 06:00

If the title confuses you, read about the Bourne Framework here.

The first demo I thought I’d throw together is a tiered ASP.Net MVC application which uses a tender-flakey WCF service layer baked right in. I’m calling it Tiered CRUD because it’s a simple CReate Update Delete application that’s contrived as can be. You should absolutely, under no circumstances expect anything mind-blowing or spectacular about this application. It’s not trying to be best practice, it’s just demonstrating the nice stuff Bourne can do for you.

Solution Structure
4 projects:

  • tieredCrud – the ASP.Net MVC “web site”
  • crudServiceHost – the IIS hosted WCF service host
  • crudServices – the WCF service implementations
  • crudContracts – the service/data contract definition library

Ok, so I said it’s not best practice and it’s not, but I also wanted to separate things out just enough so that you can see how the configuration would work in a slightly more complex example. Because I really, really, really dislike when I get examples that only show the most simple possible scenario and leave you to figure out how the heck you’re supposed to handle something with more moving parts.

Starting Small – Today’s Objective
We’re going to start, very, very small. You’ll see why. Just getting started will actually cover a lot… I hope you’re not sleepy :) The first thing we’re going to do is get a baseline configuration for our service host and MVC app. Then we’ll make a drop-dead simple service and show how we can consume the service on the MVC side without any obnoxious proxy generation.

Step 1 – Setup the contract
In the crudContracts project, add an interface called IGreet that looks like this:

using System.ServiceModel;

namespace crudContracts
{
    [ServiceContract]
    public interface IGreet
    {
        [OperationContract]
        string Greet();
    }
}

See? Very simple.

Step 2 – Create The Service Implementation
In the crudServices project, add a reference to crudContracts (where the service contract was just defined). Now add a class called Greeter.cs that looks like this:

using crudContracts;

namespace crudServices
{
    public class Greeter : IGreet
    {
        public string Greet()
        {
            return "Welcome to the Tiered CRUD demo!";
        }
    }
}

It really doesn’t get easier than this. Honest.

Step 3 – Plugging The Service Into The ServiceHost
The service host application is a WCF Service Application. If you’re unsure what that is or where you can find it, I’ve included a screen shot of where you can find the project template:

 image

Ok, so here’s where we start implementing Bourne. You’ll need to reference the following assemblies:

  • BourneFramework.dll
  • BourneFramework.WCF.dll
  • StructureMap.dll

The next thing we’ll need is an implementation of a BourneServiceHostFactory. So, add a class called ServiceFactory.cs to the crudServiceHost project and add the following code:

using BourneFramework.Logging;
using BourneFramework.Wcf;
using crudContracts;
using crudServices;
using StructureMap;

namespace crudServiceHost
{
    public class ServiceFactory : BourneServiceHostFactory
    {
        public ServiceFactory()
        {
            ObjectFactory.Configure(
                config =>
                {
                    config.ForRequestedType<IGreet>().TheDefaultIsConcreteType<Greeter>();
                });
        }
    }
}

Let’s talk this through so it’s clear what’s happening. ObjectFactory is the StructureMap class used to configure and retrieve dependencies. I’m configuring StructureMap so that when an IGreet instance is requested, the implementation provided will be the concrete type Greeter. The ServiceFactory class is what our WCF Service Host will use to create new instances of our service. This is important because, down the road, as we add dependencies to our services, we’ll want to provide StructureMap with an opportunity to supply those dependencies during service instantiation. For now, this may not make a lot of sense to you because the Greeter service has no dependencies.

Step 4a – Create The Service EndPoint
The next thing you need to do is create a service endpoint. The first part of this is creating an .svc file in the crudServiceHost project. We’ll name it Greeter.svc and it should contain the following markup:

<%@ ServiceHost Language="C#" Debug="true" Factory="crudServiceHost.ServiceFactory" Service="crudServices.Greeter, crudServices" %>

If you’ve never created a WCF service like this before, this may seem a little strange. Let’s briefly talk about each of the attributes above. Factory tells the WCF Service Host what class it should be requesting the Service instances from. If you were creating a simple WCF service from scratch, and you looked at the markup for your new service, you wouldn’t see this attribute because ServiceHostFactory is used by default to create service instances in response to incoming requests.

The service attribute tells WCF where to find the concrete class that implements the service contract. Since this class is in another assembly, you’ll notice that I’ve had to use an assembly qualifier at the end of the full service name.

Step 4b – Configure The Service EndPoint
I’m not going to go into a lot of depth here primarily because there are a lot of sources that deal specifically with how to configure WCF service endpoints and there’s nothing in the service endpoint that has anything to do with Bourne. Here’s the configuration you need:

<system.serviceModel>
    <services>
        <service behaviorConfiguration="crudServiceHost.GreeterBehavior" name="crudServices.Greeter">
    <endpoint address="" binding="basicHttpBinding" contract="crudContracts.IGreet">
                <identity>
                    <dns value="localhost"/>
                </identity>
            </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">          
    </endpoint>
        </service>
    </services>
    <behaviors>
  <serviceBehaviors>
            <behavior name="crudServiceHost.GreeterBehavior">
                <serviceMetadata httpGetEnabled="true"/>
                <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

Ok. That’s it. You should now be able to run this service, navigate to the Greeter.svc endpoint and see the nice wsdl page in response:

image 

Step 5 – Configuring MVC For Bourne
Add the following references to your ASP.Net MVC application:

  • BourneFramework.dll
  • BourneFramework.Mvc.dll
  • StructureMap.dll
  • crudContracts.dll (this is a project reference)
  • log4net.dll

In the Global.asax.cs of your MVC application, change your application so that it inherits from BourneHttpApplication. Then add a constructor with the following code:

public MvcApplication()
{
    ObjectFactory.Initialize(init =>
                             {
                                 init.AddRegistry(new ServiceClientRegistry());
                                 init.Scan(scan => scan.Assembly(typeof (HomeController).Assembly));
                             });
    ServiceClientFactory.RegisterConfigurationDelegate<IGreet>(c => c.MetadataExchangeAddress = “http://localhost:46192/greeter.svc?wsdl”);
}

Let’s go over what’s happening here. First off, you’re adding the ServiceClientRegistry to StructureMap. It’s not anything terribly fancy, it’s basically registering some Bourne dependencies with StructureMap so you won’t have to do it later. Next, we’re telling StructureMap to scan our MVC application for dependencies. The reason to do this is, just like we did for the WCF Service Host application, we’re telling StructureMap how to instantiate our controllers so that it will get the opportunity to provide dependencies to our controllers. Unlike the WCF Service Hose app, we’re actually going to take advantage of that in this post.

The last line is telling Bourne how to configure the IGreet client service. Because we’ve exposed a Metadata Exchange endpoint (abbreviated MEX forever-more), Bourne will create service client proxies for us on the fly without the need for yucky generated proxy cruft. Maybe that’s not your style, but this is one of my favorite things. It also allows you to get the instances through DI and will ensure they’re properly disposed of so you don’t have to remember the annoying close-this-if-it’s-not-faulted-abort-it-if-it’s-faulted-but-if-an-error-occurs-catch-and-abort pattern.

Step 6 – Add The Service Dependency To The Home Controller
To add the dependency, drill down to the HomeController.cs and add the code below.

private IService<IGreet> _greeter;

public HomeController(IService<IGreet> greetService)
{
    _greeter = greetService;    
}

This is adding a dependency on IService<IGreet> which is the interface Bourne uses to create the dynamic WCF service client proxies. What will happen behind the scenes is when MVC goes to instantiate the controller to handle the client request, it will look at the StructureMap configuration to get an instance of IService<IGreet>, the proxy will then use the configuration Action we provided in our MvcApplication constructor to tell the proxy “Get the metadata you need to build this proxy from the MEX at this URI”, the proxy will pull the metadata down, configure itself and then the IService<IGreet> instance will be passed onto our HomeController.

Step 7 – Call The Service
To do this, change the code in the Index() action to this:

public ActionResult Index()
{
    ViewData["Message"] = _greeter.Call(c => c.Greet());

    return View();
}

That’s it. You’re done. When you F5 your MVC Application now, you should see the following:

image

Wrap Up
Now, I know that probably seems like a whole lot of work to get the text on your page to change. But the thing to remember here is that a lot of the work we did today will be built upon in the coming tutorials. I wanted to start out with the simplest possible thing I could thing of that would demonstrate how Bourne works with both MVC and WCF to (hopefully) make your life a lot simpler.

Caution
The dynamic WCF proxy feature is very light-weight. It’s not super-full featured with a lot of whiz-bang. As I need to add additional configuration to it, I will (that means ask and ye shall receive) but for now, it works really well for simple internal WCF services.

Coming Soon
The next thing we’ll do is add in the really powerful NHibernate integration. This is where Bourne is indispensible and where Evan has spent most of his time (and it shows).

Tags:

blog comments powered by Disqus