Switching Visual Studio Environment Tools with Powershell and SlightlyPosher

 

Initially the SlightlyPosher environment configured the VS2008 tools as that was what I need on my project. Pascal was kind enough to send me a patch to use the VS2010 tools instead.

I thought it would be cool to satisfy both users, as not everyone has been lucky enough to switch to VS2010 yet.

In profile.ps1 by default the VS2010 tools are loaded.

Set-VsVars32 2010

image

If you would like to switch this, its as simple as calling:

Set-VsVars32 2008

Now you will have a VS2008 environment and MSBuild 3.5 at your fingertips.

image

The implementation for this is pretty straightforward…

#### Functions Used to Load VS Command Prompt #####
function Get-Batchfile ($file) {
    $cmd = "`"$file`" & set"
    cmd /c $cmd | Foreach-Object {
        $p, $v = $_.split('=')
        Set-Item -path env:$p -value $v
    }
}

function Set-VsVars32($vsYear)
{
   switch ($vsYear)
   {
        2008 {$vstools = $env:VS90COMNTOOLS}
        2010 {$vstools = $env:VS100COMNTOOLS }
   }

   $batchFile = [System.IO.Path]::Combine($vstools, "vsvars32.bat") 
   
   Get-Batchfile -file $batchFile
   
   Write-Host -ForegroundColor 'Yellow' "VsVars has been loaded from: $batchFile"
}

The Get-BatchFile function is provided by many blogs describing how to use the Visual Studio tools with PowerShell. The Set-VsVars32 method takes the year as an argument, and loads the tools for that Visual Studio year.

Run update.bat to get these latest changes. Enjoy!

FluentValidation and PostSharp for RESTful WCF parameter validation – Part 4

 

This is the last of the series and you can find the previous parts below:

FluentValidation and PostSharp for RESTful WCF parameter validation – Part 1
FluentValidation and PostSharp for RESTful WCF parameter validation – Part 2
FluentValidation and PostSharp for RESTful WCF parameter validation – Part 3

The promised example solution at: https://github.com/naeemkhedarun/WcfValidation 

You will need PostSharp 2.0 installed, the community edition is fine.

This is a functional RESTful WCF service where you can send a product using a JSON request, and have the same product sent back in the response.

[RestArgumentValidation]
public ProductItem Create([ProductItemValidator] ProductItem instance)
{
    return new ProductItem
               {
                   Name = instance.Name
               };
}

On my current project we use a structure similar to the sample project to organise our attributes and validators.

image

To test this service I’m using the REST Console application for Chrome. First we need to set up our target:

image

When we make the request we should get a helpful HTTP Status Code of 400 (Bad Request):

image

We should also get a response body giving us some more detail about the issue with our request.

image

To make a valid request, we simply send the correct request body which looks like:

image

image

Running the request once more we receive the proper response:

image

And there you have it, I hope you’ve found this useful!

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.

Newer Posts Older Posts