Random Code

May 29, 2008

Making session variables a little easier to work with

Filed under: WebForms, c# — Neal @ 8:35 am

It’s been quiet on here for a while - that’s because I’ve been warped back to WebForms land where everything is craziness and it takes you half a day just to figure out wth is going on because you have to work with logic spread across a half dozen code behind files that all run to a couple thousand lines (no exaggeration!).

The app I am currently working on uses session variables a lot, and doesn’t clean them up very often, leading to odd behaviors due to stale state (among other things).

The first thing I do when I come across a page using session variables is extract them all into properties at the top of the page - this ensures those ugly string indexers are only in 2 places (the get and set) and you only have to write the cast once.  The problem I find with this is that to figure out if the session variable has a value or clean up the session variable I still have to address it using the string indexer, sure I can wrap that in a simple method call so I only have the indexer in 3 or 4 places, but when you have a page with 6 session variables, this starts to add a lot of cruft to the code behind.  What I really wanted was a simple way of adding a few methods to the property so I could do something like this…


int newValue = 0;
if( MySessionVar.HasValue )
{
  newValue += MySessionVar;
}
MySessionVar.Clear();

With a little bit of poking around, some generics and a simple implicit cast, I ended up with this:


using System;
using System.Web;

namespace Blog.Code
{
    ///<summary>
    /// Wraps a number of convenience methods around session variables allowing for a more fluent
    /// expression of the intent.
    ///</summary>
    ///<typeparam name="T">The type of the value to store in the session.</typeparam>
    public class SessionVariable<T> : IEquatable<SessionVariable<T>>
    {
        private readonly T _tempValueStore;
        private readonly string _sessionKey;

        ///<summary>
        /// The stored value or the default value for the type
        /// if there is no value associated with the sessionkey
        ///</summary>
        public T Value
        {
            get
            {
                object value = HttpContext.Current.Session[_sessionKey];
                if(value == null)
                {
                    return default( T );
                }

                return (T)value;
            }
        }

        ///<summary>
        /// Indicates if there is a value stored.
        ///</summary>
        public bool HasValue
        {
            get
            {
                return HttpContext.Current.Session[ _sessionKey ] != null;
            }
        }

        ///<summary>
        /// Creates a new SessionVariable to access the value stored in <paramref name="sessionKey"/>
        ///</summary>
        ///<param name="sessionKey">The key used to access the value in the session</param>
        public SessionVariable( string sessionKey )
        {
            _sessionKey = sessionKey;
        }

        ///<summary>
        /// Creates a new SessionVariable to store the value provided.
        ///</summary>
        ///<param name="value">The value to store.</param>
        /// <remarks>
        /// Value is not stored until <see cref="Store"/> is called.
        /// </remarks>
        public SessionVariable( T value )
        {
            _tempValueStore = value;
        }

        ///<summary>
        /// Stores the value in the session using the key specified.
        ///</summary>
        ///<param name="sessionKey">The key used to store the value.</param>
        public void Store(string sessionKey)
        {
            HttpContext.Current.Session[ sessionKey ] = _tempValueStore;
        }

        ///<summary>
        /// Removes the entry from the session.
        ///</summary>
        public void Clear()
        {
            HttpContext.Current.Session.Remove( _sessionKey );
        }

        ///<summary>
        /// Implicitly converts the specified value into a SessionVariable instance.
        ///</summary>
        ///<param name="value">The value to convert.</param>
        ///<returns>A SessionVariable instance holding the specified value.</returns>
        public static implicit operator SessionVariable<T>(T value)
        {
            return new SessionVariable<T>( value );
        }

        ///<summary>
        /// Implicitly converts the SessionVariable back to the type of the wrapped value.
        ///</summary>
        ///<param name="sessionVariable">The SessionVariable to convert</param>
        ///<returns>The wrapped value.</returns>
        public static implicit operator T(SessionVariable<T> sessionVariable)
        {
            return sessionVariable.Value;
        }

        public override string ToString()
        {
            return Value.ToString();
        }

        public bool Equals( SessionVariable<T> sessionVariable )
        {
            if ( sessionVariable == null )
            {
                return false;
            }
            return Equals( Value, sessionVariable.Value );
        }

        public override bool Equals( object obj )
        {
            if ( ReferenceEquals( this, obj ) )
            {
                return true;
            }
            return Equals( obj as SessionVariable<T> );
        }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }
    }
}

Which can be used like this:


protected SessionVariable<string> SuccessMessage
{
    get
    {
        return new SessionVariable<string>("SuccessMessage");
    }
    set
    {
        value.Store("SuccessMessage");
    }
}

The only caveat is when accessing methods on the object you are wrapping, you have to use 1 of 2 approaches to get at the underlying value…


// Directly access the underlying value
SuccessMessage.Value.Split(...);

// Assign the wrapped value to a temporary variable to force the implicit cast
string successMessage = SuccessMessage;
successMessage.Split(...);

As the session is really just a Dictionary<string, object> you could probably make this work for any dictionary with a few simple changes, however I didn’t need that flexibility so I leave it as an exercise for the future.

May 14, 2008

You know you are working on bad code when …

Filed under: General — Neal @ 9:59 am
  • There’s more orange in ReSharper’s gutter than there is grey.
  • Code analysis for the current file takes longer than solutionwide error analysis of your last “good” project.

I’m back to working on legacy code written by hamfisted monkeys with little regard for anything vaguely related to good coding practices - 2500+ line codebehind classes anyone!?!

Feel free to add other “You know you’re working on bad code” signs in the comments - I’m in desperate need of a laugh :s

May 2, 2008

Saying thanks…

Filed under: General — Neal @ 3:48 pm

For the past couple of months I have been building a web based surveying application designed to allow employers to carry out lifecycle surveying of their employees (e.g. when they start, annual reviews, exit surveys).  When I started building this application, I was given complete control over how it was to be built and I chose to use MonoRail.  After a while I integrated Windsor, NHibernate and Rhino.Commons.  All of my unit tests have been written using NUnit.

After spending the previous 5 or so years fighting working with ASP.NET and various incarnations of MVP and MVC, hand writing data access code and stored procedures and not really leveraging any kind of dependency injection, using this stack has been bloody marvelous and a true breath of fresh air.  The learning curve is steep but rarely treacherous, and there is plenty of support in the community.  Even better,  I can peer into the inner working to see why something is (or isn’t) working.

To list all the contributors to those projects would require a rather long blog post (although you all deserve a huge round of applause), but there is generally one or two people who are “responsible” for these projects and spending large amounts of time and effort keeping them going.  So here’s a thank you to Hamilton Verissimo aka Hammett for the Castle stack ( MonoRail / Windsor and a whole lot more );  Karl Chu and Sergey Koshcheyev for NHibernate; Oren Eini aka Ayende for Rhino.Commons ( although his name appears a lot in conjunction with both Castle and NHibernate ); and Charlie Poole, Jamie Cansdale and Gary Feldman for NUnit.

All of these projects are the results of a large number of people donating their time and expertise, so I just wanted to throw a resounding THANK YOU! out into the ether in the hope that they might see it and know my gratitude.

MonoRail, Prototype validation and multiple submit buttons

Filed under: MonoRail, Prototype — Neal @ 2:50 pm

Previously I have discussed how I added action level filters to allow me to drop a cancel button on the page and worry about how the cancel was handled in the controller. This worked fine and did exactly as what I needed until I added client-side validation to the pages, the cancel button (being a submit button) triggered the validation.  To stop my cancel buttons triggering the validation I stopped the validator from automatically firing when the form was submitted by adding the following to the FormTag call:

$Form.FormTag( "%{action='processform', on_submit='false'}" )

To reconnect the validation and only validate the form if the button was not a cancel button, I used the following javascript that relies on the Prototype scripting library (I am using version 1.6.0.2).


/*
    Allows form validation while enabling the use of a submit button to
    cancel the page.
*/

// Register the validators once the form has loaded
Event.observe(window, 'load', RegisterValidationEventHandlers);

function RegisterValidationEventHandlers( event )
{
    if (window.prototypeValidators)
    {
        validatorsHash = $H(window.prototypeValidators);
        validatorsHash.values().each( function(value, index) {
            Event.observe(value.form, 'submit', validateFormIfNotCancelButton.bindAsEventListener(this));
        } );
    }
}

// Check if the event originated from a "cancel" button, if not proceed with normal validation
function validateFormIfNotCancelButton( event )
{
    var buttonClicked = document.activeElement || event.explicitOriginalTarget;
    var eventElementName = Element.readAttribute(buttonClicked, 'name');
    if(eventElementName != 'cancel' ;)
    {
        var validator = prototypeValidators[event.element().id];
        validator.onSubmit( event );
    }
}

This first line registers an event listener on the window load event and executes the RegisterValidationEventHandlers function.

The RegisterValidationEventHandlers function checks for the existence of an associative array called prototypeValidators (automatically created by the PrototypeWebValidator) and if it is present, loops through attaching an event listener to the submit event for each form that has a validator. Note: for this to work, you will need to patch your PrototypeWebValidator as it currently creates an associative array from a normal array which is considered bad practice (see http://support.castleproject.org/browse/MR-440 for details).

The actual validation code is reasonably simple, retrieve the element that caused the event to fire, check it’s name and if it is not cancel, delegate the validation to the Prototype validator. The one interesting point to note is that there is no consistent mechanism to get the element that initiaited the submit, hence the var buttonClicked = document.activeElement || event.explicitOriginalTarget; which works in IE (document.activeElement) and FF (event.explicitOriginalTarget).

This script will work so long as you are using the default validation provider for MonoRail (prototype / dexagogo) and supports multiple forms without the need to add anything beyond suppressing the validation on submit behaviour via the additional property in the FormTag call.

April 21, 2008

Avoiding the D’oh (aka assumptions are bad)

Filed under: Uncategorized — Neal @ 12:02 pm

I’ve just had one of those d’oh moments, if only I had written a unit test for 1 simple constructor I would have saved myself about 3 hours of pointless frustration.

I am currently integrating NHibernate into my current project, which basically means I am writing a lot of mapping files. Having never used NHibernate before I don’t have that invaluable store of wisdom built up from previous implementations - so I am relying on some very simple unit tests to make sure my mapping files are correct.

The problem came about when I was trying to map a collection of value types (EmploymentDetails) that hold the details of the entities (Employee) employment history over time (essentially what store they worked in when).  While I was looking at the domain object I realised I could clean it up a little and make it express the intent more correctly as well as a little more efficiently, so I quickly hacked together the changes and carried on building the mapping file - BIG MISTAKE.  No tests were written, it was only a simple rename and move a couple lines of code around in the constructor right?  WRONG.  I forgot 1 crucial line of code and that just cost me about 3 hours chasing what I thought was a problem in the mapping file, when it was actually a problem in the code.

Integrating a new technology (defined as one you have no prior experience with), is a high risk exercise.  The simplest way to reduce risk is to change as little as possible and make sure it works.  Unit testing allows you to follow this cycle easily, but you have to commit to it completely, otherwise the value of your investment is significantly reduced - you get a false sense of security about the state of your code and build on those assumptions.

It’s also wise to remember that no matter what - you are a terrible coder and should therefore check ALL your assumptions that your current problem is built on before trying to solve the problem - sometimes it is incredibly useful to assert these as preconditions for your test - just so you really are sure your assumptions are correct.

Lesson learned, I’m off to retrofit a test or 2 :)

April 14, 2008

MonoRail and Castle Validator

Filed under: MonoRail — Neal @ 12:54 pm

Recently I have been working to add validation to a web application I am building using MonoRail. A bit of research turned up a brilliant component created by Hammett that greatly simplifies adding client and server side validation in one place.

Hammett’s validation components work within the scope of the databinding operation that allows you to bind form fields directly into parameters in a reasonably seamless manner. You do need to be able to apply validation attributes to properties in the object being bound, so it does not appear that you can validate simple parameters, but I am using a presentation model for a majority of my forms so this was not a problem.

There is a great guide here and Hammett’s screencast here that show you how to set up the validation.

There are a couple of gotchas with the validation though, and these repeatedly tripped me up until I understood what was going on, so I will publish them here and hope that it helps someone else (all of these problems appear when doing server side validation only - I have deliberately disabled the client side validation until the server side validation is complete and correct):

Validation of simple properties happens before the value has been converted. This means the validator gets passed a string value and therefore does not always behave as expected. For example ValidateNotSameValue(CallResult.Unspecified) passes validation when a value of Unspecified is submitted because it compares Unspecified (the enum value) with “Unspecified” (a string value). My solution at the moment is to write type specific validators that extend ValidateNotSameValueAttribute and convert the value to a string that is passed to the validator (like this NotSameEnumValueValidator).

Validation only occurs if a value for the field is sent in the request. If no value is set, then the validation for that property is not triggered. For example I have a property called QuestionnaireId which must not be empty, this rule is enforced using a custom validator that ensures the value is a Guid and is not equal to Guid.Empty. The validator works (it is used in a number of other places), however it will not ensure a value is selected from a radio button group as no value is posted to the server for that form field (the databinder explicitly skips validation if there is no value to bind). I have not worked out a strategy for dealing with this yet.

I think Hammett has done a great job, and this component covers the basic scenarios as well as providing a good extensibility mechanism, however there are a few gotchas (even Hammett outlines a few here), the key is to be aware of what is happening and why.

March 19, 2008

Unit Testing MonoRail Controllers with PrincipalPermissions

Filed under: MonoRail, Unit Testing — Neal @ 8:00 am

When you apply a CodeAccessSecurityAttribute that returns a PrincipalPermission to an action on a controller, all your existing tests for that action will break (to find out more about applying principal permissions, take a look at this blog entry about creating clean principal permission attributes). After a bit of digging and a lot of googling, I came across this post by Phil Haack that demonstrates how to set up your unit tests so they run correctly again.

Phil’s approach uses Rhino Mocks to mock out the IPrincipal and IIdentity interfaces and then attaches the mocked IPrincipal to Thread.CurrentPrincipal (which is where the PrincipalPermission retrieves the principal from to check permissions against). This approach is great, however I rapidly got tired of having to write out all of the code that this approach required, and I was getting annoyed with the clutter of try / finally blocks inside my tests (as well as forgetting to put the MockRepository into replay mode numerous times), so I stubbed out the principal and identity to create a much simpler alternative to the mocked versions. You can see these classes below:

    public class PrincipalStub : IPrincipal
{
    private readonly string _name;
    private readonly string _authenticationType;
    private readonly bool _isAuthenticated;
    private readonly bool? _isInRoleResponse;
    private readonly List<string> _roles;

    public PrincipalStub( string name, string authenticationType, bool isAuthenticated, bool isInRoleResponse )
    {
        _name = name;
        _isAuthenticated = isAuthenticated;
        _authenticationType = authenticationType;
        _isInRoleResponse = isInRoleResponse;
    }

    public PrincipalStub( string name, string authenticationType, bool isAuthenticated, params string[] roles )
    {
        _name = name;
        _isAuthenticated = isAuthenticated;
        _authenticationType = authenticationType;
        _roles = new List<string>( roles );
    }

    public IIdentity Identity
    {
        get
        {
            return new IdentityStub( _name, _authenticationType, _isAuthenticated );
        }
    }

    public bool IsInRole( string role )
    {
        if ( _isInRoleResponse.HasValue )
        {
            return _isInRoleResponse.Value;
        }

        return _roles.Contains( role );
    }
}

public class IdentityStub : IIdentity
{
    private readonly string _name;
    private readonly string _authenticationType;
    private readonly bool _isAuthenticated;

    public IdentityStub( string name, string authenticationType, bool isAuthenticated )
    {
        _name = name;
        _isAuthenticated = isAuthenticated;
        _authenticationType = authenticationType;
    }

    public string Name
    {
        get
        {
            return _name;
        }
    }

    public string AuthenticationType
    {
        get
        {
            return _authenticationType;
        }
    }

    public bool IsAuthenticated
    {
        get
        {
            return _isAuthenticated;
        }
    }
}

This means I can now replace the mocks and all the associated setup with a single line of code:

IPrincipal testPrincipal = new PrincipalStub("Test", "Test", true, true);

which will create a new principal that is always in any role asked of it (remember we want to test the action, not the code access security). This still left me with the setup and teardown code that I could have put into appropriate methods in the test class, but that lacked the flexibility to specify the exact parameters of the PrincipalStub for each test, and meant that all of my tests would be running under a “false” principal - less than ideal.What I needed was a mechanism for performing a two-phase operation with a chunk of indeterminate code in the middle, and the guarantee that the second phase would always run. Delegates and anonymous methods could have worked, but I got my inspiration from an approach Oren Eini (Ayende) uses to provide a more explicit mocking syntax. Taking this and applying it to the scenario I had resulted in the following TestPrincipalManger:

public class TestPrincipalManager
{
    private PrincipalStub _principal;

    public TestPrincipalManager(string username, string authenticationType, bool isAuthenticated, params string[] roles)
    {
        _principal = new PrincipalStub(username, authenticationType, isAuthenticated, roles);
    }

    public TestPrincipalManager(string username, string authenticationType, bool isAuthenticated, bool isInRoleResponse)
    {
        _principal = new PrincipalStub(username, authenticationType, isAuthenticated, isInRoleResponse);
    }

    public IDisposable Attach()
    {
        IPrincipal originalPrincipal = Thread.CurrentPrincipal;
        Thread.CurrentPrincipal = _principal;
        return new TestPrincipalCleanup( originalPrincipal );
    }

    public class TestPrincipalCleanup : IDisposable
    {
        private readonly IPrincipal _principal;

        public TestPrincipalCleanup( IPrincipal principal )
        {
            _principal = principal;
        }

        public void Dispose()
        {
            Thread.CurrentPrincipal = _principal;
            GC.SuppressFinalize( this );
        }
    }
}

That can be used as follows:

[Test]
public void AdministratorPermissionAttribute_Permission_Succeeds_If_Principal_Does_Have_Administrator_Permission()
{
    TestPrincipalManager authorisedPrincipal = new TestPrincipalManager("A.User", "Test Auth", true, "Administrator");
    AdministratorPermissionAttribute permissionsAttribute = new AdministratorPermissionAttribute( SecurityAction.Demand );
    IPermission permission = permissionsAttribute.CreatePermission();

    using ( authorisedPrincipal.Attach() )
    {
            Assert.IsTrue(Thread.CurrentPrincipal.IsInRole("Administrator"), "Pre-condition failed: Current user does not have the Administrator permission");
            permission.Demand();
    }
}

While at first glance, this appears to be a perversion of the using syntax / IDisposable interface, if you take a second look it makes perfect sense. Using is essentially just a compiler macro that replaces the using with a try / finally, and the object that we are disposing of is following the semantics of the dispose operation - it is cleaning up after itself. Extracting the class doing the disposal out means that the Attach() method can be called repeatedly with no nasty side-effects (I hope!).

March 18, 2008

Creating Clean Principal Permission Attributes

Filed under: MonoRail, c# — Neal @ 3:13 pm

MonoRail allows you to use the PrincipalPermissionAttribute to secure your code in a reasonably unobtrusive manner as shown in the MonoRail documentation here. This is great as it allows a simple way to express the security requirements of your actions without cluttering the action with security checks. This problem I have with this is it adds a rather ugly attribute to the action that looks like:

[PrincipalPermission(SecurityAction.Demand, Role='Administrator')]
public void DoSomeAdminStuff()
{
    // ...
}

I also have to remember exactly how to type it out if I want to reuse it, so I set out to create a “nice” attribute that would communicate the same information with a lot less clutter - something like:

[RequireAdministratorPermission]
public void DoSomeAdminStuff()
{
    // ...
}

A quick bit of digging shows that the PrincipalPermissionAttribute is sealed so I can’t apply my usual trick of extending it and providing the default values I want, so I set about figuring out exactly what the PrincipalPermissionAttribute does. Turns out it is very simple, just extend the CodeAccessSecurityAttribute and implement IPermission CreatePermission(). Poking around in the PrincipalPermissionAttribute just to make sure I was doing things correctly, showed that I need to check if the underlying SecurityAttribute had it’s Unrestricted flag set and return an unrestricted permission if it was, so I extracted this into a superclass to simplify creating additional permission attributes later. The resulting classes are very simple and do not do much at all (except make my code look a lot nicer!).

public abstract class BasePrincipalPermissionAttribute : CodeAccessSecurityAttribute
{
    protected BasePrincipalPermissionAttribute( SecurityAction action ) : base( action )
    {
    }

    public override IPermission CreatePermission()
    {
        if (Unrestricted)
        {
            return new PrincipalPermission(PermissionState.Unrestricted);
        }

        return CreatePrincipalPermission();
    }

    protected abstract PrincipalPermission CreatePrincipalPermission();
}

public class AdministratorPermissionAttribute : BasePrincipalPermissionAttribute
{
    public ManageUsersPermissionAttribute( SecurityAction action ) : base( action )
    {
    }

    protected override PrincipalPermission CreatePrincipalPermission()
    {
        return new PrincipalPermission( null, "Administrator", true );
    }
}

And they can be used like:

[AdministratorPermission(SecurityAction.Demand)]
public void DoSomeAdminStuff()
{
    // ...
}

Unfortunately you still have to specify the security action, this is due to something that occurs during the compile process to serialise the permissions and store them with the assembly requiring the SecurityAction to be specified in the constructor of the attribute.

Using a Domain Model Simplifies Your Unit Testing

Filed under: Domain Driven Design, Unit Testing — Neal @ 10:16 am

I’ve just had one of those AHA! moments - you know, when you are staring at code and you have a bunch of concepts running around the back of your mind and something just falls into place.

The code I happened to be staring at was a set of unit tests for my UserController, and the tests simply ensured the basic user management operations worked as they should (user is created, user is updated etc etc). For some reason while I was staring at this I was thinking about testing that the newly created users could log in successfully, but what that would really be testing was are the users created correctly?

This kind of thinking comes from my days before unit testing, domain objects and DRY, back then the code that created the user would be quite separate from the code that logged the user in and both of these actions would have a significant “plumbing” code in them meaning that if we changed something about the way the user was created, we could conceivably break the login process without knowing it (a lot of the applications I used to build were highly procedural / transaction script oriented), so I would have something like (warning: aircode):

public bool Login(string username, string password)
{
    DataRow userRow = UserDAO.GetUser( username );
    return userRow["Password"] == password;
}

… somewhere else in the app …

public void CreateUser(string username, string password, ... )
{
    UserDAO.CreateUser(username, password, ... );
}

So what would happen if the boss suddenly decreed that all passwords should be stored with hashes? I’d definately change the CreateUser code, but what if I didn’t write the Login code, would I know about it? Without unit tests, definitely not; with unit tests, maybe, depending on how much was mocked out (as ideally I wouldn’t be testing the data access code so my mock would return what I was expecting). Compare that to my current implementation - a Credentials class that contains all of the username / password / login attempts related details (and nothing about persistence):

    public class Credentials
    {
        public const int MaximumLoginAttempts = 3;

        private string _username;
        private readonly HashedPassword _password;
        private int _loginAttemptsRemaining;

        public string Username
        {
            get
            {
                return _username;
            }
        }

        public int LoginAttemptsRemaining
        {
            get
            {
                return _loginAttemptsRemaining;
            }
        }

        public bool IsLockedOut
        {
            get
            {
                return _loginAttemptsRemaining  MaximumLoginAttempts)
            {
                loginAttemptsRemaining = MaximumLoginAttempts;
            }

            _loginAttemptsRemaining = loginAttemptsRemaining;
        }

        public bool ValidatePassword(string password)
        {
            if (_loginAttemptsRemaining <= 0)
            {
                return false;
            }

            if (_password.IsSameAs(password))
            {
                _loginAttemptsRemaining = MaximumLoginAttempts;
                return true;
            }

            _loginAttemptsRemaining = _loginAttemptsRemaining - 1;
            return false;
        }
    }

This implementation already stores the data as a hashed password, but the original version didn’t (only for the first version where I was concentrating on getting the basic behaviours). Adding the ability to hash the password didn’t change the external interface in any way and therefore any existing tests I had didn’t require any changes - they just worked.

It is not so much that using a domain model directly simplifies your unit testing, it’s more that a domain model encourages you to implement separation of concerns and the single responsibility principle. SoC and SRP combine to significantly increase the testability of your application (as well as decreasing the fragility of the unit tests).

In my case, the true realisation was that because the responsibility for the persistence of the object was separate from the user object and the controller, I couldn’t break the login code by changing the persistence code or the user creation code (assuming I created a valid user object), and because I had previously tested the login code, I had already tested the login code under all of the scenarios that were applicable.

Building a domain model is definitely worth the effort!

March 17, 2008

Troubleshooting IIS7 : 3 Things I’ve Learnt

Filed under: IIS7 — Neal @ 5:29 pm

1.  Stop!  Take a step back and think hard about the fault.

- if you are not familiar with IIS7 (and you’ve tried all those “tricks” you used to use with IIS6), more than likely your issue is IIS7 installation / configuration related.

2.  Remember IIS7 installs nothing by default

- are you sure you have installed all of the handlers you need for the site?

3.  Remember IIS7 installs nothing by default

- not even error handlers and error page generators

When something that “should” work doesn’t, frustration and “thrashing” often ensues - you refuse to accept the obvious and keep trying the same thing different ways yet the result is always the same.  This is why stopping and taking a step back often results in seeing the true nature of the problem and allowing you to solve it.  Every issue I have experienced with IIS7 so far has been because of installation (or lack of) or configuration issues.  This is because I keep thinking about IIS7 like I am used to thinking about IIS6.

Most of the issues I have had with IIS7 are due to the correct handlers not being installed.  This one has caused me problems a couple of times, the most classic example being wondering why a site looked different under IIS7 when the same site worked fine under IIS6.  I spent an hour checking and trying a lot of different things before I finally stopped and thought about what was happening - the css and images for the site were not being served, a bit of research showed that IIS7 has a separate static content handler that is not installed by default.  Installed the correct handler and the site worked fine.

If you are sure everything else is working and installed as it should be, then more than likely you have a configuration issue.  This problem is a definite probability if you are setting up an ASP.NET web application that runs fine under IIS6 but seems to fail under IIS7.  Today I spent yet another hour troubleshooting the deployment of something to IIS7, the biggest problem I had was I had no information to diagnose the issue.  Turns out that IIS7 does not even install any kind of error handlers to generate those charming yellow pages of death most ASP.NET developers will be familiar with.  Once I figured out that I had to install yet another set of handlers, I could review the error details, resolve the issue and get the site up and working quite quickly.

If you’ve got everything installed and nice error messages and fault tracing, and you still can’t figure out what the problem is, I’m sorry I can’t help, you exhausted my current knowledge on IIS7.  Google is your friend or you could try The Official Microsoft IIS Site and forums as there are plenty of people more knowledgeable than I lurking around there.

Blog at WordPress.com.