WCF Message validation (1) – WCF samples to the rescue
Recently, I needed to validatie messages going into a WCF service. It turned out the WCF samples are a rich source of knowledge and I found a sample which performs XMLSchema-based validation in \TechnologySamples\Extensibility\MessageInspectors.
The sample contains a few classes:
- ClientValidationException.cs
- Defines exceptions where validation fails clientside
- SchemaValidationBehavior.cs
- Defines an implementation of IEndpointBehavior in order to be an extender for defined endpoints
- SchemaValidationBehaviorExtensionElement.cs
- Inherits from BehaviorExtensionElement, used for configuration-time binding
- SchemaValidationMessageInspector.cs
- Contains the actual validation code, implementing IClientMessageInspector and IDispatchMessageInspector.
- ValidationFault.cs
- Defines FaultExceptions used within the code.
The sample uses a property called Schemas within it’s configuration, allowing us to define which schemas should be taken into account when validating.
<schemaValidator validateRequest="True" validateReply="True">
<schemas>
<add location="messages.xsd" />
</schemas>
</schemaValidator>
That’s great, but as you all probably know, WCF services have the ABC’s: Address, Binding and Contract. What I actually wanted the behavior to do was validate my message against the actual Contract of the endpoint the validator was working on.
In order for this to work, I did two thing:
1. I removed all “Schemas” configuration and arguments from the code.
2. I modified the SchemaValidationBehavior class to validate the actual contract.
The first steps should be self-explanatory, but the second I want to elaborate on. What I actually did was modify the methods ApplyClientBehavior and ApplyDispatchBehavior. The sample took the configured Schemas property to create the actual SchemaValidationMessageInspector:
SchemaValidationMessageInspector inspector =
new SchemaValidationMessageInspector(
schemaSet, validateRequest, validateReply, false);
I wanted to dynamically use the endpoint contract:
WsdlExporter exporter = new WsdlExporter();
exporter.ExportContract(endpoint.Contract);
SchemaValidationMessageInspector inspector =
new SchemaValidationMessageInspector(
exporter.GeneratedXmlSchemas,
validateRequest, validateReply, false);
After modifying both methods to perform this kind of setup, it was easy to configure validation based on the endpoint contract (some elements abbreviated for clarity):
<system.serviceModel>
<services>
<service name="SomeService">
<endpoint
address="SomeAddress"
binding="wsHttpBinding"
contract=" ISomeService"
behaviorConfiguration="SomeServiceEndpointBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="SomeServiceEndpointBehavior">
<SchemaValidator
validateRequest="True"
validateReply="True" />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add
name="SchemaValidator"
type="SchemaValidationBehaviorExtensionElement, ..."/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
That’s it, now we have a service endpoint validated based on it’s WSDL contract.
The sample code is attached for your enjoyment.
Comments
Anonymous
May 13, 2007
Hi, Have you heard of the Validation Application Block Integration with WCF? http://www.codeproject.com/useritems/WCFVAB.asp Guy BursteinAnonymous
May 13, 2007
Hi Guy, Yes, I know of the Validation Application Block. Although there are many good things you can do with the VAB, I agree, it involves altering my contract in code, which I don't particularly like for my situation. I'm building towards Contract-First WCF services, where an XML schema defines the data, not a class. This is done for versioning purposes. I was actually planning on doing a second article (hence the (1) in the title ;-)) on WCF integration for the Validation Application Block in Enterprise Library v3.0. With your article on codeproject, there's little for me to add to that :). Thanks, MartijnAnonymous
May 13, 2007
Rimando ad un post interessante che illustra un'estensione WCF che può effettivamente risultare utileAnonymous
August 19, 2007
The comment has been removedAnonymous
November 24, 2007
Just wanted to support you on this thing with Validation Block. It is amazing how somebody can believe that making validation decisions as a part of the assembly metadata can actually work in the real world scenario.Anonymous
August 15, 2008
We are trying to do a similar thing... We are starting out with a schema that contains xsd:restrictions and when svcutil.exe is used to generate our service these restrictions (lenght for example) are lost. So we would like to validate against the schema we generated our service from. But when you ask WCF for the wsdl it replies by doing som self-inspection and generate a wsdl on the fly, and that wsdl doesn't contain our restrictions. Do you have a solution to this problem? You state that you want to go contract-first so I presume that you start out with a wsdl-file and generate your service from it. Any tip would be greatly appriceated, this is really frustating. I want validation. And I want it now! ;)Anonymous
August 15, 2008
Hi Marcus, What I didn't realize is the introspection causes custom XSD modifiications to be removed. What you could do is use the original SDK sample. This sample allows you to point to the XSD with annotations. HTH