Using Service Endpoints

Applies to: SharePoint Foundation 2010

All communications with the Windows Communication Foundation (WCF) service occur through service endpoints. A service endpoint specifies a contract that defines which methods of the service class can be accessed via the endpoint, and each endpoint can expose a different set of methods. The endpoints also define a binding that specifies how a client communicates with the service and the network address where the endpoint resides.

Supported Protocols

The Service Application Framework supports all of the WCF supported protocols, however we recommend using http and https protocols for service endpoints:

  • HTTP

  • HTTPS

    Note

    The Service Application Framework automatically installs and configures a Secure Sockets Layer (SSL) certificate for your HTTPS service endpoints. The Internet Information Services (IIS) management user interface does not display this certificate, but it is installed. You can confirm the installation by typing the following command at a command prompt:

    netsh http show sslcert ipport=0.0.0.0:32844

Defining Service Endpoints

Each endpoint supported by your WCF service application must be defined in the web.config settings for the application. The protocol and address of each endpoint must be unique. For example, two endpoints can have the same address if they specify different protocols in their respective bindings. However, if two endpoints use the same protocol, they must specify different addresses.

Use a unique endpoint address for every endpoint so that these addresses are not dependent on the binding protocol. Specify an endpoint address that is relative to the base address configured by the Service Application Framework.

For example, to specify two endpoints with relative addresses of "http" and "https", use the following code.

<services>
    <service
        name="Microsoft.SharePoint.Test.SampleWebServiceApplication">
        <endpoint
          address="http"
          contract="Microsoft.SharePoint.Test.ISampleWebServiceContract"
          binding="customBinding"
          bindingConfiguration="SampleWebServiceHttpBinding" />
        <endpoint
          address="https"
          contract="Microsoft.SharePoint.Test.ISampleWebServiceContract"
          binding="customBinding"
          bindingConfiguration="SampleWebServiceHttpsBinding" />
      </service>
    </services>

In the previous example, if the service base address is http://machine:8080/application/calculator.svc, the endpoint addresses is the following:

http://machine:8080/application/calculator.svc/http

http://machine:8080/application/calculator.svc/https

Providing Multiple Endpoints

A service application might support two endpoints: one that uses a binding that is optimized for performance (where, for example, the network traffic between the front-end web server and the application server is on a private, back-end LAN and does not have to be encrypted), and one that uses a binding that is optimized for security (where the network traffic must be encrypted). The Service Application Framework provides a user interface that enables a farm administrator to choose the endpoint most appropriate for the network topology. Administrators can manage the endpoint selection by using the Publish option on the Service Application Management page in the Central Administration site, or by using the DefaultEndpoint parameter of the Set-SPServiceApplication Windows PowerShell cmdlet.

Defining Endpoints in Service Provisioning Code

By default, a web service application has one HTTP endpoint. If this is the configuration you want for your service application, no changes are required. If you want to use a different protocol or if you want to support multiple endpoints, you must explicitly define all of the endpoints your service application will support.

Use the AddServiceEndpoint method of the SPIisWebServiceApplication as shown in the following example.

// Construct your SPIisWebServiceApplication derived class as usual.
MyWebServiceApplication app = new MyWebServiceApplication(…);

// Commit the new application to the configuration database.
// NOTE: Update must be called before AddServiceEndpoint.

// The service application must be committed to the configuration database before endpoints can be added.
app.Update();

// Add the endpoints supported by the application.
// NOTE: AddServiceEndpoint should be called before app.Provision, because app.Provision will provision 
// the default HTTP endpoint if no endpoints are explicitly added to the application.
// NOTE: The default endpoint name is always "http"
app.AddServiceEndpoint("", SPIisWebServiceBindingType.Http);

// Add an alternate HTTPS endpoint.
app.AddServiceEndpoint("secure", SPIisWebServiceBindingType.Https);

The endpoint with the name "http" is used as the default endpoint for the service application. A service endpoint name must be unique, even if your endpoint addresses are not unique. If you have two endpoints at the same relative address, you must use the optional third parameter of AddServiceEndpoint to specify the relative address. The third parameter defaults to the endpoint name.

The following example shows how to define two endpoints at the same base service address, the first using the HTTP protocol and the second using the HTTPS protocol. The https endpoint is at the base service address "".

app.AddServiceEndpoint("", SPIisWebServiceBindingType.Http); 
// The default endpoint.
app.AddServiceEndpoint("https", SPIisWebServiceBindingType.Https, ""); 

Defining Endpoints in the Client Configuration

Each endpoint must also be defined in your client configuration. Create a client.config file with bindings that match the web.config file for your service application. Each client endpoint must have a unique name attribute value so that it can be referenced from the proxy code that will read the configuration file, as shown in the following example.

The endpoint configuration names in this example were chosen to match the service endpoint relative addresses, although this is not a requirement.

<configuration>
  <system.serviceModel>
    <client>
      <endpoint
        name="http"
        contract="Microsoft.SharePoint.Test.ISampleWebServiceContract"
        binding="customBinding"
        bindingConfiguration="SampleWebServiceHttpBinding" />
      <endpoint
        name="https"
        contract="Microsoft.SharePoint.Test.ISampleWebServiceContract"
        binding="customBinding"
        bindingConfiguration="SampleWebServiceHttpsBinding" />
    </client>

Defining Endpoints in Proxy Code

Your proxy code must create a channel factory by using the appropriate endpoint configuration. The endpoint configuration is identified by name (the name attribute of the endpoint client configuration element). To determine the endpoint configuration name, inspect the endpoint URI before creating a channel and compare the relative address with known endpoint addresses. The code used to cache the client channel factory is shown in the following example. If your endpoint addresses are differentiated only by protocol, use the URI scheme in your comparison.

private string m_EndpointConfigurationName;
private ChannelFactory<ISampleWebServiceContract> m_ChannelFactory;
private object m_ChannelFactoryLock = new object();

Now get the endpoint configuration name for a given endpoint address.<param name="address">The endpoint address.</param>

GetEndpointConfigurationName returns the endpoint configuration name. The returned endpoint name must match one of the endpoint element names in the client.config file.

private string GetEndpointConfigurationName(Uri address)
{
    if (null == address)
    {
        throw new ArgumentNullException("address");
    }
    if (address.Scheme == Uri.UriSchemeHttp)
    {
        return "http";
    }

    if (address.Scheme == Uri.UriSchemeHttps)
    {
        return "https";
    }
    return String.Empty;
}
private ISampleWebServiceContract GetChannel(Uri address)
{
    // Create an endpoint address for the service.
    EndpointAddress endpointAddress = new EndpointAddress(address); 

    // Get the endpoint configuration name.
    string endpointConfigurationName = GetEndpointConfigurationName(address); 
    // Check for a cached channel factory for the endpoint configuration.
    if ((null == m_ChannelFactory) || 
    (endpointConfigurationName != m_EndpointConfigurationName))
    {
        lock (m_ChannelFactoryLock)
        {
            if ((null == m_ChannelFactory) || 
               (endpointConfigurationName != m_EndpointConfigurationName))
            {

                // Create a channel factory
                // endpoint configuration name.
                m_ChannelFactory = 
                CreateChannelFactory<ISampleWebServiceContract>
                (endpointConfigurationName);
                // Store the current endpoint configuration name.
                m_EndpointConfigurationName = endpointConfigurationName;
            }
        }
    }
    // Create a channel from the channel factory.
    return m_ChannelFactory.CreateChannel(endpointAddress);
}

Note

If the channel factory is cached, you must invalidate the cache.

See Also

Concepts

Creating Service Application Framework Web Services