find a location for property in a new city

Monday, 20 June 2011

Azure SDK enable IIS 7.0 with ASP.NET support

Trying to install Windows Azure SDK and Windows Azure Tools for Microsoft Visual Studio on Windows 7 running IIS 7.5 throws an error that states, "... enable internet information services 7.0 with asp.net support ..."

I do not have IIS 7.0 - I am using IIS 7.5. Surely the Windows Azure SDK and Windows Azure Tools are compatible with 7.5 though? Well, they are! So why do I need IIS 7.0?

Well, you don't. The clue is in the message "with ASP.NET support." I needed to edit my IIS in control panel to do this.

Enabling IIS 7+ with ASP.NET

Go to Control Panel > Programs > Turn Windows features on or off.

Then find Internet Information Services. Expand it then go to World Wide Web Services, then Application Development Features and then check ASP.NET. This will check a few other dependent features and after a short wait should be able to run the installation for Windows Azure SDK again.

Follow britishdev on Twitter

Tuesday, 14 June 2011

Two bugs in ASP.NET MVC 3 and a workaround for both

So I spent an hour today arsing about with a couple of ASP.NET MVC 3 bugs. One was a Routing issue that caused it to act differently to MVC 2. The second I found was a FormsAuthentication issue that insisting on sending me to /Account/Login.

Amazing how this crept in really given that it was community tested to death with such a massive ASP.NET MVC following so it is a wonder they weren't weeded out and fixed before RTM. Oh well, don't pretend you don't like a challenge.

Routing doesn't work the same in MVC3 from MVC2

Here is an example of this bug in action

My current route is:
routes.MapRoute("groups", "groups/{groupSlug}/{action}/{id}/{urlTitle}",
                new
                {
                    controller = "groups",
                    groupSlug = UrlParameter.Optional,
                    action = "index",
                    id = UrlParameter.Optional,
                    urlTitle = UrlParameter.Optional
                });

I am using this route in an ActionLink like this (well obviously I've changed it for clarity - but I was totally using T4MVC!):
<%: Html.ActionLink(item.Group.Title, "index", new { groupSlug = "something" })%>

In MVC2 it that produces the URL /groups/something. But in MVC3 it produces the URL /groups?groupSlug=something.

MVC3 Routing UrlParameter.Optional workaround

I struggled with this for a good few hours, many a time exclaiming that, "my route IS there! What the hell is wrong with you?!" I took it apart piece by piece to discover that MVC3 no longer likes multiple UrlParameter.Optional's in a row.

A rather ugly workaround for this is to put in a new route for each of these problem routes that have no reference to the following UrlParameter.Optional's. So AFTER the above route you I need to put in another route like this:
//workaround for MVC3 bug
routes.MapRoute("groupsFix", "groups/{groupSlug}/{action}",
                new
                {
                    controller = "groups",
                    groupSlug = UrlParameter.Optional,
                    action = "index"
                });

Since writing this I have discovered it is a known issue and Phil Haack has a much better explanation than me! Obviously.

FormsAuthentication.LoginUrl is always /Account/Login

I have setup my forms authentication in web.config to register the LoginUrl as "~/login" but since upgrading to MVC3 it has decided to ignore that and now FormsAuthentication.LoginUrl returns "~/Account/LogIn" regardless of what I set in web.config.

There is a workaround for this though. You simply need to add this line to your AppSettings:

and everything works how it used to. Strangeness indeed.

Conclusion

Live with it. Fix up your errors as explained above and continue staying up to speed with ASP.NET MVC. It's worth it if even just for Razor alone.

Follow britishdev on Twitter

Monday, 13 June 2011

Adding MVC dependencies to a project for deployment

Deployment of new web applications has been a bit annoying since the birth of ASP.NET MVC. Production servers with .NET 4 or 3.5 installed will still be missing key assemblies such as System.Web.Mvc.dll. This will cause errors such as "Could not load file or assembly 'System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies" and "Could not load file or assembly 'System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies." when your project is deployed to production.

It is confusing for two reasons: Why does it work on your development machine? Well, when you install all the tools required to make MVC application you get all the necessary assemblies with it. Which assemblies are your production servers missing? Well there were 3 in ASP.NET 1, 1 in ASP.NET MVC 2 but now with ASP.NET MVC 3 + Razor there are loads. I've found out which ones I actually need before but it is still confusing.

With Visual Studio 2010 SP1 there is a new feature that does all the hard work for you. You can right click your ASP.NET MVC web application project and select 'Add Deployable Dependencies...':

Then you select the type of features you are using so Visual Studio can decide which references are needed:


It will then create a _bin_deployableAssemblies directory for you with all the assemblies included:


Now if you publish using Web Deploy it will include those files as expected and your deployed solution will be happy once more.

Important note:
If you are not using the 'Web Deploy' as your publish method though - this will NOT work. You will need to reference the assemblies and make them bin deployable yourself.

Follow britishdev on Twitter

Wednesday, 8 June 2011

Why WatiN tests are slow with the IE browser

I found opening and closing of the IE browser in WatiN a massive overhead when I was having to dispose of IE at the end of each of NUnit's tests. I found a way though to speed the whole process up.

I really wanted to open one instance of IE in my NUnit TestFixture and use that for the duration. This would save the huge huge cost of opening and disposing of WatiN's IE browser. As a sidenote it was a lot quicker in FireFox but since most users use IE best stick to that!

There were a couple of hurdles to jump to enable me to use just one IE browser for all my NUnit TestFixture's WatiN tests though.

1. Initialise and Dispose of IE at either end of the TestFixture

This is fairly obvious if you are familiar with NUnit. You just need to utilise the TestFixtureSetUp and TestFixtureTearDown attributes to initialise and dispose of your IE browser like so:
[TestFixture]
public class MyTests : IDisposable
{
    IE Browser;
 
    [TestFixtureSetUp]
    public void Init()
    {
        Browser = new IE();
    }

    [TestFixtureTearDown]
    public void Dispose()
    {
        if (Browser != null)
        {
            Browser.Dispose();
        }
    }

    ...

TestFixtureTearDown will run regardless of any fails in Assertions or even Exceptions so you can be confident that the browser will close on any unmaned CI machines.

2. Solving the weird STA problem (in NUnit)

You need to add to your app.config to ensure the tests run in an single thread apartment (STA) so that the non thread safe Internet Explorer browser can run safely.

I have written separately about how to solve the STA threading problem in Internet Explorer for WatiN.

The overhead of opening and closing the Internet Explorer browser should now be reduced to a one off. I have seen tests times of my NUnit powered WatiN tests reduce from 12 mins down to just 51 secs!

Follow britishdev on Twitter

ThreadStateException thown in WatiN with Internet Explorer

I was using NUnit to Assert some responses from a suite of WatiN tests whilst using the IE browser. Running them caused a ThreadStateException with an error message of 'The CurrentThread needs to have its ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer'

Internet Explorer is not thread safe so WatiN should use a single threaded apartment (STA). To ensure you abide by this WatiN will throw a ThreadStateException if it is not. This can be rectified by setting the ApartmentState to ApartmentState.STA as the error message suggests for Internet Explorer.

How set your CurrentThread to ApartmenState.STA for WatiN in NUnit

If you've haven't already create an App.config in your NUnit testing assembly. You will need to add the following to it:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
   <sectionGroup name="NUnit">
    <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
   </sectionGroup>
  </configSections>
  <NUnit>
   <TestRunner>
    <!-- Valid values are STA,MTA. Others ignored. -->
    <add key="ApartmentState" value="STA" />
   </TestRunner>
  </NUnit>
</configuration>

If you are having problems with different runners other than NUnit you can find tips on how to set STA on them too.

Follow britishdev on Twitter