Service factory merge issues...

I have already mentioned that I have been heavily using the service factory modelling edition in recent projects; very recently I got massive conflict with an SVN update to one particular service!

The servicecontract itself took an awful lot of fixing with a lot of messing around in DiffMerge to make sure all the changes from both sets of changes were correctly merged - it's not easy to merge but reading the operations and relating back is honkingly fiddly but not impossible.  Then it came to the supporting diagram XML - this was a real mess; it really only took me one look before I had to think of something else. After thinking through the hassle of rolling back my changes, then applying to the updated contract - I realised I wanted to avoid this hassle. I thought I would get into the old school "just try it and see" mode - I canned the inner XML from the diagram file, sweetly if you leave the root element and delete all content, once you open the service contract diagram it re-adds all the required elements.  So its just a case of laying out again - significantly less hassle than the other option. So I was chuffed that I saved time.

By the way this worked with the data contract that was also massively conflicted.

ASP.NET MVC, Moq, and unit testing auth/auth

This is a short post about unit testing authentication and authorisation using the framework Authorize attribute. For the most recent project we have built behind the ASP.NET provider template implementation of the IMembershipService to meet very specific customer requirements, but this testing approach remains the same if you use built in.

It was clear pretty quickly that duplication was going to happen testing authentication and authorisation so I wanted to distill the test code as much as I could. I ended up writing two helper methods to check for redirection of an unauthenticated user, and a user not in a define role - the following the helper in full:

public class AuthenticationTests
{
    public static void UnAuthorizedUserRedirects(Controller controller, string actionName)
    {
        var user = new Mock<IPrincipal>();
        user.ExpectGet(u => u.Identity.IsAuthenticated).Returns(false);
        var context = new Mock<ControllerContext>();
        context.ExpectGet(c => c.Controller).Returns(controller);
        context.ExpectGet(c => c.HttpContext.User).Returns(user.Object);
        context.ExpectSet(c => c.HttpContext.Response.StatusCode).Callback(status => Assert.AreEqual(401, status)).Verifiable();
        controller.ActionInvoker.InvokeAction(context.Object, actionName);
        context.VerifyAll();
        user.VerifyAll();
    }
    public static void UserNotInRoleRedirects(Controller controller, string actionName, string roleName)
    {
        var user = new Mock<IPrincipal>();
        user.ExpectGet(u => u.Identity.IsAuthenticated).Returns(true);
        user.Expect(u => u.IsInRole(roleName)).Returns(false);
        var context = new Mock<ControllerContext>();
        context.ExpectGet(c => c.Controller).Returns(controller);
        context.ExpectGet(c => c.HttpContext.User).Returns(user.Object);
        context.ExpectSet(c => c.HttpContext.Response.StatusCode).Callback(status => Assert.AreEqual(401, status)).Verifiable();
        controller.ActionInvoker.InvokeAction(context.Object, actionName);
        context.VerifyAll();
        user.VerifyAll();
    }
}

 

Using Moq they set expectations on a Moq'ed IPrincipal and ControllerContext to ensure that the action sets an HTTP StatusCode of 401 (unauthorised); I won't go into too much detail, you can read the code, and it's actually surprisingly straight forward...

Usage is then dead easy and keeps the tests really clean- just spin up your controller and ask one of the actions to check - for example:

[Test]
public void UnAuthenticatedUserRequestForRevokeRedirects()
{
    Mock<IMembershipService> membershipService = new Mock<IMembershipService>();
    AccountAdminController controller = new AccountAdminController(membershipService.Object);
    AuthenticationTests.UnAuthorizedUserRedirects(controller, "Revoke");
}

ASP.NET MVC RC1 Authorize

I found a wee issue with the ASP.NET MVC Web Application template with the Authorize

attribute.  Initially I was in two minds whether to convert the existing app or create a new project from template and port the code over - I took the second option as this usually causes the least amount of angst in the long run..

So the issue was found when trying to use the Authorize attribute to redirect to the template login page.  By default the has web.config with the following authentication section

<authentication mode="Forms">
	<forms loginUrl="~/Account/LogIn" />
</authentication>

but the AccountController action is called LogOn!  Note the subtle difference between LogIn and LogOn...

ASP.NET MVC and Moq

Using the Beta 1 of ASP.NET MVC I was trying to use Moq to test a controller action that used the UpdateModel using a FormCollection as the value provider. Reading Scott Guthrie's post for Beta 1 he makes it clear that it should be possible not to mock the context for the controller to descrease unit test friction - however any use of the UpdateModel generates an ArgumentNullException...

So I still had to mock - hopefully this will be worked out in the next beta but for now using Moq this is the minimum required to Mock the ControllerContext.

            var routeData = new RouteData();
            var httpContext = new Mock<HttpContextBase>();
            var controllerContext = new Mock<ControllerContext>(httpContext.Object, routeData,controller);
            controller.ControllerContext = controllerContext.Object;

NUnit binary requirement...

I like to have all dependencies for a project in the source code repository so that the solution can build for new developers straight from a check out. After having to work sift through the NUnit binary (again) to work out what I needed rather than reference the GAC, this list is as a reminder:

nunit-console-runner.dll
nunit-console.exe
nunit-console.exe.config
nunit-gui-runner.dll
nunit.core.dll
nunit.core.extensions.dll
nunit.core.interfaces.dll
nunit.exe
nunit.exe.config
nunit.framework.dll
nunit.framework.extensions.dll
nunit.mocks.dll
nunit.uikit.dll
nunit.util.dll

 

This includes the UI stuff required for running the GUI - just in case there is someone out there that doesn't have resharper...

Messed up Service Factory projects!

Using service factory modelling edition recently I managed to get a new service project into a position where it would not generate code with no indication as to why.  I knew it was my fault as I had deleted, moved and renamed projects a few times - it was one of those situations where I wanted to get the name right, but had an indecisive few minutes changed it, then eventually settled on the first name.  The self inflicted mess I managed to end up with was two projects in the project mapping table, and obviously by sheer luck I had chosen the one that referenced the deleted projects!

I resolves it by opening the ProjectMapping.xml and finding the ProjectMappingTable element that contained the correct projects references - basically this meant finding by project Id those projects that still exist in the solution file.

Configuring logging for ODP.NET

For the 11g client it's just not documented very well. The details of the settings can be found in http://download.oracle.com/docs/html/E10927_01/featConfig.htm, but you need to set the values in HKLM/ORACLE/ODP.NET/CLR Version/.  To get started set the TraceLevel to 1 and TraceFileName to something sensible and you get the method entry and exit points along with SQL logged.

Although not a great deal of use for solving or working around some of the issues we have been encountering with the 11.1.0.6.20 provider version (particularly problematic are support for the user defined object types and XMLType), but useful for debugging and identifying issues.

Enterprise Library ValueValidator for NHibernate unique values

Mouthful of a title...  So the background story is the need to check uniqueness of a value against the existing database of values during the Enterprise Library (v4.0) validation (and before the DB constraint violation), oh and I'm using NHibernate (v2.0) for persistence.  I decided to to create a ValueValidator to allow the application of rule by config or attribute rather than implement as self validation. Straight to it then. I will list the full class later but to help explain the cocky bit these are the main methods:

private bool IsUnique(Type targetType, string propertyName, object propertyValue, object validatedObject)
{
    using (ISession session = m_factory.OpenSession())
    {
        int matches = (int)session.CreateCriteria(targetType)
            .Add(Expression.Eq(propertyName, propertyValue))
            .Add(Expression.Not(EqualIdentifier(targetType, validatedObject)))
            .SetProjection(Projections.ProjectionList()
                .Add(Projections.RowCount()))
            .UniqueResult();
        return (matches == 0);
    }
}
private SimpleExpression EqualIdentifier(Type targetType, object validatedObject)
{
    ISessionFactoryImplementor factoryImplementor = (ISessionFactoryImplementor)m_factory;
    IEntityPersister persister = factoryImplementor.GetEntityPersister(targetType);
    object idPropertyValue = persister.GetIdentifier(validatedObject, EntityMode.Poco);
    string idPropertyName = persister.IdentifierPropertyName;
    return Expression.Eq(idPropertyName, idPropertyValue);
}

The IsUnique method is called within the DoValidate of the ValueValidator, it constructs a criteria query to basically select count(*) from table where unique property = value and not key column = key value - with the identifier detail returned as a SimpleExpression from the  EqualIdentifier method using the objects persister.  Actually pretty simple and sweet!  Full code for the validator:

public class UniqueValueValidator : ValueValidator
{
    private ISessionFactory m_factory;
    public UniqueValueValidator(string messageTemplate, string tag, bool negated)
        : base(messageTemplate, tag, negated)
    {
        Configuration config = new Configuration().Configure();
        m_factory = config.BuildSessionFactory();
    }
    protected override void DoValidate(object objectToValidate, object currentTarget, string key, ValidationResults validationResults)
    {
        Type targetType = GetTargetType(currentTarget);
        object target = GetTargetObject(currentTarget);
        if (!IsUnique(targetType, key, objectToValidate, target))
            validationResults.AddResult(new ValidationResult(key + " must be unique", currentTarget, key, base.Tag, this));
    }
    private bool IsUnique(Type targetType, string propertyName, object propertyValue, object validatedObject)
    {
        using (ISession session = m_factory.OpenSession())
        {
            int matches = (int)session.CreateCriteria(targetType)
                .Add(Expression.Eq(propertyName, propertyValue))
                .Add(Expression.Not(EqualIdentifier(targetType, validatedObject)))
                .SetProjection(Projections.ProjectionList()
                    .Add(Projections.RowCount()))
                .UniqueResult();
            return (matches == 0);
        }
    }
    private SimpleExpression EqualIdentifier(Type targetType, object validatedObject)
    {
        ISessionFactoryImplementor factoryImplementor = (ISessionFactoryImplementor)m_factory;
        IEntityPersister persister = factoryImplementor.GetEntityPersister(targetType);
        object idPropertyValue = persister.GetIdentifier(validatedObject, EntityMode.Poco);
        string idPropertyName = persister.IdentifierPropertyName;
        return Expression.Eq(idPropertyName, idPropertyValue);
    }
    private Type GetTargetType(object currentTarget)
    {
        if (currentTarget == null)
            throw new ArgumentException("Target should not be null");
        if (currentTarget is IValidationIntegrationProxy)
            return (currentTarget as IValidationIntegrationProxy).ValidatedType;
        return currentTarget.GetType();
    }
    private object GetTargetObject(object currentTarget)
    {
        if (currentTarget == null)
            throw new ArgumentException("Target should not be null");
        if (currentTarget is IValidationIntegrationProxy)
            return (currentTarget as IValidationIntegrationProxy).GetRawValue();
        return currentTarget;
    }
    protected override string DefaultNegatedMessageTemplate
    {
        get { return "The value must be unique"; }
    }
    protected override string DefaultNonNegatedMessageTemplate
    {
        get { return "The value must be unique"; }
    }
}

and for the attribute:

public class UniqueValueValidatorAttribute : ValueValidatorAttribute
{
    protected override Validator DoCreateValidator(Type targetType)
    {
        return new UniqueValueValidator(MessageTemplate, Tag, Negated);
    }
}
Which means that you can add the UniqueValueValidator attribute to properties to enforce unique value during validation:
        [UniqueValueValidator]
        public virtual string Name { get; set; }

HttpContext in ASP.NET MVC

A quick gotcha for ASP.NET MVC newbies (like me), the HttpContext object on the Controller are not set on construction.  I found this out when trying to capture the authenticated users IIdentity and then spent 20 minutes of my life working out why it was always null!  Good excuse to peruse the source though...

Move Service Factory projects

I have been using the Service Factory Modelling Edition a lot lately, whilst they do produce a lot of projects and may appear unwieldy at first glance, the consistency of implementation alone is worth it in some of the larger implementations.

The issue I have was a need to migrate a Service Factory project into another pre-existing solution (I am a tidy freak).  The best way I found was to manually copy and edit the sln file; all you need to do is copy the ProjectMapping.xml file along with the folders containing the implementations and the models into the new solution folder, then start to edit the new sln file!  As a word of caution remember to make copies of everything before you start, as editing the sln file can lead to splinters...

In the project section for Solution Items add the ProjectMapping.xml file:

Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A47C9E2B-340A-4E76-AA04-EE0B0A053637}"
            ProjectSection(SolutionItems) = preProject
                        ProjectMapping.xml = ProjectMapping.xml
            EndProjectSection
EndProject

 

If there is no Solution Items section just add a file to the root of the new solution in the IDE then close and start again.

The copy all of the Project sections relating the the folders and projects for the Service Factory from the original solution into the new solution, they are quite nicely grouped together, so this should be easy.  Just be wary to ensure that any other projects added to the original solution are not copied across.

Finally (to make sure you get all the solution folders setup correctly) copy all of the relevant nesting from the section:

GlobalSection(NestedProjects) = preSolution

 

This is usually at the end of the sln file, to the same location in the new sln.  If you have done everything correctly (some luck required) the new solution should open and build correctly in the IDE!  If the solution won't build and moans about project references, the most likely cause is the NestedProjects section. This section is sensitive to non existent projects, which is easy to do if If you are moving the project from a solution that contains more than just the Service Factory. Check each identifier in the section exists in the solution file, removing all those that don't.