Thursday, 26 March 2009

ASP.NET MVC – More Than a Storefront

A project I’m currently working on is leveraging the newly released ASP.NET MVC Framework as the web presentation framework. The non-technical challenges of employing MVC are worthy of a whole post of their own, but the topic for this post is explaining an approach I’ve utilised to make the most of MVC in building scalable, testable web applications. When introducing new technology, the mention of those two terms alone is almost enough to appease the concerns of IT managers & decision makers... well, some anyway.

Structure

Being a fan of the Patterns & Practices guidance for application architecture, web applications are structured in the following manner.

Baseline Architecture:

Application Architecture

  • Client – Consumer application which renders content delivered by the web.
  • MVC Web Application – Web application which enables interaction by the client, processes requests and renders content.
  • Business Services – Services application which represents the business logic offered by the Web Application.
  • Protected Resources – Databases, web services, file systems, line of business systems, etc.

MVC Web Application Breakdown:

Web Application Breakdown

Where:

  1. The custom Controller Factory utilises Unity (configuration vs convention – you decide) for dependency injection driven Controller assembly. This concept is equally applicable to containers such as Spring.NET and StructureMap. The Controller Factory takes an argument of another Controller Factory as a fallback mechanism for creating a Controller.
  2. The Controller Factory resolves the Controller based on the controller name (as determined by the MVC Framework) and System.Web.Mvc.IController. If the Controller resolution fails, the fallback Controller Factory is called.
  3. Service Agents are injected into the controller when the Controller instance is resolved out of the container. Personal preference is via constructor arguments, but what ever works...

A policy I enforce in the application is that the web application does not have any direct access to the database or any other protected resource – everything goes through an Agent. Primarily, this has two purposes:

  1. The application enjoys the security benefits of N-tier deployment, and
  2. The application is services enabled by default. No need to attempt to retrofit services around complex class libraries after the fact.

For start-ups, this approach is ideal in that you can deploy your web and service applications on the one server communicating via named pipes (or net.tcp on localhost), keeping infrastructure costs to a minimum. As your application grows and is adopted by a wider audience, you can move your business services onto another host, and the impact on your application, theoretically, is merely configuration. From there on out, it’s the usual scale out/up story to beefing up the deployment.

Testing

Unit tests are written to target the Controller classes, in the same way unit tests are written to test any other form of business logic classes. The general way unit tests are employed are as follows:

  • Write at least one unit test per Controller Action. How many additional tests are written will vary based on the functionality offered by the action.
  • Mock out the behaviour of the Service Agent interface(s) based on expectations of the unit tests. My personal weapon of choice is Rhino Mocks.
  • Instantiate the controller with your mocked out agent(s) and execute the action in question.
  • At a minimum, make test pass assertions based on:
    • the type of Action returned
    • the presence (or absence) of validation errors in the model state
    • the content of the model returned with the view

With a number of UI targeting unit tests in your arsenal and included as part of your build acceptance, it can be proven that the UI will render and behave as expected when hit by a client with a browser.

Friday, 20 March 2009

Windows Live Writer + Custom Code Paste Plug-in = W00t!

When I started this blog, I figured that I’d use Windows Live Writer (WLW), under the banner of “you’re a .NET guy, so pimp out the MS technology, you brand whore”. And so far, I don’t mind what I see.

As a developer/architect, one of the things (hopefully) that will provide some value out of my blog posts is sample code. There are a few plug-ins for WLW available that do code formatting, but there are a few issues, particularly around the format of your code when posted to your blog host (in my case, Blogger). Line breaks in the source code in particular are treated badly when published.

My first attempt at posting code clips resulted in poorly formatted code (initially, anyway – it’s since been cleaned up), which annoyed me to no end. With a bit of digging around, I found a couple of blog posts that, when combined, give you code post joy.

Between the two of these posts, I was able to build something that solved my ugly formatting problems. From here on out, there shouldn’t be any formatting dramas.

Entity Framework & Many to Many Relationships

Using the Entity Framework? Got a many-to-many relationship between two entities?

Recently I’ve been working on a bit of code where there’s a many-to-many relationship between two entities, and I needed to remove the relationship between two entities (“it’s not you, it’s me… honest”).

Thankfully, the entity framework looks after the auto-mapping where the relationship is a standard M:N relationship.One entity appears as a collection on the other, and vice versa.

When inserting records, the process is relatively straightforward. But, as I found, removing the relationship isn’t quite as obvious.

To add the relationship:

public void AddItem1ToItem2(long item1Id, Guid item2Id)
{
    string connString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
    using(
MyEntities ctx = new MyEntities(connString))
    {
       
Item1 item1 = ctx.Item1s.Where(item1 => item1.Item1Id == item1Id).First();
        item1.Item2s.Add(ctx.Item2s.Where(item2 => item2.Item2Id == item2Id).First());
        ctx.SaveChanges(
);
    }

}

To remove the relationship:

public void RemoveItem1FromItem2(long item1Id, Guid item2Id)
{
    string connString = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
    using(MyEntities ctx = new MyEntities(connString))
    {
       
Item1 item1 = ctx.Item1s.Include("Item2s").Where(item1 => item1.ItemId == item1Id).First();
       
Item2 item2 = ctx.Item2s.Where(item2 => item2.Item2Id == item2Id).First();
        item1.Item2s.Remove(item2);
        ctx.SaveChanges(
false);
    }
}

Without the Include on the selection of item1 in the removal process, the Entity Framework does not load the related Item2 entities. Hence, when you call Remove, the list is empty, nothing is removed from the list, and the change tracking within the entity context does not recognise that anything’s changed. Therefore, when you call SaveChanges, no updates are done to the database.

Before I figured this out, I was trying a few different things, including loading up the entity on each side of the relationship and calling Remove on both entities to no avail.

If you’ve been trying to deal with a similar problem, with any luck, this will either a) save you time, or b) explain what you’ve been doing wrong and solve your problems.

Wednesday, 4 March 2009

First Post!

Most first posts are about the author – who they are, where they’re from, and what they intend writing about. And, I suppose, this one isn’t going to be too different.

In a nutshell, here’s the rundown:

  • My name’s Adam Schmidt, and I live and work in Sydney, Australia.
  • I’m a .NET solution architect working on a range of different projects, mostly relating to web- and service-based platforms.
  • I spend a lot of time working with patterns and practices, figuring out how they fit in building robust, scalable applications.
  • Team Foundation Server and Visual Studio Team System are my sandpit.

This is going to be as much a brain dump of what I read, learn, do, and discover. I suppose this will be as much a mental dump of “Notes to Self” as helpful topics for the greater .NET community.

Now… on with the show.