Edit

Share via


How to: Set the ProtectionLevel Property

You can set the protection level by applying an appropriate attribute and setting the property. You can set protection at the service level to affect all parts of every message, or you can set protection at increasingly granular levels, from methods to message parts. For more information about the ProtectionLevel property, see Understanding Protection Level.

Note

You can set protection levels only in code, not in configuration.

To sign all messages for a service

  1. Create an interface for the service.

  2. Apply the ServiceContractAttribute attribute to the service and set the ProtectionLevel property to Sign, as shown in the following code (the default level is EncryptAndSign).

    // Set the ProtectionLevel on the whole service to Sign.
    [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)]
    public interface ICalculator
    

To sign all message parts for an operation

  1. Create an interface for the service and apply the ServiceContractAttribute attribute to the interface.

  2. Add a method declaration to the interface.

  3. Apply the OperationContractAttribute attribute to the method, and set the ProtectionLevel property to Sign, as shown in the following code.

    // Set the ProtectionLevel on the whole service to Sign.
    [ServiceContract(ProtectionLevel = ProtectionLevel.Sign)]
    public interface ICalculator
    {
        // Set the ProtectionLevel on this operation to None.
        [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
        double Add(double a, double b);
    }
    

Protecting Fault Messages

Exceptions that are thrown on a service can be sent to a client as SOAP faults. For more information about creating strongly typed faults, see Specifying and Handling Faults in Contracts and Services and How to: Declare Faults in Service Contracts.

To protect a fault message

  1. Create a type that represents the fault message. The following example creates a class named MathFault with two fields.

  2. Apply the DataContractAttribute attribute to the type and a DataMemberAttribute attribute to each field that should be serialized, as shown in the following code.

    [DataContract]
    public class MathFault
    {
        [DataMember]
        public string operation;
        [DataMember]
        public string description;
    }
    
  3. In the interface that will return the fault, apply the FaultContractAttribute attribute to the method that will return the fault and set the detailType parameter to the type of the fault class.

  4. Also in the constructor, set the ProtectionLevel property to EncryptAndSign, as shown in the following code.

    public interface ICalculator
    {
        // Set the ProtectionLevel on a FaultContractAttribute.
        [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        [FaultContract(
            typeof(MathFault),
            Action = @"http://localhost/Add",
            Name = "AddFault",
            Namespace = "http://contoso.com",
            ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        double Add(double a, double b);
    }
    

Protecting Message Parts

Use a message contract to protect parts of a message. For more information about message contracts, see Using Message Contracts.

To protect a message body

  1. Create a type that represents the message. The following example creates a Company class with two fields, CompanyName and CompanyID.

  2. Apply the MessageContractAttribute attribute to the class and set the ProtectionLevel property to EncryptAndSign.

  3. Apply the MessageHeaderAttribute attribute to a field that will be expressed as a message header and set the ProtectionLevel property to EncryptAndSign.

  4. Apply the MessageBodyMemberAttribute to any field that will be expressed as part of the message body, and set the ProtectionLevel property to EncryptAndSign, as shown in the following example.

    [MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    public class Company
    {
        [MessageHeader(ProtectionLevel = ProtectionLevel.Sign)]
        public string CompanyName;
    
        [MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
        public string CompanyID;
    }
    

Example

The following example sets the ProtectionLevel property of several attribute classes at various places in a service.

[ServiceContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public interface ICalculator
{
    [OperationContract(ProtectionLevel = ProtectionLevel.Sign)]
    double Add(double a, double b);

    [OperationContract()]
    [FaultContract(typeof(MathFault),
        ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    double Subtract(double a, double b);

    [OperationContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    Company GetCompanyInfo();
}

[DataContract]
public class MathFault
{
    [DataMember]
    public string operation;
    [DataMember]
    public string description;
}

[MessageContract(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
public class Company
{
    [MessageHeader(ProtectionLevel = ProtectionLevel.Sign)]
    public string CompanyName;

    [MessageBodyMember(ProtectionLevel = ProtectionLevel.EncryptAndSign)]
    public string CompanyID;
}

[MessageContract(ProtectionLevel = ProtectionLevel.Sign)]
public class Calculator : ICalculator
{
    public double Add(double a, double b)
    {
        return a + b;
    }

    public double Subtract(double a, double b)
    {
        return a - b;
    }

    public Company GetCompanyInfo()
    {
        Company co = new Company();
        co.CompanyName = "www.cohowinery.com";
        return co;
    }
}

public class Test
{
    static void Main()
    {
        Test t = new Test();
        try
        {
            t.Run();
        }
        catch (System.InvalidOperationException inv)
        {
            Console.WriteLine(inv.Message);
        }
    }

    private void Run()
    {
        // Create a binding and set the security mode to Message.
        WSHttpBinding b = new WSHttpBinding();
        b.Security.Mode = SecurityMode.Message;

        Type contractType = typeof(ICalculator);
        Type implementedContract = typeof(Calculator);
        Uri baseAddress = new Uri("http://localhost:8044/base");

        // Create the ServiceHost and add an endpoint.
        ServiceHost sh = new ServiceHost(implementedContract, baseAddress);
        sh.AddServiceEndpoint(contractType, b, "Calculator");

        ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
        sm.HttpGetEnabled = true;
        sh.Description.Behaviors.Add(sm);
        sh.Credentials.ServiceCertificate.SetCertificate(
            StoreLocation.CurrentUser,
            StoreName.My,
            X509FindType.FindByIssuerName,
            "ValidCertificateIssuer");

        foreach (ServiceEndpoint se in sh.Description.Endpoints)
        {
            ContractDescription cd = se.Contract;
            Console.WriteLine($"\nContractDescription: ProtectionLevel = {cd.Name}");
            foreach (OperationDescription od in cd.Operations)
            {
                Console.WriteLine($"\nOperationDescription: Name = {od.Name}");
                Console.WriteLine($"ProtectionLevel = {od.ProtectionLevel}");
                foreach (MessageDescription m in od.Messages)
                {
                    Console.WriteLine($"\t {m.Action}: {m.ProtectionLevel}");
                    foreach (MessageHeaderDescription mh in m.Headers)
                    {
                        Console.WriteLine($"\t\t {mh.Name}: {mh.ProtectionLevel}");

                        foreach (MessagePropertyDescription mp in m.Properties)
                        {
                            Console.WriteLine($"{mp.Name}: {mp.ProtectionLevel}");
                        }
                    }
                }
            }
        }
        sh.Open();
        Console.WriteLine("Listening");
        Console.ReadLine();
        sh.Close();
    }
}

Compiling the Code

The following code shows the namespaces required to compile the example code.

using System;
using System.ServiceModel;
using System.Net.Security;
using System.ServiceModel.Description;
using System.Security.Cryptography.X509Certificates;
using System.Runtime.Serialization;

See also