Usage of Standard Endpoints

The StandardEndpoints sample demonstrates how to use standard endpoints in service configuration files. A standard endpoint allows the user to simplify endpoint definitions by using a single property to describe an address, binding and contract combination with additional properties associated to it. This sample demonstrates how to define and implement a custom standard endpoint and how to define specific properties in the endpoint.

Sample Details

Service endpoints can be specified by supplying three parameters: address, binding and contract. Other parameters that can be supplied include behavior configuration, headers, listen URI, and so on. In some cases, any or all of addresses, bindings and contracts have values that cannot change. For this reason, it is possible to use standard endpoints. Some examples of such endpoints include metadata exchange endpoints and discovery endpoints. Standard endpoints also improve usability by allowing configuration of service endpoints without having to provide information of a fixed nature or to create their own standard endpoints, for example to improve usability by supplying a reasonable set of default values and thus reducing the verbosity of configuration files.

This sample consists of two projects: the service that defines two standard endpoints and the client that communicates with the service. The way the standard endpoints are defined for the service in the configuration file is show in the following example.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <extensions>
      <endpointExtensions>
        <add name="customEndpoint" type="Microsoft.Samples.StandardEndpoints.CustomEndpointCollectionElement, service" />
      </endpointExtensions>
    </extensions>
    <services>
      <service name="Microsoft.Samples.StandardEndpoints.CalculatorService">
        <endpoint address="http://localhost:8000/Samples/Service.svc/customEndpoint" contract="Microsoft.Samples.StandardEndpoints.ICalculator" kind="customEndpoint" />
        <endpoint kind="mexEndpoint" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="True"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <standardEndpoints>
      <customEndpoint>
        <standardEndpoint property="True" />
      </customEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>

The first endpoint defined for the service is of kind customEndpoint, whose definition can be seen in the <standardEndpoints> section, in which the property property is given the value true. This is the case of an endpoint customized with a new property. The second endpoint corresponds to a metadata endpoint, in which the values for address, binding and contract are fixed.

To define the standard endpoint element, a class that derives from StandardEndpointElement must be created. In the case of this sample, the CustomEndpointElement class has been defined as shown in the following example.

public class CustomEndpointElement : StandardEndpointElement
{
    public bool Property
    {
        get { return (bool)base["property"]; }
        set { base["property"] = value; }
    }

    protected override ConfigurationPropertyCollection Properties
    {
        get
        {
            ConfigurationPropertyCollection properties = base.Properties;
            properties.Add(new ConfigurationProperty("property", typeof(bool), false, ConfigurationPropertyOptions.None));
            return properties;
        }
    }

    protected override Type EndpointType
    {
        get { return typeof(CustomEndpoint); }
    }

    protected override ServiceEndpoint CreateServiceEndpoint(ContractDescription contract)
    {
        return new CustomEndpoint();
    }

    protected override void OnApplyConfiguration(ServiceEndpoint endpoint, ServiceEndpointElement serviceEndpointElement)
    {
        CustomEndpoint customEndpoint = (CustomEndpoint)endpoint;
        customEndpoint.Property = this.Property;
    }

    protected override void OnApplyConfiguration(ServiceEndpoint endpoint, ChannelEndpointElement channelEndpointElement)
    {
        CustomEndpoint customEndpoint = (CustomEndpoint)endpoint;
        customEndpoint.Property = this.Property;
    }

    protected override void OnInitializeAndValidate(ServiceEndpointElement serviceEndpointElement)
    {
    }

    protected override void OnInitializeAndValidate(ChannelEndpointElement channelEndpointElement)
    {
    }
}

In the CreateServiceEndpoint function, a CustomEndpoint object is created. Its definition is shown in the following example:

public class CustomEndpoint : ServiceEndpoint
{
    public CustomEndpoint()
        : this(string.Empty)
    {
    }

    public CustomEndpoint(string address)
        : this(address, ContractDescription.GetContract(typeof(ICalculator)))
    {
    }

    public CustomEndpoint(string address, ContractDescription contract)
        : base(contract)
    {
        this.Binding = new BasicHttpBinding();
        this.IsSystemEndpoint = false;
    }

    public bool Property
    {
        get;
        set;
    }
}

To perform the communication between service and client, a service reference is created in the client to the service. When the sample is built and executed, the service executes and the client communicates with it. Note that the service reference should be updated every time there is some change in the service.

To use this sample

  1. Using Visual Studio, open the StandardEndpoints.sln file.

  2. Enable multiple projects to start up.

    1. In Solution Explorer, right-click the Standard Endpoints solution and then select Properties.

    2. In Common Properties, select Startup Project, and then click Multiple Startup Projects.

    3. Move the Service project to the beginning of the list, with the Action set to Start.

    4. Move the Client project after the Service project, also with the Action set to Start.

      This specifies that the Client project is executed after the Service project.

  3. To run the solution, press F5.

Note

If these steps don't work, then make sure that your environment has been properly set up, using the following steps:

  1. Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.
  2. To build the solution, follow the instructions in Building the Windows Communication Foundation Samples.
  3. To run the sample in a single or multiple computer configurations, follow the instructions in Running the Windows Communication Foundation Samples.