How To: Perform Message Validation with Schema Validation in WCF

- J.D. Meier, Jason Taylor, Prashant Bansode, Carlos Farre, Madhu Sundararajan, Steve Gregersen

Applies To

  • Windows Communication Foundation (WCF) 3.5
  • .NET framework 3.5
  • Microsoft® Visual Studio® 2008

Summary

This How To article shows you how to perform message validation using schema in WCF. This article shows you how to create a custom client message inspector and dispatcher message inspector that can be used to validate messages on both the server and on the client.

Contents

  • Objectives
  • Overview
  • Summary of Steps
  • Step 1 – Create a Sample WCF Service
  • Step 2 – Configure the WCF Service to Use wsHttpBinding with Windows Authentication and Message Security
  • Step 3 – Create the Schema to Validate the Message
  • Step 4 – Create a Windows Class Library Project that Will Contain the Three Classes Necessary for Schema Validation
  • Step 5 – Create a Class that Implements the Schema Validation Logic
  • Step 6 – Create a Class that Implements a Custom Endpoint Behavior
  • Step 7 – Create a Class that Implements a Custom Configuration Element
  • Step 8 – Add the Custom Behavior to the Configuration File
  • Step 9 – Create an Endpoint Behavior and Map it to Use the Custom Behavior
  • Step 10 – Configure the Service Endpoint to Use the Endpoint Behavior
  • Step 11 – Test the Parameter Validator
  • Deployment Considerations
  • Additional Resources

Objectives

  • Learn how to create a custom configuration element that will allow exposing the custom endpoint behavior in configuration file.
  • Learn how to create a custom endpoint behavior that will consume the client and dispatcher message inspectors.
  • Learn how to create a custom client and dispatcher message inspectors to validate messages using schemas.

Overview

Message validation represents one line of defense in the protection of your WCF application. Validate messages using schemas to protect WCF service operations from attack by a malicious client. Validate all messages received by the client to protect the client from attack by a malicious service. Message validation provides a way to validate messages when operations consume message contracts or data contracts, not possible to validate with parameter validation. Message validation allows creating validation logic inside schemas, providing more flexibility and less development time. Schemas can be reused across different applications inside the organization, creating standards for data representation. Additionally message validation allows you to protect operations when they consume more complex data types, involving contracts representing business logic.

To perform message validation, you will build a schema that represents the operations of your service and the types consumed by those operations. Then you will create .NET class that implements a custom client message inspector and custom dispatcher message inspector to validate the messages sent/received to/from the service. You then will implement a custom endpoint behavior to enable message validation on both the client and the service. Finally, you will implement a custom configuration element on the class that allows you to expose the extended custom endpoint behavior in the configuration file of the service or the client.

Summary of Steps

  • Step 1 – Create a Sample WCF Service
  • Step 2 – Configure the WCF Service to Use wsHttpBinding with Windows Authentication and Message Security
  • Step 3 – Create the Schema to Validate the Message
  • Step 4 – Create a Windows Class Library Project that Will Contain the Three Classes Necessary for Schema Validation
  • Step 5 – Create a Class that Implements the Schema Validation Logic
  • Step 6 – Create a Class that Implements a Custom Endpoint Behavior
  • Step 7 – Create a Class that Implements a Custom Configuration Element
  • Step 8 – Add the Custom Behavior to the Configuration File
  • Step 9 – Create an Endpoint Behavior and Map it to Use the Custom Behavior
  • Step 10 – Configure the Service Endpoint to Use the Endpoint Behavior
  • Step 11 – Test the Parameter Validator

Step 1 – Create a Sample WCF Service

In this step you will create a WCF service in Visual Studio, hosted in an IIS virtual directory.
  1. In Visual Studio select File -> New Web Site.
  2. In the New Web Site dialog box, under Templates section select WCF Service. Make sure that the Location is set to Http .
  3. In the New Web Site dialog box, set the new Web site address to http://localhost/WCFTestSchemaValidation and click Ok.
  4. Create a data contract that will have the class CustomerData. This data contract will be consumed by the operation of your service. Double click the IService.cs file in Visual studio. Copy and paste the below code snippet at the bottom of IService.cs file.
  5. DataContract(Namespace "http://Microsoft.PatternPractices.WCFGuide")
public class CustomerData
{
    [DataMember]
    string text;
    [DataMember]
    int CustomerID;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }

    public int customerid
    {
        get { return CustomerID; }
        set { CustomerID = value; }
    }
}
  1. Change the definition of the GetData operation contract to use CustomerData type. Double click IService.cs. Go to the top of the file and replace the previous definition with the new one

Previous operation contract
[OperationContract]
string GetData(int value);

New operation contract
[OperationContract]
CustomerData GetData(CustomerData CustomerInfo);
  1. Change the implementation of the GetData operation contract to use CustomerData type. Double click Service.cs. Go to the top of the file and replace the previous definition with the new one

Previous operation contract implementation
public string GetData(int value)
{
    return string.Format("You entered: {0}", value);
}

New operation contract implementation
public CustomerData GetData(CustomerData CustomerInfo)
{
   CustomerData CustomerInfoResponse = new CustomerData();
   CustomerInfoResponse.Text = CustomerInfo.Text;
   CustomerInfoResponse.customerid = CustomerInfo.customerid+1;
   return CustomerInfoResponse;
}
  1. Add the namespace definition to conform to your schema that is going to be created. Double click IService.cs file and add the string (Namespace = "http://Microsoft.PatternPractices.WCFGuide") after ServiceContract entry in that file. Your service contract entry will be like below fragment.

[ServiceContract(Namespace = "http://Microsoft.PatternPractices.WCFGuide")]

Step 2 – Configure the WCF Service to use wsHttpBinding with Windows Authentication and Message Security

By default your WCF service will be configured to use wsHttpBinding with message security and Windows authentication. Verify that your web.config configuration file looks as below:
…
<services>
  <service name="Service" behaviorConfiguration="ServiceBehavior">
    <!-- Service Endpoints -->
    <endpoint address="" binding="wsHttpBinding" contract="IService">
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
  </service>
</services> 
…

Step 3 – Create the Schema to Validate the Message

In this step you will create the schema to validate the message.
  1. Right click the http://localhost/WCFTestSchemaValidation project and select Add New Item.
  2. Select Xml Schema from the visual studio installed templates and give the name SchemaValidation in the name text box. Select Visual C# as language and click Add
  3. In Visual Studio editor delete the whole content of this file. Copy and paste the below schema definition
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://Microsoft.PatternPractices.WCFGuide" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Microsoft.PatternPractices.WCFGuide">
  <xs:element name="GetData">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="CustomerInfo" nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:complexType name="CustomerData">
    <xs:sequence>
      <xs:element name="CustomerID" type="tns:CustIDLimitor">
      </xs:element>
      <xs:element name="text" type="tns:CustomerN">
      </xs:element>     
    </xs:sequence>
  </xs:complexType>
  <xs:simpleType name="CustomerN">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
      <xs:maxLength value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CustIDLimitor">
    <xs:restriction base="xs:int">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="GetDataResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" name="GetDataResult" nillable="false" type="tns:CustomerData" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The schema first defines GetData operation contract that takes a type CustomerData as a parameter being instantiated by CustomerInfo being passed to the operation call. CustomerData has to exist and cannot be null
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" targetNamespace="http://Microsoft.PatternPractices.WCFGuide" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Microsoft.PatternPractices.WCFGuide">
  <xs:element name="GetData">
    <xs:complexType>
      <xs:sequence>
        *<xs:element minOccurs="1" name="CustomerInfo" nillable="false" type="tns:CustomerData"/>*
      </xs:sequence>
    </xs:complexType>
  </xs:element>

CustomerData is a complex type; it has data members CustomerID and text. CustomerID and text are of type CustIDLimitor and CustomerN.
  <xs:complexType name="CustomerData">
    <xs:sequence>
      <xs:element name="CustomerID" type="tns:CustIDLimitor">
      </xs:element>
      <xs:element name="text" type="tns:CustomerN">
      </xs:element>     
    </xs:sequence>
  </xs:complexType>

CustomerN and CustIDLimitor are just schema facets: they are simple types: string and integer that serve to limit the length and value of the string and integer. In the fragment below string is limited to 1 and 5 characters in length and integer is limited to range values of 1 and 5.
  <xs:simpleType name="CustomerN">
    <xs:restriction base="xs:string">
      <xs:minLength value="1" />
      <xs:maxLength value="5" />
    </xs:restriction>
  </xs:simpleType>
  <xs:simpleType name="CustIDLimitor">
    <xs:restriction base="xs:int">
      <xs:minInclusive value="1" />
      <xs:maxInclusive value="5" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema> 

The GetDataResponse element it is a response from GetData. It returns a CustomerInfoResponse with type CustomerData, so the response will be also tested
  <xs:element name="GetDataResponse">
    <xs:complexType>
      <xs:sequence>
        *<xs:element minOccurs="1" name="GetDataResult" nillable="false" type="tns:CustomerData" />*
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Step 4 – Create a Windows Class Library Project that Will Contain the Three Classes Necessary for Schema Validation

In this step you will create a Windows class library project that will have three classes for the schema validation:
  • One class to implement the schema validation logic
  • A second class to implement the endpoint behavior that will use the schema validation class
  • A third class to implement a behavior extension so that the validator will be visible in the service and client configuration files

Use the following steps:
  1. Open a new instance of Visual Studio, leaving your WCF service solution still open.
  2. In the new instance of Visual Studio click File, New, then Project.
  3. Expand Visual C#, click on Windows, then select Class Library.
  4. In the Name field, enter MySchemaValidationClass and click OK.
  5. Right click on References in the Solution Explorer, click Add Reference, select the .NET tab, select System.ServiceModel, and then click Ok.
  6. Right click on References in the Solution Explorer, click Add Reference, select the .NET tab, select System.Configuration, and then click Ok.
  7. Open the Class1.cs file and rename the class name from Class1 to Validation.
  8. Add the following using statements to the top of the Class1.cs file.
{{
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

Step 5 – Create a Class that Implements the Schema Validation Logic

In this step you will create a new class, derived from interfaces IClientMessageInspector and IDispatchMessageInspector; to implement the schema validation logic for both the client and the dispatcher.

The newly created class has the following characteristics:
It implements AfterReceiveRequest(),BeforeSendReply(),BeforeSendRequest() and AfterReceiveReply() methods.
# On the dispatcher: AfterReceiveRequest will happen when inbound messages are received by the dispatcher, before the operation is invoked and deserialization of messages has occurred. If message is encrypted, decryption will take place first. BeforeSendReply will happen when outbound messages are to be sent back to the client. It will happen after operation is invoked, and after serialization has occurred. If message is encrypted, encryption will not take place.
# On the client: BeforeSendRequest will happen when outbound messages are sent by the client, after serialization has occurred. If message is encrypted, encryption will not take place. AfterReceiveReply will happened when inbound messages are received by the client before deserialization of message has occurred. If message is encrypted, decryption will take place first.
# ValidateMessage will validate the message with regards of the schema definition. If validation succeeds a new message is constructed and returned to the caller. On the dispatcher side either a new message is returned before operation invocation or before sending response to the client. On the client before sending the message to the service or before returning to the application

In this example a simple schema validation logic is implemented by simply traversing the XmlReader. If validation fails then a fault exception or a message is returned to the client.

Copy and paste the code snippet below to the class1.cs file:
public class SchemaValidation
  {
     public class SchemaValidationMessageInspector : IClientMessageInspector,IDispatchMessageInspector
      {
          XmlSchemaSet schemas;
          public SchemaValidationMessageInspector(XmlSchemaSet schemas)
          {
              this.schemas = schemas;
          }
          void validateMessage(ref System.ServiceModel.Channels.Message message)
          {
              XmlDocument bodyDoc = new XmlDocument();
                bodyDoc.Load(message.GetReaderAtBodyContents());
              XmlReaderSettings settings = new XmlReaderSettings();
              settings.Schemas.Add(schemas);
              settings.ValidationType = ValidationType.Schema;
              XmlReader r = XmlReader.Create(new XmlNodeReader(bodyDoc), settings);
              while (r.Read()) ; // do nothing, just validate
              // Create new message 
              Message newMsg = Message.CreateMessage(message.Version, null,
                  new XmlNodeReader(bodyDoc.DocumentElement));
              newMsg.Headers.CopyHeadersFrom(message);
              foreach (string propertyKey in message.Properties.Keys)
                  newMsg.Properties.Add(propertyKey, message.Properties[propertyKey]);
              // Close the original message and return new message 
              message.Close();
              message = newMsg; 
          }

          object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
          {
              try{
                  validateMessage(ref request);
               }*      
          catch (FaultException e)
          {
              throw new FaultException<string>(e.Message);
          }
          return null;
             
          }

          void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
          {
              try
              {
                  validateMessage(ref reply);                
              }
              catch (FaultException fault)
              {
                  // if a validation error occurred, the message is replaced
                  // with the validation fault.
                  reply = Message.CreateMessage(reply.Version, new FaultException("validation error in reply message").CreateMessageFault() , reply.Headers.Action);
              }
              
          }
   
          void IClientMessageInspector.AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
          {
              validateMessage(ref reply);               
          }

          object IClientMessageInspector.BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
          {
              validateMessage(ref request);
              return null;
          }            
        }
  }

Step 6 – Create a Class that Implements a Custom Endpoint Behavior

In this step you will create a new class, derived from IEndpointBehavior, that implements a custom endpoint behavior.

The newly created class has the following characteristics:
  1. It implements ApplyClientBehavior() to add the SchemaValidationMessageInspector to the client operation and enable client side validation.
  2. It implements ApplyDispatchBehavior() to add the SchemaValidationMessageInspector to the dispatch operation and enable service side validation.
  3. It verifies that it is enabled in the configuration before adding the SchemaValidationMessageInspector r to the client or dispatch runtime.

Copy and paste the below code snippet to the Class1.cs file, inside the Validation class that already exists:
class SchemaValidationBehavior : IEndpointBehavior
{
    private bool enabled;
    private XmlSchemaSet schemaSet; 
   

    internal SchemaValidationBehavior(bool enabled,XmlSchemaSet schemaSet)
    {
        this.enabled = enabled;
        this.schemaSet = schemaSet;
    }

    public bool Enabled
    {
        get { return enabled; }
        set { enabled = value; }
    }

    public void AddBindingParameters(ServiceEndpoint serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    { }

    public void ApplyClientBehavior(
      ServiceEndpoint endpoint,
      ClientRuntime clientRuntime)
    {
        //If enable is not true in the config we do not apply the Parameter Inspector
        if (false == this.enabled)
        {
            return;
        }
        SchemaValidationMessageInspector inspector = new SchemaValidationMessageInspector(schemaSet);
        clientRuntime.MessageInspectors.Add(inspector);               
    }

    public void ApplyDispatchBehavior(
       ServiceEndpoint endpoint,
       EndpointDispatcher endpointDispatcher)
    {
        //If enable is not true in the config we do not apply the Parameter Inspector
        if (false == this.enabled)
        {
            return;
        }
        SchemaValidationMessageInspector inspector = new SchemaValidationMessageInspector(schemaSet);
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);  
    }

    public void Validate(ServiceEndpoint serviceEndpoint)
    {

    }

    
}

Step 7 – Create a Class that Implements a Custom Configuration Element

In this step you will create a new class, derived from BehaviorExtensionElement, that implements a custom configuration element.

The newly created class has the following characteristics:
  1. It implements CreateBehavior() to create an instance of the SchemaValidationBehavior class. Inside the method a schema set is initialized with the schema that reads the base directory of the application loading the SchemaValidation.xsd file created before. The schema set is passed to the Schemavalidation behavior that will pass it to the schema inspector.
  2. It implements BehaviorType() to return the SchemaValidationBehavior type. This will allow the custom behavior to be exposed in the service or client configuration sections.
  3. It implements ConfigurationProperty to allow the behavior to be enabled or disabled in the WCF configuration files.

Copy and paste the below code snippet to the Class1.cs file, inside the Validation class that already exists:
public class CustomBehaviorSection : BehaviorExtensionElement
{

    private const string EnabledAttributeName = "enabled";

    [ConfigurationProperty(EnabledAttributeName, DefaultValue = true, IsRequired = false)]
    public bool Enabled
    {
        get { return (bool)base[EnabledAttributeName]; }
        set { base[EnabledAttributeName] = value; }
    }

    protected override object CreateBehavior()
    {
       XmlSchemaSet schemaSet = new XmlSchemaSet();
       Uri baseSchema = new Uri(AppDomain.CurrentDomain.BaseDirectory);
       string mySchema = new Uri(baseSchema,"SchemaValidation.xsd").ToString();
       XmlSchema schema = XmlSchema.Read(new XmlTextReader(mySchema), null);
       schemaSet.Add(schema);
       return new SchemaValidationBehavior(this.Enabled,schemaSet);

    }

    public override Type BehaviorType
    {

        get { return typeof(SchemaValidationBehavior); }


    }
}

Step 8 – Add the Custom Behavior to the Configuration File

In this step you will add the custom behavior to the behavior element extension in the WCF configuration file so it can be used by the WCF endpoint.
  1. Compile your schema validation class library solution to create MySchemaClassValidation.dll
  2. Return to the original instance of Visual Studio that contains your WCF service solution.
  3. Right click on the WCF Web site project and click Add Reference. Navigate to the folder containing the MySchemaClassValidation.dll and click add.
  4. Right click on the web.config and click Edit WCF configuration.
  5. If you do not see the Edit WCF Configuration option, on the Tools menu, click WCF Service Configuration Editor. Close the WCF Service Configuration Editor tool that appears. The option should now appear on the web.config context menu.
  6. Expand the Services node and the Extensions node** and then click on behavior element extensions.
  7. Click the New button.
  8. In the Name field enter SchemaValidator.
  9. Select the Type field, click on the button that appears to the right, navigate to the folder containing MySchemaClassValidation.dll and double click the dll file.
  10. Double click the type name MySchemaValidationClass.SchemaValidation+CustomBehaviorSection and click OK.
  11. Click File then Save in the WCF configuration editor.

Verify that your configuration file contains the following:
<system.*ser*viceModel>
  ...
<extensions>
      <behaviorExtensions>
        <add name="SchemaValidator" type="MySchemaValidationClass.SchemaValidation+CustomBehaviorSection, MySchemaValidationClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      </behaviorExtensions>
    </extensions>
 ... 
 <system.serviceModel>

Step 9 – Create an Endpoint Behavior and Map it to Use the Custom Behavior

In this step you will create an endpoint behavior and map it to the custom behavior created in Step 7.
  1. In the WCF configuration editor, expand the Advanced node, right click on Endpoint Behavior, and click New Endpoint Behavior Configuration.
  2. Select the new behavior and enter MyEndPointBehavior in the Name field.
  3. Click Add, select the SchemaValidator custom behavior, and click Add.
  4. Click File then Save in the WCF configuration editor.

Verify that your configuration file contains the following:
<behaviors>
  ...
<endpointBehaviors>
        <behavior name="MyEndPointBehavior">
          <SchemaValidator />
        </behavior>
      </endpointBehaviors>
 ...  
 </behaviors>

Step 10 – Configure the Service Endpoint to Use the Endpoint Behavior

In this step you will configure the service to use the endpoint behavior to consume the custom validator.
  1. In the WCF configuration editor, expand the Service node and then expand Endpoints.
  2. Select the first Empty Name* node.
  3. In the BehaviorConfiguration field select MyEndPointBehavior
  4. Click File then Save in the WCF configuration editor.

Verify that your configuration file contains the following:
<endpoint address="" behaviorConfiguration="MyEndPointBehavior"
          binding="wsHttpBinding" contract="IService">
          <identity>
            <dns value="localhost" />
          </identity>
</endpoint>

Step 11 - Test the Parameter Validator

In this step you will create a sample WCF client to test your validator.
  1. Right-click your WCF service solution, click Add and then click New Project
  2. In the Add New Project dialog box, select Windows Forms Application from the Templates section.
  3. In the Name field, type Test Client and click Ok.
  4. Right-click your client project and select Add Service Reference.
  5. In the Add Service Reference dialog box set the Address field to http://localhost/WCFTestSchemaValidation and click Go.
  6. Set the Namespace field to WCFTestService and click Ok.
  7. Open the designer for your new Windows form.
  8. Drag 3 text box controls to the designer
  9. Drag a button control to the designer.
  10. Double-click the button to show the code behind.
  11. In the code behind the button, create an instance of the WCF service proxy, and call the GetData() method on your WCF Service.
try
{
      WCFTestService.CustomerData CustomerInfo = new WindowsFormsApplication1. WCFTestService.CustomerData();
      CustomerInfo.text = textBox1.Text;
      CustomerInfo.CustomerID = int.Parse(textBox2.Text);
      WCFTestService.ServiceClient proxy = new WindowsFormsApplication1. WCFTestService.ServiceClient();
      WCFTestService.CustomerData CustomerInfoResponse = proxy.GetData(CustomerInfo);
      textBox3.Text = CustomerInfoResponse.text;
      proxy.Close();
}

catch (FaultException ex)
{
     textBox3.Text = ex.Message;
}

Right click on the client project and select Set as Startup Project.
Run the client application using F5 or Ctrl+F5 and click the button. In the textbox1 and textbox2 enter a value text and integer(text maximum of 5 characters integer in range value 1 and 4. If you enter 5 it will cause an exception in the validation of the response. The application will display a message in textbox3 with the text enter in the textbox1 for the correct value (input between 1 and 5) or a validation error for the incorrect values.

Deployment Considerations

  • Do not divulge exception errors to clients in production. Instead develop a fault contract and return it to your client inside the AfterReceiveRequest()e
  • Do not divulge exception errors after BeforeSendReply(). Instead develop a fault contract and build a error message with the fault contract and return it to the client.
  • For client side validation follow the same steps of this how to but instead use the app.config of the client consuming the service.
  • Consider caching the schema for performance benefits.
  • Consider more advanced schema validation logic that provided in this how to download sample in http://msdn2.microsoft.com/en-us/library/aa717047.aspx

Additional Resources

Contributors and Reviewers

  • External Contributors and Reviewers:
  • Microsoft Consulting Services and PSS Contributors and Reviewers:
  • Test team: Rohit Sharma, Chaitanya Bijwe, Parameswaran Vaideeswaran.
  • Edit team: Dennis Rea.
  • SEO team: Rob Boucher.

Last edited Apr 30, 2008 at 9:52 PM by prashantbansode, version 2

Comments

darrenwwwa Dec 1, 2009 at 11:09 AM 
Is schema validation possible with webHttpBinding?

I would think that validating incoming messages with a schema on a WCF web service would be standard, but I cannot find anything about it.

Please help.
Thanks!

yazidarezki May 19, 2008 at 11:10 AM 
Excellent lab,

Are these Typos?

1 In step 4, in the code you have something like:

{{
public class SchemaValidation
{
public class SchemaValidationMessageInspector

}}

A class inside another class, I did not need that to get it working.

2 In step 8 you have:

{{
<system.serviceModel>
...
<extensions>
<behaviorExtensions>
<add name="SchemaValidator" type="MySchemaValidationClass.SchemaValidation+CustomBehaviorSection, MySchemaValidationClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
...
<system.serviceModel>
}}

In my config I had:

type="MySchemaValidationClass.CustomBehaviorSection

instead of

type="MySchemaValidationClass.SchemaValidation+CustomBehaviorSection

Regards
Yaz