Friday 26 April 2013

Don’t reinvent the wheel; use the tools provided

Every so often I read a blog post and most of the time it’s interesting and the ideas it’s trying to portray are good however it’s the small snippets of code in them which can start to annoy me. It’s usually the little things such as re-writing functions which the .net framework will do for you.

One of the biggest culprits is when you have an array of strings, usually role names in user management, and you want a single comma separated string of them. I’ve seen for loops, for each loops, …. don’t think I’ve seen a while implementation yet. I’ve seen variations on a theme for the internal loop logic as well but still you get the idea and you end up with something like:

var roles = string.Empty;
for (var index = 0; index < Roles.Length; index++)
{
    roles += Roles[index];
    if (index != Roles.Length - 1)
    {
        roles += ",";
    }
}
return roles;

Now, it’s syntactically correct and yes it does what is required and yes this is a personal frustration of mine so I’m not pointing to anyone specifically but unless you’re doing something else in the code why not use string.Join and reduce it to …

return string.Join(",", Roles);

If we can start blogging code which harnesses the power of the frameworks we’re using then hopefully we can pass on this experience and techniques to newer developers and we can start to not reinvent the wheel, write more robust code and concentrate on the fun stuff.

Wednesday 24 April 2013

Tournament – Learning to CRUD

This is the 3rd part of a series that is following my progress writing a sporting tournament results website. The previous posts in this series can be found at:

In the previous post I explained the setup that I will be using for my project. In this post I will go through the basic CRUD operations and interesting routing issues which I found to get the setup I was looking for.

What do I want to achieve?

By the end of this post I will show you how I have managed to sort out the CRUD operations for a simple Entity object including working with RavenDB to get auto incrementing identifiers. I will also describe the tweaks to the default routing definitions to allow for the url pattern I want to continue to work with for the public urls.

Should your Entity be your ViewModel?

After my post the other day about your view driving data structure I decided to put in ViewModel / Entity mappings after originally writing the CRUD setup straight onto both my Team and Player entities. I didn’t like the fact that there were DataAnnotations in my data model so I refactored it to use ViewModels instead to avoid this “clutter” and keep the separation between View and Data. To aid in the mapping between the two types I Nuget’ed down AutoMapper.

To keep with the default pattern of everything which is required by the application being setup in Global.ascx.cs in Application_Start but done through calling static methods into specific function classes in App_Start I created an AutoMapperConfig class with a static register method (see below).

public class AutoMapperConfig
{
    public static void RegisterMappings()
    {
        // Team
        Mapper.CreateMap<Team, TeamViewModel>();
        Mapper.CreateMap<TeamViewModel, Team>();

        // Location
        Mapper.CreateMap<Location, LocationViewModel>();
        Mapper.CreateMap<LocationViewModel, Location>();

        // Player
        Mapper.CreateMap<Player, PlayerViewModel>();
        Mapper.CreateMap<PlayerViewModel, Player>();
    }
}

With doing this I can keep all my mappings in a single place and it won’t clutter the Global.ascx.cs with unnecessary mess.

Auto incrementing Ids

The default setup for storing documents in RavenDB is using a HiLow algorithm. However this does not give the auto incrementing id functionality I’d like. Why will this not do? Well the id makes up part of the url route linking to the individual entity and I want to keep that as sequential and not dot about. The default ID creation would be fine for Ids which aren’t exposed to the public but they will be in this application.

Thanks to the pointers from Itamar and Kim on Twitter I was able to achieve the desired effect without much trouble at all. In the create method on the TeamController when storing the data I had to call a different override to the Store method and specify the collection part of the identifier to use.

RavenSession.Store(team, "teams/");

And that was it.

Routing setup

There was two issues when it came to routing; accessing the record for admin functions and accessing the details of a specific entity to keep with the routing in the current site. Default RavenDB ids are made up of the collection name of the document and the id eg “teams/2”. To get Asp.net MVC to understand these the controller actions which accept an id need to be changed from int to string

public ActionResult Edit(string id) { .. }

And the default route gets updated as follows:

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

On a brief look it might not look like anything has changed however the {id} part of the url has been updated to {*id} to allow for anything before the id part – this will allow the Raven DB default collection based indicators to match eg. teams/2

The next part was the public routes to see the details of the different entities. Let me explain this a bit further. The default url to access teams is /team and for a specific team I want to have a url which follows the url pattern of /team/{id}/{slug} eg /team/1/team-name-slug-here. This is to partially aid with SEO but also make the urls more human readable when posted on forums, twitter etc.

This can be established using the following route:

routes.MapRoute(
    name: "EntityDetail",
    url: "{controller}/{id}/{slug}",
    defaults: new { action = "detail", slug = UrlParameter.Optional },
    constraints: new { id = @"^[0-9]+$" }
    );

The constraint is to limit the matching to integer values only – remember routes match from specific to general. We want to limit the restriction to just this url pattern only.

The next hurdle to over come was the issue with the raven DB identifier which includes the collection name (eg teams/2 or players/5), all I want is the integer part to make up the url and hence match the url route pattern which we defined above. To do this I wrote a small extension method which works on a string. It’s very basic, see below. 

public static string Id(this string ravenId)
        {
            var split = ravenId.Split('/');
            return (split.Count() == 2) ? split[1] : split[0];
        }

This will allow me to reference the identifier properties on my view models however be able to access the integer part of it to setup the route for the entity specific none admin views. So how do we use this?

<viewModel>.Id.Id()

Conclusion

In this post I have shown how to setup the basic mappings between entities and view models. In addition to this I have shown how I made Raven DB play nice with sequential incrementing identifiers. I have also discussed the current routing requirements and how to extract out the integer identifier part of a Raven DB collection identifier to be able to set these as required.

In the next post I will briefly discuss how I am planning on saving match results and take a look at the first attempt at using indexes in Raven DB to calculate each players results.

As always you can follow the progress of the project on GitHub. Any pointers, comments, suggestions please let me know via Twitter or leave a comment on this blog.

Monday 22 April 2013

Tournament – Project Setup

For the first few iterations of this project it will be based in a single Asp.Net MVC 4 Internet Web Application. This can be found through the regular File > New process in Visual Studio. I may at some point decide to break it up into different projects but at the moment I don’t see an immediate need and don’t want to over complicate it at the beginning.

Once Visual Studio has setup the project and is happy then it’s time to add in the required packages to use RavenDB. Most of the development will be done using just the client RavenDB functionality as I have a RavenDB server running locally however when I get close to deployment I will create it so that it can either run with a dedicated server instance or in an embedded way.

The NuGet packages which I have installed are the following:

<package id="RavenDB.Client" version="2.0.2261" targetFramework="net40" />
<package id="RavenDB.Client.MvcIntegration" version="2.0.2261" targetFramework="net40" />

These give us the basics required to get the data access rolling as well as a way to start profiling what is going on.

I’ve decided to go for the setup of having the DocumentStore instance setup in the Global.ascx.cs on Application_Start and then create a session on each action call via a BaseController and finalise at the end of the call of each action. After some Googling this seems to be a simple and common way to setup a RavenDB session, avoiding DRY situations and I read somewhere (can’t remember where) that creating a session is relatively inexpensive processing wise. If this changes or I find an issue with performance then I may need to come back to it.

The base controller is very simple …

public class BaseController : Controller
{
    public IDocumentSession RavenSession { get; protected set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        RavenSession = MvcApplication.Store.OpenSession();
    }

    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.IsChildAction)
            return;

        using (RavenSession)
        {
            if (filterContext.Exception != null)
                return;

            if (RavenSession != null)
                RavenSession.SaveChanges();
        }
    }
}

Now we’re ready to roll!

As always you can follow the progress of the project on GitHub. Any pointers, comments, suggestions please let me know via Twitter or leave a comment on this blog.

Thursday 18 April 2013

My Journey with Asp.Net MVC and RavenDB – Introduction to Tournament

The idea of this journey is based on a number of reasons. The main two are to learn how to use and work with RavenDB, focusing the usage in an Asp.Net MVC context and the other is to re-work a site which has been live for the past 4 years which has had minimal change over that time and needs a refresh and admin functionality.

I have chosen to use RavenDB as the backend of this system due to the nature of how the data is stored. The site is a sporting results site so once an event has taken place the results will not change. They may need some tweaking while entering them but once in and confirmed they won’t change. Due to this a relational database I feel isn’t the best fit for the data. Reading and speed of reading the data is the main function. The current site calculates scores on the fly all the time where as this isn’t required due to the previous reason of once the results are in they’re in.

I have decided to post the code onto GitHub during the development so the world can see how I’m progressing. I will also be posting about what I have learnt, what issues I’ve come across and how I’ve over come them. Also I believe it’s a good way to show case of what I am capable of. This series won’t be a step by step walk through but I hope with looking at the code and the description of the main parts in the blog it should aid others in how to get up and running.

Any pointers, comments, suggestions please let me know via Twitter or leave a comment on this blog.

Let’s start the journey ….