FluentValidation and PostSharp for RESTful WCF parameter validation – Part 1

 

My current project involves publishing a RESTful WCF service, and its possible that parameters coming into the service could be incorrect. When this is the case one of two things should happen:

  • A HTTP response code and JSON payload returned to the client explaining the error.
  • The invalid parameter ignored and a default one used instead.

Since we are using FluentValidation elsewhere in the application it seemed like a logical choice for this project as well. It provides us with both a fluent interface for simple validation rules and a method of extension for custom rules.

For example let’s take a look at a fluent configuration for validating a request object.

public class CustomerIdValidator : AbstractValidator<string>
{
    public CustomerIdValidator()
    {
        RuleFor(s => s)
            .Cascade()
            .StopOnFirstFailure()
            .NotNull()
            .NotEmpty()
            .Length(32)
            .WithName("customerid")
            .WithMessage("Customer Id should be thirty two letter string.")
            .Must(IsStringAValidCustomerId)
            .WithName("customerid")
            .WithMessage("Customer Id is invalid.");
    }

    private static bool IsStringAValidCustomerId(string customerId)
    {
        Guid parseCustomerId;
        return Guid.TryParse(customerId, out parseCustomerId); ;
    }
}

Personally I find this easy to read without the messy conditional branching that we would have needed had we done this manually. You can apply rules to custom objects too.

public class BasketItemValidator : AbstractValidator<BasketItem>
{
    public BasketItemValidator()
    {
        RuleFor(basketItem => basketItem.CustomerId)
            .SetValidator(new CustomerIdValidator());

        RuleFor(basketItem => basketItem.Price)
            .NotEmpty()
            .WithName("price");

        RuleFor(basketItem => basketItem.Quantity)
            .GreaterThan(0)
            .WithName("quantity");

        RuleFor(basketItem => basketItem.ProductId)
            .SetValidator(new ProductIdValidator());

        RuleFor(basketItem => basketItem.ItemType)
            .Must(itemType => Enum.IsDefined(typeof (BasketItemType), itemType))
            .WithName("itemtype");
    }
}

Reusing existing validators using the SetValidator extension is a neat way of reusing validaiton routines. However there are some cases where you do need more complex logic, and FluentValidation luckily has us covered.

public class BasketItemListValidator : AbstractValidator<IEnumerable<BasketItem>>
{
    public override ValidationResult Validate(IEnumerable<BasketItem> instance)
    {
        var failures = new List<ValidationFailure>();

        if(instance == null || !instance.Any())
        {
            failures.Add(new ValidationFailure("basketItems", 
                "There should be at least one basket item to move."));
        }
        else
        {
            foreach (var basketItem in instance)
            {
                failures.AddRange(new BasketItemValidator().Validate(basketItem).Errors);
            }
        }

        return new ValidationResult(failures);
    }
}

We can simply override the Validate method to apply our custom routines, which in this case is applying an existing validator to a list of objects and collating the results.

If you need a validation framework I can recommend this one whole heartedly. Next up is using PostSharp to apply these routines when a call is made to WCF.

Finding all projects containing a reference to X assembly using POSH

 

Finding all the projects which reference a specific assembly can be a little tough in visual studio if you have hundreds of projects. NDepend can do this for you, but that requires you’re willing to pay for a licence (you should) if you need it commercially.

I wrote a little bit of POSH to do this for me…

function Get-ContainsReferenceTo($projectFile, $referenceName)
{
    [xml]$s = get-content $projectFile

    $references = $s.Project.ItemGroup | Where-Object { $_.Reference -ne $null }
    
    foreach($reference in $references.ChildNodes)
    { 
        if($reference.Include -ne $null -and $reference.Include.StartsWith($referenceName))
        {
            return $true
        }
    }

    return $false
}

 

After loading the project file into an XmlDocument, we can iterate through each reference and do a string compare against the reference name.

Running this will return “True” or “False” as to whether the file contains the reference or not.

We can then do this for all project files in a directory by doing:

function Get-ProjectsContainingReferenceTo($directory, $referenceName)
{
    Get-ChildItem $directory -include *.csproj,*.vbproj -Recurse | foreach ($_) { 
        if(Get-ContainsReferenceTo $_.fullname $referenceName -eq $true){ $_.fullname }
    }
}

 

Now if any project files match the reference, the full path of the project file will be output to the command window. We can use this to perform batch operations to change references, remove them or anything else we would like.

I hope you find this useful and you can find it bundled with SlightlyPosher.

NBuilder is fantastic for generating object graphs

 

A library which I have not seen used often enough is NBuilder. On my current project we needed to create a WCF service for consumption by a 3rd party. Since the structure of the web service was agreed beforehand, we wanted to publish an early version for them to connect to.

Instead of manually hand cranking the test data that the API was to return, we were able to use NBuilder to do 90% of the work, with overrides to handle more complex cases.

You can also use it in your unit tests wrapped by a builder pattern to create common object graphs for use by your tests.

We created some common interfaces for our builders to get a default setup of an object, which we could then use the provided builder methods to override.

public interface IBuilder<T>
{
    ISingleObjectBuilder<T> GetDefault();
}

public interface IManyBuilder<T>
{
    IListBuilder<T> GetDefault();
}

Next we implemented default builders to get the common configured setup. NBuilder has generators for many common types, and iterates through the object graph populating dummy data.

public class CustomerBasketBuilder : IBuilder<Basket>
{
    public ISingleObjectBuilder<Basket> GetDefault()
    {
        var basketItems = new CustomerBasketItemsBuilder().GetDefault().Build();

        var basket = Builder<Basket>
            .CreateNew()
            .With(basket1 => basket1.BasketItems = basketItems)
            .With(basket1 => basket1.ItemCount = basketItems.Count)
            .With(basket1 => basket1.CustomerId = new PrimitiveBuilder().GetCustomerId())
            .With(basket1 => basket1.TotalBasketValue = basketItems.Sum(item => item.BasePrice));

        return basket;
    }
}

 

Whenever we use the With method here, we are setting up an override over the default generators. I manually call the BasketItemsBuilder to get the default setup for a list of items, and then ask NBuilder to Build the object graph using a combination of my overrides with the default generators.

public class CustomerBasketItemsBuilder : IManyBuilder<BasketItem>
{
    public IListBuilder<BasketItem> GetDefault()
    {
        var generator = new UniqueRandomGenerator();
        
        var basketItems = Builder<BasketItem>
            .CreateListOfSize(10)
                .All()
                    .With(item => item.ItemId = generator.Next(100000, 999999))
                    .With(item => item.Colour = Pick<string>.RandomItemFrom(new[] { "Red", "Green", "Blue" }))
                    .With(item => item.ItemType = BasketItemType.Product)
                    .With(item => item.ValidOperations = new[]
                                                             {
                                                                BasketItemOperations.CanSaveForLater,
                                                                BasketItemOperations.CanDelete,
                                                                BasketItemOperations.CanEdit
                                                             });
                
        return basketItems;
    }
}

 

UniqueRandomGenerator is one of the OOTB generators, which is normally called implicitly, however we needed a defined range in this case. The Pick methods are also useful for one liner random item choosing. I strongly recommend going through the NBuilder codebase to see what’s available. There’s some real gems in there which unfortunately are not documented.

Here’s a refactored sample from one of our tests:

Before After
image image

 

It turns out refactoring unit tests is really satisfying, and reduces stress, I highly recommend it.

Configuring Log4net in code using Windsor Installers

 

Castle provides a great way to structure the setup of your application using the installers. Ninject providers a similar mechanism with modules which you could also use.

Managing configuration was getting pretty painful on my current project, so cutting it down was necessary. Since we don’t need to edit most of the log4net configuration after a build is done, compiling this in is acceptable.

We are using the log4net facility for castle, so this is the first thing we set up.

public class LoggingInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        if (!container.Kernel.GetFacilities().OfType<LoggingFacility>().Any())
        {
            container.AddFacility("logging", new LoggingFacility(LoggerImplementation.Log4net));
        }

        var root = ((Hierarchy)LogManager.GetRepository()).Root;
        root.AddAppender(GetEventLogAppender());
        root.Repository.Configured = true;
    }
}

 

Next we set up an EventLog appender using the built in object model provided by log4net.

private static IAppender GetEventLogAppender()
{
    var patternLayout = new PatternLayout("%appdomain [%thread] %-5level - %message%newline [%properties]%newline %exception");

    var eventLogAppender = new EventLogAppender
                               {
                                   Name = "Application",
                                   Layout = patternLayout,
                                   ApplicationName = "MyApp",
                                   SecurityContext = NullSecurityContext.Instance
                               };
    return eventLogAppender;
}

 

And after calling container.Install(new LoggingInstaller()) we have logging without writing a single line of XML!

Newer Posts Older Posts