Walkthrough: Creating a Policy Assertion

The Web Services Enhancements for Microsoft .NET (WSE) has built-in support for the following policy assertions:

  • Security token
  • Integrity
  • Confidentiality
  • Message age
  • Message predicate

If a Web service must enforce a policy that is not already handled by WSE, the Web service must provide a policy assertion for the policy, as well as custom code to enforce the assertion on the send side and to verify it on the receive side.

Goals of the Walkthrough

This walkthrough illustrates how to create a policy assertion for the following scenario:

  • You have been asked to develop an online chat and forum service for children. The service policy must specify that all messages be checked for unacceptable content before being sent. If they pass the test, the assertion on the client adds a header that the policy assertion when receiving the message at the service expects.

During this walkthrough, you will learn how to:

  • Create a new solution with a Web service and a client application.
  • Define the policy assertion.
  • Write code to verify the policy

Map the policy assertion to the Web service and client application.

Creating the Solution

The first step is to create a solution in Visual Studio .NET 2003 that contains two projects: a Web service and a Web service client.

To create the solution

  1. On the File menu, point to New, and then click Project.

  2. In the New Project dialog box, under Project Types, click Visual Studio Solutions.

  3. Under Templates, click Blank Solution.

  4. In the Name box, type a name for the solution.

To create the Web service project

  1. On the File menu, point to Add Project, and then click New Project.

  2. In the Add New Project dialog box, under Project Types, click Visual C# Projects.

  3. Under Templates, click ASP.NET Web Service.

  4. In the Location box, type the address of the Web server on which you will develop the XML Web service.

    For example, to develop in the root directory, enter https://www.contoso.com/Application or https://www.contoso.com.

  5. Click OK to create the project.

  6. Add a reference to the Microsoft.Web.Services2 assembly.

    1. In Solution Explorer, right-click References, and then click Add Reference.
    2. Click the .NET tab, under Component Name, click Microsoft.Web.Services2.dll, and then click Select.
    3. Click OK.

To create the Web service client project

  1. On the File menu, point to Add, and then click New Project.

  2. In the Add New Project dialog box, under Project Types, click Visual C# Projects.

  3. Under Templates, click Console Application.

  4. In the Name box, type a name for your project.

  5. Click OK to create the project.

  6. Add references to the Microsoft.Web.Services2 and System.Web.Services assemblies.

    1. In Solution Explorer, right-click References, and then click Add Reference.
    2. Click the .NET tab, under Component Name, click Microsoft.Web.Services2.dll, and then click Select.
    3. On the .NET tab, under Component Name, click System.Web.Services.dll, and then click Select.
  7. Click OK.

Defining the Policy Assertion

The policy assertion is XML code that is contained in a policy file. For general information on policy files, see Configuring a Web Service's Policy.

To define the policy assertion

  1. Under the <policies> element of the policy file, declare a <policy> element.

  2. Under the <policy> element, define the policy assertion.

    <wsp:Policy wsu:Id="policy-5218e068-d399-4ad3-a014-9461df97209c"   
      xmlns:wsp="https://schemas.xmlsoap.org/ws/2002/12/policy">
      <wsbn:BeNice wsp:Usage="wsp:Required" 
        xmlns:wsbn="http://schemas.cohowinery.com/wsbn" />
    </wsp:Policy>
    

Writing Code to Verify and Enforce the Policy

For both the Web service and Web service client, you create a class that derives from the PolicyAssertion class to process the policy. For the Web service, you write code to verify the policy. For the Web service client, you write code to enforce the policy.

To write code to verify the receive-side policy

  1. Add a new class file to the Web service project.

  2. Add the following directives to the top of the file:

    using System.Xml;
    using Microsoft.Web.Services2;
    using Microsoft.Web.Services2.Policy;
    
  3. Create a class named BeNiceAssertion that derives from the PolicyAssertion class.

    1. Define a public static field of type XmlQualifiedName and provide the name and namespace of the policy assertion in the XmlQualifiedName constructor.
    2. Define a constructor that accepts an XmlElement as a parameter and pass the XmlQualifiedName and the XmlElement to the base class constructor.
    public class BeNiceAssertion : PolicyAssertion
    {
        public static readonly XmlQualifiedName BeNiceQName = new 
            XmlQualifiedName("BeNice", "http://schemas.cohowinery.com/wsbn");
    
        public BeNiceAssertion(XmlElement element)
        : base(BeNiceQName, element)
        {
            // The BeNiceAssertion has no attributes or child
            // elements to parse, so this constructor is empty.
        }
    }
    
  4. In the BeNiceAssertion class, override the IsSatisfiedBy method to check the message for any occurrence of a word that would violate the policy.

    public override bool IsSatisfiedBy(SoapEnvelope message)
    {
        // The message should not be null.
        if (message == null)
            throw new ArgumentNullException("message");
        XmlElement body = message.Body;
    
        // Look for any "bad words" in the body text.
        // For this sample, the only bad word is "Hello".
        return (body.InnerXml.IndexOf("Hello") == -1);
    }
    

    If the IsSatisfiedBy method returns false for the incoming message, the WSE policy system will not call the CanEnforce method. If receiving a message, the service cannot enforce the policy. The CanEnforce method is a required member of a PolicyAssertion, so simply return false from CanEnforce.

  5. In the BeNiceAssertion class, override the CanEnforce method to return false.

    public override bool CanEnforce(ref IPolicyEnforcer enforcer)
    {
        return false;
    }
    

To write code for policy enforcement on the client

  1. Add a new class file to the client project.

  2. Add the following directives to the top of the file:

    using System.Xml;
    using Microsoft.Web.Services2;
    using Microsoft.Web.Services2.Policy;
    
  3. Create a class named BeNiceAssertion that derives from the PolicyAssertion class and implements the IPolicyEnforcer interface.

    1. Define a public static field of type XmlQualifiedName and provide the name and namespace of the policy assertion in the XmlQualifiedName constructor.

    2. Define a constructor that accepts an XmlElement as a parameter and pass the XmlQualifiedName and the XmlElement to the base class constructor.

      public class BeNiceAssertion : PolicyAssertion, IPolicyEnforcer
      {
          public static readonly XmlQualifiedName BeNiceQName = new 
              XmlQualifiedName("BeNice", "http://schemas.cohowinery.com/wsbn");
      
          public BeNiceAssertion(XmlElement element)
          : base(BeNiceQName, element)
          {
              // The BeNiceAssertion has no attributes or child
              // elements to parse, so this constructor is empty.
          }
      }
      
  4. In the BeNiceAssertion class, override the IsSatisfiedBy method.

    public override bool IsSatisfiedBy(SoapEnvelope message)
    {
        //The message should not be null.
        if (message == null)
            throw new ArgumentNullException("message");
        XmlElement body = message.Body;
    
        // Look for any "bad words" in the body text.
        // For this sample, the only bad word is "Hello".
        return (body.InnerXml.IndexOf("Hello") == -1);
    }
    

    If the IsSatisfiedBy method returns false for the outgoing message, WSE policy system calls the CanEnforce method to determine if the assertion is capable of changing the message to make it satisfactory.

  5. In the BeNiceAssertion class, override the CanEnforce method.

    public override bool CanEnforce(ref IPolicyEnforcer enforcer)
    {
        // This class implements the IPolicyEnforcer 
        // interface, so set the enforcer to this class.
        enforcer = this;
    
        // This assertion can change unsatisfactory
        // messages, so return true.
        return true;
    }
    
  6. In the BeNiceAssertion class, override the Enforce method.

    public void Enforce(SoapEnvelope message)
    {
        // The message should not be null.
        if (message == null)
            throw new ArgumentNullException("message");
    
        // Replace any "bad words" in the body text.
        string oldBody = message.Body.InnerXml;
        message.Body.InnerXml = oldBody.Replace("Hello", "Goodbye");
    }
    

Mapping the Policy Assertion

The following procedure details how to configure your policy assertion, so that it can be used within an application.

To map the policy assertion to the Web service

  1. Add a <microsoft.web.services2> Element element to the <configuration> section of the Web.config file.

  2. Add a <policy> Element (WSE for Microsoft .NET) (2) element under the <microsoft.web.services2> Element element.

  3. Add a <cache> Element for <policy> element under the <policy> Element (WSE for Microsoft .NET) (2) element that specifies the name of the policy file.

  4. Add an <assertion> Element element under the <policy> Element (WSE for Microsoft .NET) (2) element.

    The following code example specifies that the policies for the Web application affected by the configuration file are in a file named policyCache.xml in the root folder of the application. Additionally, it specifies that the policy assertion wsbn:BeNice is handled by a class named BeNiceAssertion, which belongs to the namespace BeNicePolicyService in an assembly named BeNicePolicyService.dll.

    <microsoft.web.services2>
      <policy>
        <cache name="policyCache.xml" />
        <assertion xmlns:wsbn="http://schemas.cohowinery.com/wsbn" 
          name="wsbn:BeNice" type="BeNicePolicyService.BeNiceAssertion,
          BeNicePolicyService"/>
      </policy>
    </microsoft.web.services2>
    

To map the policy assertion to the client application

  1. Add a <microsoft.web.services2> Element element to the <configuration> section of the App.config file.

  2. Add a <policy> Element (WSE for Microsoft .NET) (2) element under the <microsoft.web.services2> Element element.

  3. Add a <cache> Element for <policy> element under the <policy> Element (WSE for Microsoft .NET) (2) element that specifies the name of the policy file.

  4. Add an <assertion> Element element under the <policy> Element (WSE for Microsoft .NET) (2) element.

    The following code example specifies that the policies for the Web application affected by the configuration file are in a file named policyCache.xml in the root folder of the application. Additionally, it specifies that the policy assertion wsbn:BeNice is handled by a class named BeNiceAssertion, which belongs to the namespace BeNicePolicyClient in an assembly named BeNicePolicyClient.exe.

    <microsoft.web.services2>
      <policy>
        <cache name="policyCache.xml" />
        <assertion xmlns:wsbn="http://schemas.cohowinery.com/wsbn" 
          name="wsbn:BeNice" type="BeNicePolicyClient.BeNiceAssertion,
          BeNicePolicyClient"/>
      </policy>
    </microsoft.web.services2>
    

Testing the Policy

The following procedure details how to test the policy assertion.

To test the policy

  1. In the Web service project, view the code for the Service1.asmx file.

  2. Uncomment the method HelloWorld and add a string parameter to it.

    [WebMethod]
    public string HelloWorld(string MessageText)
    {
        return "Hello World";
    }
    
  3. Build the comment solution.

  4. In the client project, add a Web reference to the service.

  5. In the Main method of the client, create an instance of the Web service proxy class and call the Web service method.

    static void Main(string[] args)
    {
        localhost.Service1Wse Proxy = new localhost.Service1Wse();
        Console.Write(Proxy.HelloWorld("Hello"));
    }
    

    By policy enforcement, "Hello" is replaced with "Goodbye".

See Also

Tasks

How to: Map a Policy to a Web Service
How to: Configure the Policy File

Reference

<assertion> Element