Skip Navigation LinksHome > View Post

Rulesets on Operations in WCF with Validation Application Block

In my last post I introduced the WCF integration in the Validation Application Block from the Patterns and Practices team at Microsoft. I mention at the end that I would like the ability to specify individual Rulesets to each operation within a ServiceContract.

Let's start by examining the ValidationBehavior and ValidationBehaviorAttribute in the Validation.Integration.WCF project in EntLib 4.0.


public class ValidationBehavior : IEndpointBehavior, IContractBehavior
{    
    // Details excluded
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,
Inherited = false, AllowMultiple = false)]
public class ValidationBehaviorAttribute : Attribute, IEndpointBehavior, IContractBehavior
{
    // Details excluded
}

The first thing to notice is that the ValidationBehavior implements the IContractBehavior interface which "Implements methods that can be used to extend run-time behavior for a contract in either a service or client application.".

WCF also supports implementing the IOperationBehavior interface which "Implements methods that can be used to extend run-time behavior for an operation in either a service or client application.". This seems like what I am looking for, so off we go and add this interface to both the ValidationBehavior class and the ValidationBehaviorAttribute class.


public class ValidationBehavior : IEndpointBehavior, IContractBehavior, IOperationBehavior
{
    // Details excluded
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,
Inherited = false, AllowMultiple = false)]
public class ValidationBehaviorAttribute : Attribute, IEndpointBehavior, IContractBehavior, IOperationBehavior
{
    // Details excluded
}

The methods you have to implement when adding this Interface are surprisingly similar to the methods in the IContractBehavior interface so I am not even going to describe it in this post. For those of you who would like to try this, just download the source files that are available from the link at the end of this post.

Now the second thing to notice is that the ValidationBehaviorAttribute's AttributeUsage does not include AttributeTargets.Method. So let's add this one too. The final version of the two class definitions look like this:


public class ValidationBehavior : IEndpointBehavior, IContractBehavior, IOperationBehavior
{
    // Details excluded
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method,
Inherited = false, AllowMultiple = false)]
public class ValidationBehaviorAttribute : Attribute, IEndpointBehavior, IContractBehavior, IOperationBehavior
{
    // Details excluded
}

If you remember my example from the previous post, I am now able to specify a different Ruleset to run on each operation. Tidy!


[ServiceContract]
public interface IValidationService
{
    [OperationContract]
    [ValidationBehavior("Update")]
    [FaultContract(typeof (ValidationFault))]
    void Update(Customer customer);

    [OperationContract]
    [ValidationBehavior("Create")]
    [FaultContract(typeof (ValidationFault))]
    CustomerKey Create(Customer customer);
}

[DataContract]
public class Customer
{
    [DataMember]
    [NotNullValidator(Ruleset = "Update")]
    public string Id { get; set; }

    [DataMember]
    [StringLengthValidator(1, RangeBoundaryType.Inclusive, 20, RangeBoundaryType.Inclusive, MessageTemplate = "Firstname must be between 1 and 20.", Ruleset = "Update")]
    [StringLengthValidator(1, RangeBoundaryType.Inclusive, 20, RangeBoundaryType.Inclusive, MessageTemplate = "Firstname must be between 1 and 20.", Ruleset = "Create")]
    public string FirstName { get; set; }

    [DataMember]
    [StringLengthValidator(1, RangeBoundaryType.Inclusive, 20, RangeBoundaryType.Inclusive, MessageTemplate = "Username must be between 1 and 20.", Ruleset = "Create")]
    public string UserName { get; set; }
}

If you would like this kind of control yourself, go to EntLib on Codeplex and view the issue that I added and download the source. I would also appreciate if you give it a vote so we can see this in a future release of EntLib.

Tags: ASP.NET

 
Bruusi Post By Bruusi
6:02 AM
18 Aug 2008

» Next Post: theJoyOfCode in PC Pro Magazine
« Previous Post: Validation Application Block and WCF

Comments are closed for this post.

Posted by raffaeu @ 26 Nov 2009 9:26 AM
Hi dude. Interesting post for sure, but not completely agree on the approach. In your sample you are exposing some C.r.u.d. operations inside WCF and as you know this will never happen in an enterprise application. Usually you have a Dto and anyway you don't ask for a Dto in the message but for a parameter list.
For example, if I have something like

myService.UpdateJob(int jobId, string status);

How I can handle the EntLib validation in order to validate those two parameters? Should I create a fake DataContract only for this call? Oh boy ...

Posted by Gary @ 10 Mar 2010 6:54 AM
Hi Bruusi,

Great post! I found this extremely helpful. I would like to do something and I'm not sure if it is possible; maybe you know whether it is or not.

I would like apply a different set of schema validation rules to a data transfer object based on the value of one of its fields. For example, if the field "district_code" is "NJ" apply the ruleset "validateNJ" if the field "district_code" is "NY" apply the ruleset "validateNY". Do you think there is any way to do this?

Any help/insight would be greatly appreciated. Thanks again for this awesome post!

© 2005 - 2014 Josh Twist - All Rights Reserved.