Click here to Skip to main content
15,879,535 members
Articles / Operating Systems / Windows
Article

Introduction to Validation Application Block integration with Windows Communication Foundation (WCF)

Rate me:
Please Sign up or sign in to vote.
4.28/5 (12 votes)
5 May 20077 min read 92.4K   953   43   9
An article on Validation Application Block integration with Windows Communication Foundation (WCF)

Screenshot - WCFVAB1.gif

Contents

Introduction

There are many ways to validate messages and parameters for service operations. The most common way to do this is writing complex code at the beginning of each service operation. Although this approach will help you achieve your goal, it can sometimes become too complex to maintain, and not enough flexible to control with configuration. You also have to refactor it over and over again in order to perform the same validations in additional services and operations.

One of the most interesting new inclusions in Enterprise Library 3.0 is the "Validation Application Block", which lets you easily separate the validation requirements of your business objects from the flow of your business logic, and gives you the flexibility to configure it in configuration.

The Validation Application Block can integrate with Windows Forms, ASP.NET and Windows Communication Foundation in order to be adopted more smoothly in line of business applications. This article will talk about the integration between the Validation Application Block and Windows Communication Foundation.

This article assumes that you have some background in Windows Communication Foundation, and that you are familiar with the basic concepts of the Validation Application Block.

Validating WCF Services messages and parameters

Validating Parameters on a service operation

If your service operation receives parameters with primitive types, such as:

C#
[ServiceContract]
public interface IOrdersService
{
    [OperationContract]
    int CreateOrder(string currency, double amount);
}

and you want to validate them, you can use the parameter-level validation in the service contract:

C#
[ServiceContract]
public interface IOrdersService
{
    [OperationContract]
    int CreateOrder(
        [NotNullValidator] string currency,
        [RangeValidator(1.0, RangeBoundaryType.Inclusive, 2.0, 
                RangeBoundaryType.Inclusive)] double amount);
}

Notice the usage of the validation attributes before each of the parameters of the service operation. These attributes specify validation requirements for the parameters and will be used by the Validation Application Block in run-time.

Validating Message Contracts or Data Contracts passed to a service operation

If your service operation receives a "Data Contract" parameter or a "Message Contract" parameter, you actually use the validation logic specified for them. For example, this a Data Contract of order data that has validation logic that makes sure that the input currency is one of a pre-defined domain of values.

C#
[DataContract]
public class OrderData
{
    [DataMember]
    public double Amount
    {
        get { return amount; }
        set { amount = value; }
    }

    [DataMember]
    [DomainValidator("USD","EUR","JPY")]
    public string Currency
    {
        get { return currency; }
        set { currency = value; }
    }
}

Now, when you use it in a service contract definition, you don't have to specify the validation for the input parameters, since it will be taken from the Data Contract definition.

C#
[OperationContract]
OrderInfo CreateOrder(OrderData orderData);

Keep in mind that in order to validate an object, using attributes is not the only way to do so. If you need more flexibility you can do it using the configuration file. Using the configuration file for declaring the validation logic for types and objects are out of scope for this article.

Extending the Service Contract with Validation Behavior

As I will discuss in more details later, the "Validation Application Block" extension to WCF is done using a ValidationBehavior. A WCF behavior is a component that controls various run-time aspects of a service, an endpoint, a particular operation, or a client, and can be configured via attributes or configuration. Same goes for the Validation Behavior.

Using attributes to Configure Validation

One way to add the validation behavior to the service is to set the [ValidationBehavior] attribute above the service contract. This attribute adds a ValidationParametersInspector to each operation runtime definition in order to be executed each time a service operation is called.

C#
[ServiceContract]
[ValidationBehavior]
public interface IOrdersService
{
    ...
}

Configuring Validation using Configuration File

The first thing you should do in order to configure the validation application block extension to WCF is to declare the Validation Behavior Extension in the system.serviceModel section:

XML
<configuration>
  <system.serviceModel>

    <extensions>
      <behaviorExtensions>
        <add name="validation"
             type="Microsoft.Practices.EnterpriseLibrary.
            Validation.Integration.WCF.ValidationElement, 
            Microsoft.Practices.EnterpriseLibrary.Validation.
            Integration.WCF, Version=3.0.0.0, Culture=neutral, 
            PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>

  </system.serviceModel>
</configuration>

This declaration in the configuration file allows you to configure an Endpoint Behavior that uses definitions in a configuration element specified in that extension. In our case, this is the ValidationElement, which has two attributes: enabled (true/false) and ruleset (string).

The definition of this endpoint behavior will look like this:

XML
<configuration>
  <system.serviceModel>

    <behaviors>
      <endpointBehaviors>
        <behavior name="Validation">
          <validation enabled="true" ruleset="myruleset"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

While using the [ValidationBehavior] attribute adds a service-level behavior to the service, using the configuration approach adds an endpoint-level behavior. This way, if you expose multiple endpoints for your service you have more flexibility in changing the validation rules between the endpoint, but basically, the effect is the same in both approaches.

In order to relate an endpoint to the above behavior, you have to add the behaviorConfiguration attribute to the endpoint definition.

Here is a complete configuration snippet that shows the configuration needed in order to add the validation to the service endpoints.

XML
<configuration>
  <system.serviceModel>

    <extensions>
      <behaviorExtensions>
        <add name="validation"
             type="Microsoft.Practices.EnterpriseLibrary.Validation.
                    Integration.WCF.ValidationElement,
                   Microsoft.Practices.EnterpriseLibrary.Validation.
                            Integration.WCF,
                  Version=3.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>

  </system.serviceModel>
</configuration>

<configuration>
  <system.serviceModel>

    <behaviors>
      <endpointBehaviors>
        <behavior name="Validation">
          <validation enabled="true" ruleset="myruleset"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

<configuration>
  <system.serviceModel>
    <services>
      <service name="Bursteg.Samples.WCFIntegration.Services.OrdersService">

        <endpoint address="http://localhost:8080/OrdersService"
                  binding="basicHttpBinding"
                  behaviorConfiguration="Validation"
                  contract="Bursteg.Samples.WCFIntegration.
                ServiceContracts.IOrdersService" />
      </service>
    </services>

    <behaviors>
      <endpointBehaviors>
        <behavior name="Validation">
          <validation enabled="true" ruleset="myruleset"/>
        </behavior>
      </endpointBehaviors>

    <extensions>
      <behaviorExtensions>
        <add name="validation"
            type="Microsoft.Practices.EnterpriseLibrary.Validation.
            Integration.WCF.ValidationElement, 
            Microsoft.Practices.EnterpriseLibrary.Validation.
            Integration.WCF, Version=3.0.0.0, Culture=neutral, 
            PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>

  </system.serviceModel>
</configuration>

Return value in case of invalid parameters

The Validation Application Block inspector intercepts calls to service operations and performs logic for validating the parameters passed to that operation. What happens if the parameters are found invalid is that the actual service operation never gets executed, and an exception (actually a Fault) is thrown back to the client.

Validation Results

When using the standard code to validate on object, we usually use the following code snippet. We validate the target object, receive back a ValidationResults object that contains the list of validation results that were returned by the validators that were executed in this validation.

C#
Validator validator = ValidationFactory.CreateValidator<orderdata />();
ValidationResults results = validator.Validate(myOrderData);
foreach (ValidationResult result in results)
{
    ...
}

With WCF Services things are a little bit different, since we do not initiate the objects validation, but the Validation Application Block integration with WCF component does. If the parameters are found invalid, this component throws a FaultException<ValidationFault> which is translated to a Soap Fault on the wire. The ValidationFault class (similar to ValidationResults) contains an array of ValidationDetails items which are similar to ValidationResult items that contain the validation message, key and tag.

The WCF Fault Handling is a basic subject that one should be familiar with and it is not part of this article, but what is important to mention is that if you want to be able to catch this exception in the client, and get the details about the validation errors, there are two things that you want to do:

  1. Specify the FaultContract attribute for each service operation that has a validation attached to it (or its parameters), and give the ValidationFault class as the type of the fault:

    C#
    [ServiceContract]
    public interface IOrdersService
    {
        [FaultContract(typeof(ValidationFault))]
        [OperationContract]
        OrderInfo CreateOrder(OrderData orderData);
    }

  2. Use the following code to catch the validation exception and investigate the validation details.

    C#
    try
    {
        // Call the service operation
    }
    catch (FaultException<ValidationFault> ex)
    {
        // Extract the Detail node from the Fault Exception. 
        // This details is the
        // ValidationFault class
        ValidationFault fault = ex.Detail;
    
        // Iterate through the list of validation errors
        Console.WriteLine("Fault Occurred:");
        foreach (ValidationDetail validationResult in faults.Details)
        {
            Console.WriteLine(string.Format("Message={0} Key={1} Tag={2}",
                validationResult.Message, validationResult.Key, 
                        validationResult.Tag));
        }
    }

WCF Extensibility

Parameter Inspector

WCF has many extensibility points over its layers. You can extend the Service Model, the Channel Layer, the Messaging Layer and so on. One of ways to extend WCF is using a "Parameter Inspector". A parameter inspector enables inspection or modification of information prior to and subsequent to calls on either the client or the service. In order to implement a parameter inspector, one should implement the IParameterInspector Interface:

C#
public interface IParameterInspector
{
    void AfterCall(string operationName, object[] outputs, 
            object returnValue, object correlationState);
    object BeforeCall(string operationName, object[] inputs);
}

Operation Description

Without getting into much details about it, WCF separates the static descriptions of the operations, contracts and endpoints and the runtime definitions of them. When you create a proxy on the client or when you create a Service Host on the server, WCF builds the runtime description of the contracts, operations and endpoints. During this creation of the runtime description, all the behaviors and extensions are added.

You can use the following code in order to get a reference to the OperationDescription which you want to add the parameter inspector to, and see in runtime what are the values of its properties:

C#
public OperationDescription GetOperationDescription(Type contractType, 
                            string operationName)
{
    ContractDescription contract = new ContractDescription(contractType.Name);
    OperationDescription operation = new OperationDescription
                        (operationName, contract);
    operation.SyncMethod = contractType.GetMethod(operationName);
    return operation;
}

Once you have the OperationDescription, you can create an instance of the ValidationParameterInspector:

C#
ValidationParameterInspector validationInspector = 
        new ValidationParameterInspector(operation, "myRuleset");

Now, you can test the validation of your service operations without having to use a client:

C#
try
{
    // Create the data contract parameter to pass to the operation
    OrderData orderData = new OrderData();
    orderData.Amount = 3.0;
    orderData.Currency = "ASD";

    validationInspector.BeforeCall("CreateOrder", new object[] { orderData });
}
catch (FaultException<ValidationFault> e)
{
    ValidationFault fault = e.Detail;
    DisplayFault(fault);
}

One thing you should know is that the ValidationParameterInspector has implementation only for the BeforeCall method (makes sense...), so you should not test the AfterCall method.

Validation Behavior

As I mentioned in an earlier post, you can use the ValidationBehavior attribute above a service contract to tell the WCF runtime to add the validation behavior. This behavior implements both IEndpointBehavior and IContractBehavior interfaces apply extensions to the runtime service contract and endpoint descriptions. In the case of the Validation Application Block, this behavior adds the above Parameter Inspector.

Using the code

This article contains a sample project that uses the Validation Application Block Extensions for WCF. It shows both the parameter-level validation and message level validation, and contains the configuration needed to run the sample with validation logic. It is a good place to start in order to get a feel of the topics I have talked about in this article.

Screenshot - WCFVAB2.gif

Conclusion

The usage of Validation Application Block with WCF can reduce the amount of code we have to write in order to validate the service messages. It separates the validation logic from the business logic and gives us the flexibility to control the validation with configuration files. In this article I have described the Validation Application Block extension for Windows Communication Foundation. I have talked about parameter-level and message-level validation, and how do enable validating in your service contracts or endpoint by code or configuration.

History

  • April 14, 2007 – Created

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Israel Israel
Guy Burstein is a senior consultant and lecturer at Advantech Technologies – Microsoft Division, specializing in architecture, design and development of distributed applications.
He is a presenter at conferences and user-group meetings and has delivered seminars, courses and hands-on training for developing distributed applications using latest Microsoft tools and technologies.

Comments and Discussions

 
Generalgood ..thanks Pin
George__Washington11-Jun-07 22:17
George__Washington11-Jun-07 22:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.