FluentValidation and PostSharp for RESTful WCF parameter validation – Part 3

 

Now we can take a look at how to take advantage of everything we have put in place. As mention in the first post, two thing can happen after a validation failure:

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

So our PostSharp aspect needs to handle both of these cases.

[DataContract]
public class ErrorMessage
{
    public ErrorMessage()
    {
        Errors = new List<string>();
    }

    [DataMember]
    public string ParameterName { get; set; }
    
    [DataMember]
    public ICollection<string> Errors { get; set; }
}

This is the object that is serialised back to the client in the event of a failure with no default value. Now we need to override the OnInvoke method in order to apply our runtime interception.

public override void OnInvoke(MethodInterceptionArgs args)
{
    var errorMessage = new List<ErrorMessage>();            
    Arguments arguments = args.Arguments;

    foreach (var parameterValidation in _validationRules)
    {
        foreach (var validatorType in parameterValidation.ValidationRules)
        {
            var result = ValidateArgument(validatorType, arguments[parameterValidation.Parameter.Position]);

            if (result != null && !parameterValidation.HasDefaultValue)
            {
                var message = new ErrorMessage
                                  {
                                      ParameterName = parameterValidation.Parameter.Name
                                  };
                foreach (var validationFailure in result)
                {
                    message.Errors.Add(validationFailure.ToString());
                }
                errorMessage.Add(message);
            }
            else if(result != null)
            {
                args.Arguments.SetArgument(parameterValidation.Parameter.Position, parameterValidation.DefaultValue());
            }
        }
    }

    if(errorMessage.Any())
    {
        throw new WebFaultException<List<ErrorMessage>>(errorMessage, HttpStatusCode.BadRequest);                
    }

    base.OnInvoke(args);
}

So we iterate through the validation rules, where each rule composes of a parameter, the default value if there is one and the rules which should apply to it. We check whether the actual value passes the rule, and if there are any failures raise a WebFaultException available in the .NET 4 BCL.

In the cause of a failure which does have a default value defined, we use PostSharp to override the actual value with the default one before returning to the intercepted method.

The ValidateArgument method looks like:

static IEnumerable<ValidationFailure> ValidateArgument(Type validatorType, object argument)
{
    IValidator validator = (IValidator) Activator.CreateInstance(validatorType, null);

    var result = validator.Validate(argument);
    if (!result.IsValid)
    {
        return result.Errors;
    }
    return null;

}

This calls upon FluentValidation to perform the checking and returns the result.

In the event of a failure with no default value, the client get a nice HTTP Status code indicating an error…

clip_image002

And a message detailing why…

clip_image002[5]

Next up will be a sample solution up on GitHub.

FluentValidation and PostSharp for RESTful WCF parameter validation – Part 2

 

Now that we have introduced FluentValidation in the previous post we can take a look at applying these based on attributes applied to the incoming WCF parameters. Let’s take a simple method and apply some parameters to it.

[RestArgumentValidation]
public Basket Basket(
    [CustomerIdValidator] string customerid,
    [BasketItemValidator] BasketItem basketItem)
{
    // Stuff happens
}

While these attributes do clutter the code, personally I feel they make it clear these parameters are being validated. Let’s take a look at what these parameter attributes are before looking at the PostSharp.

First we need a base class for the attributes to provide both a default value if needed, and what validators should apply to the decorated parameter.

[Serializable]
public abstract class RestArgumentValidatorBase : Attribute
{
    public abstract IEnumerable<Type> Validators { get; }

    public virtual Func<object> DefaultValue { get; private set; }
}

The reason we need to define a function that returns the default value is because PostSharp serialises these attributes as an optimisation. If the default value is based on an expression which can only be calculated at runtime, then we cannot serialise it, but we can serialise the expression which computes this value. Let’s take a look at some examples of this in action:

public class BasketItemValidatorAttribute : RestArgumentValidatorBase
{
    public override IEnumerable<Type> Validators
    {
        get
        {
            return new[]
                       {
                           typeof(BasketItemValidator)
                       };
        }
    }
}

Here we specify the validator used for the object BasketItem, and no default value. This means if the validation fails a response will be sent to the client indicating what has gone wrong.

public class CurrencyValidatorAttribute : RestArgumentValidatorBase
{
    public override Func<object> DefaultValue
    {
        get { return () => ConfigurationManager.AppSettings["defaultCurrency"]; }
    }

    public override IEnumerable<Type> Validators
    {
        get { return new[] { typeof(CurrencyValidator) }; }
    }
}

Here we specify a default value which is taken from the app settings, so if an invalid parameter is sent down, we can use this value instead. All that’s left is the PostSharp aspect which ties all this together which we can go through step by step.

First we need to analyse the method which has the aspect applied to see what validation needs to happen. We can compute this ahead of time during compilation so the runtime overhead is reduced.

public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
    foreach (var parameterInfo in method.GetParameters())
    {
        var validationAttribute = (from attributeType in parameterInfo.GetCustomAttributes(true)
                                   where typeof(RestArgumentValidatorBase).IsAssignableFrom(attributeType.GetType())
                                   select attributeType).Cast<RestArgumentValidatorBase>().FirstOrDefault();

        if(validationAttribute != null)
        {
            _validationRules.Add(new ParameterValidation
                                     {
                                         Parameter = parameterInfo,
                                         DefaultValue = validationAttribute.DefaultValue,
                                         ValidationRules = validationAttribute.Validators
                                     });
        }
    }
}

This can be summarised as:

  1. Take a look at each parameter on the method.
  2. See if it has a validation attribute applied.
  3. Cache the default value expression and validation rules for that parameter in a serialised list which is used at runtime.

The cached serialised object itself looks like:

[Serializable]
class ParameterValidation
{
    public ParameterInfo Parameter { get; set; }

    public Func<object> DefaultValue { get; set; }

    public bool HasDefaultValue
    {
        get
        {
            return DefaultValue != null;
        }
    }

    public IEnumerable<Type> ValidationRules { get; set; }
}

Next up we’ll take a look at using this cached information at runtime.

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.

The Template Method pattern gone wrong (or how to stop your overridden methods getting called)

The definition of the “Template Method pattern” may or may not be familiar to you, but the following bit of code sure will:

public abstract class BroadcasterBase 
{ 
    public void SendMessage(Message msg) 
    { 
        // Perform some validation and pre-processing on msg 
        base.SendMessageInternal(msg); 
    } 

    protected virtual void SendMessageInternal(msg)
    {
        // Some default behaviour
    }
}

public class NetworkBroadcaster : BroadcasterBase
{
    protected override void SendMessageInternal(Message msg) 
    {
        // Send the message, now that it has been validated and all pre-processing is complete
    }
}

For the pedants amongst us (which includes me), the Template Method pattern can be defined as:

A template method defines the program skeleton of an algorithm. One or more of the algorithm steps can be overridden by subclasses to allow differing behaviours while ensuring that the overarching algorithm is still followed.

Now this works well until it starts becoming over-engineered and we start having more than one base class. 

public abstract class BroadcasterBase 
{ 
    protected virtual void SendMessageInternal(msg)
    {
        // Some default behaviour
    }
}

public abstract class ValidatingBroadcaster : BroadcasterBase
{
    public void SendMessage(Message msg) 
    { 
        // Perform some validation and pre-processing on msg 
        base.SendMessageInternal(msg); 
    } 
}

public class NetworkBroadcaster : ValidatingBroadcaster
{
    protected override void SendMessageInternal(Message msg) 
    {
        // Send the message, now that it has been validated and all pre-processing is complete
    }
}

And at this point it’s actually broken!  The code inside NetworkBroadcaster will no longer get executed.  This is actually down to one very small bit of code … the use of the “base” keyword in the ValidatingBroadcaster.  This actually makes the call non-virtual and binds it to the specific class, in this case BroadcasterBase.SendMessageInternal.  Eric Lippert puts it nicely:

a base call is a non-virtual call to the nearest method on any base class, based entirely on information known at compile time.

I ran into this problem with the Microsoft Prism framework when extending the eventing mechanism.  Specifically I wanted to derive from CompositePresentationEvent and override the event publication mechanisms.  This particular problem prevented me from doing that.

There are probably two important lessons from this:

  1. Don’t go blithely putting “base.” in front of methods calls, e.g. because something like StyleCop thinks you should
  2. Just because you have a base class with some overridable methods, don’t assume they will get called
June 27 2011
Newer Posts Older Posts