Publishing an MVC site to load balanced servers

The purpose of this post is just a few notes to remind me of the steps I followed yesterday when publishing an MVC site to our load balanced servers.

We have three web servers and our hosting company controls the load balancing for us. So, it’s possible that some of the solutions that worked for me might not work for you.

When I first created the website I simply had one simple html page. Checking this page in a browser at first worked but after a refresh showed a 500 error, which took me by surprise. I refreshed the page several times, sometimes it would display, other times the 500 error was shown. The problem here was permissions. Using IIS on one of the servers I went to the site, clicked on Advanced Settings and added the correct account in the Physical Path Credentials. Now, anonymous users coming to this site use this account’s permissions as a proxy. That last sentence sounds complicated but it explains (at least to me) why this step needed to be taken.

I was then ready to publish the actual site, which I did using the Publish facility in Visual Studio. All the files went across but when I tried the site I saw an error saying that it couldn’t find the System.Web.Helpers DLL. My first thought was I just put this in the GAC but then I thought this could be due to MVC not being installed on the server. I found this post by Josh Gallagher, which details quite nicely how to ‘Add Deployable Dependencies’. Doing this meant my site was up and running and I didn’t need to re-start live servers (which simply was not an option!). I also added the <identity> key to my web.config so as my site can access the data stores to get the necessary information.

However, all was not over. My MVC site uses Forms Authentication and I found that whilst I could log in, every so often when I clicked on a link I was being prompted to log in again. This made me think that I was being authenticated on one server but when the load balancer switched me to a new server I needed to go through the process again. The way to solve this problem was to add a <machine key> setting to the web.config file. This has various attributes: the validationKey decryptionKey, validation and decryption. Setting these values and adding this key to the config file solved the problem. So, I could now log in and move around the site regardless of which server was serving the content.

The next problem was more specific to my application. I am using an ASPX page, which has a Microsoft ReportViewer control. During development I did try and see if I could host this within MVC but that didn’t seem possible. Steps that needed to be taken here was making sure the identity my site uses has permissions to see the reports on the report server and adding another setting to the web.config. This time the <sessionState> key. Again this was needed because of the site being on load-balanced servers and getting the message ‘ASP.NET session has expired or could not be found’. After all that I put my feet up and had a cup of tea!

Migrating TeamCity from its internal database

When I first installed TeamCity, a continuous integration tool from JetBrains, I went with its default setup, which uses its internal database to keep track of builds and so on. TeamCity displays a warning that the internal database should only be used for evaluation and that if using TeamCity for production purposes it highly recommends using an external database.

This is a task that’s needed doing for a while but I’ve not really been looking forward to it. Finally, today I bit the bullet, grasped the nettle, and every other cliche (and like the readers of this sentence are wishing) got on with it!

As we’ve been using TeamCity now for five months there is quite a bit of data that I didn’t want to lose so I wanted to migrate the data. The instructions are quite detailed and I feel can cause a bit of confusion but basically there are three steps to follow.

  1. Create an external database. For me this was Microsoft SQL server, version 2008 R2. In Management Studio I created a new database called TeamCity and a new login. I right-clicked on the new login, selected properties and mapped the user to this new database.
  2. I then downloaded the native driver for SQL Server for TeamCity to use. I got the MS sqljdbc package from Microsoft. The extension said it was an exe but it is a zip file. Un-packing it I put the sqljdbc.jar into the correct folder following the TeamCity instructions
  3. Then again following the instructions I created a database.properties file putting in the appropriate values. Make sure you look closely at the typing since I had some problems running the maintainDB tool when it couldn’t find the correct driver.
  4. Shut the teamcity service down.
  5. I then needed to run the maintainDB tool to move data into the new database. I had some problems here. The instructions explicitly state that you only need to specify two arguments: -A and -T. However, you also need to specify the source. Thankfully I found this post and the excellent comments by my namesake . Once I specified the three arguments then I could run maintainDB with no problems.
  6. Re-start the TeamCity service and see it pick up the new settings.

I suspect that a few more times doing this and it won’t feel so daunting.

 

Using Generics

A while ago on StackOverflow I asked a question about what problems could be solved using generics. I had read a lot about generics and use Lists a lot but I personally for a good long while hadn’t used them.

Recently I started looking at http://valueinjecter.codeplex.com/ to use for DataMapping and ended up developing the following service to help me in my code. This is a fairly good use of generics I feel. What the service is doing is taking two objects: a target and a source. It then copies the values from the target into the source.

using System.Collections.Generic;
using Omu.ValueInjecter;

//Uses http://valueinjecter.codeplex.com/ to do the mapping

namespace MyVee24.Services {

    public interface IDataMappingService<T, K> where T : class
                                                                                  where K : new() {
         K Map(T storeDept);
         List<K> MapList(List<T> dataStoreDepts);
    }

    public class DataMappingService<T, K> : IDataMappingService<T, K> where T : class
                                                                                                                                   where K : new() {

        public K Map(T source) {
K target = new K();
target.InjectFrom(source);
return target;
}

        public List<K> MapList(List<T> sourceList) {
List<K> targetList = new List<K>();
foreach (T item in sourceList) {
targetList.Add(Map(item));
}

            return targetList;
        }
    }
}

I’m posting this as a handy reference, mainly for myself.

P.S: Apologies for the lousy formatting. I’ll try and find time to learn how to format code samples nicely in WordPress