Developing a Web Application with TDD and ASP.NET MVC, Part 1: Application Design

by Sekhat 17. December 2009 12:59

Introduction

I’m going to start a series about writing a web application using Test Driven Development and ASP.NET MVC. I’ll be learning as I go and this will basically be documenting what I learn as I learn it and hopefully in the end it will also be of some help to other people.

Defining the Application

Okay, so the application we’re writing here is a web app that allows Artists to showcase their work. It’s a simple application in concept, so lets define some basic functionality that is required, this functionality is simply the first bit of functionality we’ll implement to consider it our first release.

So basic functionality:

  • Artist can upload images to a gallery
  • Artists can create new galleries giving each a title and description
  • Artist can give titles to images
  • Artists can give descriptions to images
  • Visitors can view images that have been organized in to galleries.
  • Visitors can download images that have been marked as downloadable.
  • There is an about page that the Artist can use to describe themselves.

Some functionality that isn’t so basic, but is wanted for the initial release

  • Images viewed from website should have a watermark applied.
  • Downloaded images do not have watermarks applied.

Some implied functionality

  • Login system, so that visitors can be prevented from uploading images and administrating galleries.

And then some non functionality stuff that should be true

  • Simple and well structured HTML that allows easy customization of website via CSS.

Initial Design

So first we need to translate these requirements into some basic design. But we’re doing TDD, I hear you cry, that should do the designing for us. Well the answer is no, we need to a basic design first to at least get an idea where to start. Our design needs to be basic so that it can be flexible because TDD may cause our design to emerge differently, via throwing up problems or issues or code smells that we haven’t thought of at this stage.

So lets take a look.

Users of the site

We have an Artist and a Visitor in terms of users of the site, only an Artist will be logging in, in order to administrate the site. This means that the defining difference between a Artist and a Visitor, is that an Artist is logged in and a Visitor isn’t.

So in our code, we’ll call an Artist a RegisteredUser and a visitor is called a GuestUser. Doesn’t match our stories, but it makes more sense in terms of web applications and are terms everyone is familiar with.

Our Domain

While I don’t plan on learning Domain Driven Design here, as I believe this site is too simple for such an approach since DDD is a way to manage complexity and complexity isn’t something we really have, we do have a domain. This is the domain of Artwork.

From our functionality list we can see that we have a Gallery and an Image

A Gallery has a title and a description and contains many images.

An image has a title and a description and will need some reference to the image data.

We also need someway to store information about the artist. We’ll call this the artist’s Profile

Data Storage

Our information needs to be stored somewhere, so looking at what we have and with a small amount of thinking, we have two places where we’ll need to store our data.

The Database and the File System.

The database will store details about our Users (or user in this case), galleries, images and the artists profile.

The file system will store the actual images in the format of the files uploaded.

Recap

Where’s the code and tests? Well we haven’t done any yet but we’ve outlined some basic things that allow us to see the basic direction of the application and should help us in figuring out where to get started. This initial design stage is important, and we’ll be doing design stages again in the future when we come to sit down and start writing units of functionality. In my head our order of work should be: Decide on piece of functionality to write, Basic design of functionality, Write tests and code in a test first manner allowing them to cause our final overall design to emerge and repeat.

See you next time.

Databinding to ListControls, and fixing the peril of string assigned property names.

by Sekhat 11. September 2009 15:14

I came up with a solution today to a small little problem. The problem is when I'm data binding from a collection of objects to a list control.

myListControl.DataSource = myCollectionOfObjects;
myListControl.DataTextField = "Name";
myListControl.DataValueField = "ID";
myListControl.DataBind();

As you may (or may not know) what this will do is take myCollectionOfObjects, populates myListControl using the objects in that collection by making the ListItems value property equal to Name property on the object in the collection and the Text value property equal to the ID of the object.

Assuming my object is defined as so:

public class MyObject
{
    public int ID { get; set; }
    public string Name { get; set; }
}

and assuming the objects in myCollectionOfObjects have the following data:

IDName
1My Object 1
2My Object 2
3My Object 3
4My Object 4

I'd end up with this:

Which is all well and good. But the problem is back up with the C# code, I tell it which properties of my class I'm using for data binding via strings. This means there is no compile-time checking against those names and if those names change I won't know until runtime, when my lovely web-app crashes and burns spectacularly with a cryptic error message.

So I set about to resolve this, and I did, thanks to the wonders of extension methods, lamdas and expression trees.

I wrote the following extension class for ListControls:

public static class ListControlExtensions
    {
        public static void SetDataBindForList(
            this ListControl control, IEnumerable dataSource, Expression> textField, Expression> valueField)
        {
            control.DataSource = dataSource;

            SetDataTextField(control, textField);

            SetDataValueField(control, valueField);
        }

        public static void SetDataTextField(this ListControl control, Expression> textField)
        {
            var memberExpression = textField.Body as MemberExpression;

            if (IsProperty(memberExpression))
            {
                control.DataTextField = memberExpression.Member.Name;
            }
            else
                throw new ArgumentException("textField is not a property", "textField");
        }

        public static void SetDataValueField(this ListControl control, Expression> valueField)
        {
            var memberExpression = valueField.Body as MemberExpression;

            if (IsProperty(memberExpression))
            {
                control.DataValueField = memberExpression.Member.Name;
            }
            else
                throw new ArgumentException("valueField is not a property", "valueField");
        }

        private static bool IsProperty(MemberExpression memberExpression)
        {
            if (memberExpression == null ||
                memberExpression.Member.MemberType != System.Reflection.MemberTypes.Property)
                return false;
            
            return true;
        }
    }

Here I have three extension methods (and one private helper method) where the first method, SetDataBindForList, is used to setup the data binding and calls the other two to set the DataTextField and DataValueField respectively.

SetDataTextField is used to set the DataTextField if you want to do it by itself and likewise with SetDataValueField except it's for DataValueField.

The new code I write when I want to databind to a ListControl now is this:

myListControl.SetDataBindForList(
    myCollectionOfObjects,
    o => o.Name,
    o => o.ID);

Thanks to the type inference of the compiler this becomes one very simple call and it's checked at compile time for correctness on my field names. Pretty neat huh?

-- Edit: It appears my code plugin for blogengine.net is a bit silly with the whole formatting thing. I'll sort it out this evening. -- Edit 2: Tidy complete :)

Type Safe ViewState Retrieval

by Sekhat 30. August 2009 14:20

Often when I'm using the view state I'll have to code nice getters in my control or page to get me a value from the view state as the type I stored it in, for example:

public int PageCount
{
    get
    {
        object viewStateObject = ViewState["PageCount"];

        if (viewStateObject != null && viewStateObject is int)
        {
            return (int)viewStateObject;
        }
    
        return 0;
    }

    set
    {
        ViewState["PageCount"] = value;
    }
}

As you can probably guess this gets pretty damn repetitive once you have more than one item to retrieve from view state.

So I decided to create a couple of nice extension methods to help with this, here's the code:

    public static class StateBagExtensions
    {
        ///
        /// Gets an item from a state bag
        ///
        /// The type of item to retrieve
        ///
"stateBag" />The state bag to retrieve the item from
        /// "key" />The key of the item to retrive from the state bag
        /// The item retrieved from the state bag or the default value
        ///
        ///
        /// The default value is retrived using the default(T) call.
        ///
        ///
        /// The default value is only returned if one of the following conditions is met:
        ///
        /// The object for the given key does not exist in the state bag
        /// The object for the given key retrieves a null value from the state bag
        /// The object for the given key is not of the requested type
        ///
        ///
        public static T GetOrDefault(this StateBag stateBag, string key)
        {
            return GetOrDefault(stateBag, key, default(T));
        }

        ///
        /// Gets an item from a state bag
        ///
        /// The type of item to retrieve
        ///
"stateBag" />The state bag to retrieve the item from
        /// "key" />The key of the item to retrive from the state bag
        /// "defaultValue" />The value to use as the default value
        /// The item retrieved from the state bag or the default value
        ///
        ///
        /// The default value is only returned if one of the following conditions is met:
        ///
        /// The object for the given key does not exist in the state bag
        /// The object for the given key retrieves a null value from the state bag
        /// The object for the given key is not of the requested type
        ///
        ///
        public static T GetOrDefault(this StateBag stateBag, string key, T defaultValue)
        {
            object viewStateObject = stateBag[key];

            if (viewStateObject != null && viewStateObject is T)
            {
                return (T)viewStateObject;
            }

            return defaultValue;
        }
    }

Which means now my repetitive view state accessing properties now become:

public int PageCount
{
    get
    {
        return ViewState.GetOrDefault("PageCount", 0);
    }

    set
    {
        ViewState["PageCount"] = value;
    }
}

Which means accessing my viewstate is much simpler and also a hell of a lot DRYer.

Till next time :)