Integrating with WCF

Windows Communication Foundation (WCF) provides extension points that allow you to support custom scenarios such as checking security attributes and performing policy assertions. The Validation Application Block includes a WCF integration library that adds a custom behavior, and a parameter inspector. This extension allows the application block to validate WCF messages, data contracts, and parameters.

When the WCF service begins, it invokes the custom behavior. This custom behavior then adds the parameter inspector. WCF calls the parameter inspector twice for each message it processes. The first time is before it sends the call to the service implementation. The second time is after the service generates the return message. This section explains how you can use the Validation Application Block with your WCF applications. In general, you must do the following:

  • Include the Validation Application Block in your service contract.
  • Define a behavior that uses the application block.
  • Define an endpoint that uses the behavior.
  • Modify the service contract so that the client can receive relevant failure information.
  • Add validators to parameters as required.

Including the Validation Application Block

You can either use attributes or configuration to include the Validation Application Block in your service contract. The following sections discuss each approach.

Using Attributes

To use attributes, add the ValidationBehavior attribute to your service contract. This is shown in the following code example.

[ServiceContract(Namespace = "http://tempuri.org")]
[ValidationBehavior]
interface IMyService
{
  // ...
}
'Usage
<ServiceContract(Namespace = "http://tempuri.org")> _
<ValidationBehavior> _
Interface IMyService
  ' ...
End Interface

By adding this attribute, the application block automatically validates all input values that are associated with rule sets. You can specify the rule set to use by including the rule set name as an argument to the ValidationBehavior attribute. If you do not specify a specific rule set, it uses the default rule set. You can use different rule names for different operation or you can use a single name across the service contract.

You then add attributes to the members of your OperationContract interface to define the validation rules. You should not apply the validation attributes to the implementation of the interface.

Using Configuration

To use configuration, you must edit the <System.serviceModel> section of the configuration file. First register the behavior extension. This is shown in the following code example, which registers a behavior extension named "validation".

<system.serviceModel>
  ...
<extensions>
<behaviorExtensions>
<add name="validation"
           type="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF.ValidationElement,
             Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF" />
</behaviorExtensions>
</extensions>
</system.serviceModel>

Defining a Behavior

After you include the application block, you can define a behavior that uses it. You can use either a service behavior or an endpoint behavior. The following code example defines an endpoint behavior.

<system.serviceModel>
  <behaviors>
    <endpointBehaviors>
      <behavior name="ValidationBehavior">
        <validation enabled="true" ruleset="MyRuleset"/>
      </behavior>
    </endpointBehaviors>
    <serviceBehaviors>
      ...
    </serviceBehaviors>
    ...
  </behaviors>
  ...
<system.serviceModel>

This example specifies a rule set named "Bank2Rules" in the behavior element. If you do not specify a rule set, the application block uses the default rule set.

You can also define operation and contract behavior as in the following two examples.

<operationBehaviors>
  <behavior name="operationBehavior">
    <validation enabled="true" ruleset="MyRuleset"/>
  </behavior>
</operationBehaviors>

The following defines a contract behavior.

<contractBehaviors>
  <behavior name="contractBehavior">
    <validation enabled="true" ruleset="MyRuleset"/>
  </behavior>
</contractBehaviors>

Defining an Endpoint

Finally, define the endpoint that uses this behavior. This is shown in the following code example.

<service behaviorConfiguration="MyService_Behavior"
         name="MyServiceImplementation">
  ...
  <endpoint binding="basicHttpBinding"
            contract="MyTestService.IMyService"
            behaviorConfiguration="ValidationBehavior" /> 
  <endpoint address="mex" binding="mexHttpBinding"
            contract="IMetadataExchange" />
</service>

Reporting Validation Faults

If you want the client to receive relevant validation failure information, you must modify the service contract. To do this, use the FaultContract attribute, as demonstrated in the following code example. The implementation of the StartTransaction method of the IMyService interface and the implementations of the types for its parameter and return value are not shown here.

[ServiceContract]
[ValidationBehavior]
public interface IMyService
{
  [OperationContract]
  [FaultContract(typeof(ValidationFault))]
  StartTransactionResponse StartTransaction(request StartTransactionRequest);
}
'Usage
<ServiceContract> _
<ValidationBehavior> _
Public Interface IMyService
  <OperationContract> _
  <FaultContract(GetType(ValidationFault))> _
  StartTransactionResponse StartTransaction(request As StartTransactionRequest)
End Interface

Any time a client invokes the StartTransaction method, the rule sets that are associated with the StartTransactionRequest type run. If any of the validators included in the rule set fail, the service is not called and the client receives an exception of type FaultException<ValidationFault>. If you do not specify the FaultContract attribute, the client only receives the generic exception message and any specific validation error information is lost.

Validating Parameters

Because WCF messages and data contracts are all .NET types, they can be associated with validators either by using the standard validation attributes or with the configuration tools, just as you can for any other type. In most applications, you can apply validators to properties, fields, and methods in your OperationContract interface (not in the implementation of an interface). However, with WCF applications, you can also associate validators with specific parameters of a method. This is shown in the following code example.

void ValidateMyParameters(
  [NotNullValidator][RegexValidator(@”\d{3}-\d{2}-\d{4}”)]
  string ssn,
  [RangeValidator(5, RangeBoundaryType.Inclusive, 50, RangeBoundaryType.Inclusive)]
  int value)
{ 
  ... 
}
'Usage
Sub ValidateMyParameters( _
  <NotNullValidator()><RegexValidator("\D{3}-\D{2}-\D{4}")> _
  ByVal ssn As String, _
  <RangeValidator(5, RangeBoundaryType.Inclusive, 50, RangeBoundaryType.Inclusive)> _
  ByVal value As Integer)
  ...
End Sub

This example checks that one parameter is a non-null string that is formatted as a valid social security number and that the other parameter is an integer in the range of 5 to 50. This validation should occur within the operation contract.

For more information about WCF, see Windows Communication Foundation on MSDN.

Note

You can only validate parameters with attributes, and not with configuration.