Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#5.0

Default Binding and Behavior Configurations, Standard Endpoints and File-less Activation in WCF 4.0/4.5

4.90/5 (10 votes)
26 Apr 2014CPOL12 min read 75.9K   490  
This article describes default binding configurations, default behavior configurations, inheritance model in behavior configurations, file-less activation and standard endpoints in WCF 4.0/4.5

Table of Contents

Introduction

In my recent article (Default Endpoints and Default Protocol Mapping in WCF 4.0/4.5), I've explained default endpoints and default protocol mapping features of WCF 4.0/4.5 with examples. Now I'm going to explore some more features like default binding configurations, default behavior configurations, inheritance model in behavior configurations, file-less activation and standard endpoints shipped with WCF 4.0/4.5 in this article.

Demo Service

For this post, I've created a demo service- Greeting. I've defined two service contracts IHello and IWelcome and then created Greeting service by implementing these service contracts. Please see the code below-

C#
[ServiceContract]
public interface IHello
{
    [OperationContract]
    void Hello(string message);
}

[ServiceContract]
public interface IWelcome
{
    [OperationContract]
    void Welcome(string message);
}

public class Greeting: IHello, IWelcome
{
    public void Hello(string message)
    {
        Console.WriteLine("Hell Mr. {0}", message);
    }

    public void Welcome(string message)
    {
        Console.WriteLine("Welcome Mr. {0}", message); ;
    }
}

I've hosted Greeting service in a windows console application using self-hosting technique.

Default Binding Configurations

In WCF every binding has a built-in default configuration and used with the same unless explicitly overridden by the host application for a particular endpoint in a service. You can override a binding instance built-in default configuration by defining & applying an explicit binding configuration.

In WCF 3.x, you first define a named binding configuration and then apply the same to endpoint(s) definitions through the bindingConfiguration attribute. Suppose that you want to override the built-in default configuration of the BasicHttpbinding in order to support MTOM message encoding with basic authentication type to desire endpoint(s) in your service. For this first you'll need to define a named binding configuration for the BasicHttpbinding then you'll apply the same to the desire endpoint(s). A typical configuration file in WCF 3.x would be as-

ASP.NET
<system.serviceModel>
<services>
    <service name="WelcomeService.Greeting">
        <endpoint address="" binding="basicHttpBinding" contract="WelcomeService.IWelcome"/>
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="BasicWithMtomPlusBasicAuthentication" contract="WelcomeService.IHello"/>
        <host>
            <baseAddresses>
                <add baseAddress="http://localhost:8080/greeting"/>
            </baseAddresses>
        </host>
    </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicWithMtomPlusBasicAuthentication" messageEncoding="Mtom">
          <security mode="None">
            <transport proxyCredentialType="Basic"/>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
</system.serviceModel>

In the above, a named binding configuration BasicWithMtomPlusBasicAuthentication has been configured for the BasicHttpbinding and applied to the endpoint with relative address basic. If you run our console host application with the above configuration in the context of WCF 3.x, you'll observe that the endpoint with relative address basic is displaying with the overridden named binding configuration BasicWithMtomPlusBasicAuthentication on the console windows while the other one just with the built-in default configuration for BasicHttpBinding.

Image 1

It is important to note that if you only define a named binding configuration and don't apply the same on desire endpoint(s), then the overridden configuration would not reflect on the desire endpoint(s) in WCF 3.x. So just run our console host application without applying named binding configuration to any endpoints, you'll see both endpoints are displaying on the console window with built-in default configuration for BasicHttpBinding.

Image 2

With WCF 4.0/4.5, you can define default binding configurations by simply omitting the binding configuration name when defining the new binding configuration. If you define a default binding configuration for a particular binding, then WCF will use that default binding configuration for the endpoint(s) with same binding not having an explicit binding configuration set on it/them.

Compare this default binding configuration on application level with WCF 3.5 where each endpoint with the same binding would need to have an explicit binding configuration name set on it.

If you add default binding configurations to the machine.config file, it will get reflect across all the services running on the machine. You can also define default binding configuration on application level by adding the same within the application configuration file.

Let's try to grasp this concept. For the demo I've configured our Greeting service with a http base address and added an endpoint with relative address basic, BasicHttpbinding and service contract IHello through app.config file. I've also define a named binding configuration- WithMtom in order to support MTOM message encoding on endpoint(s) with BasicHttpBinding and finally applied the same on our endpoint having relative address basic through bindingConfiguration attribute. Configuration file of our console host (app.config) is shown below-

ASP.NET
<system.serviceModel>
    <services>
      <service name="WelcomeService.Greeting">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="withMtom"
          contract="WelcomeService.IHello" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <basicHttpBinding>
        <binding name="withMtom" messageEncoding="Mtom" />
      </basicHttpBinding>
    </bindings>
  </system.serviceModel>

I've also called AddDefaultEndpoints method to add default endpoints too along with the endpoint having relative address basic like-

C#
host.AddDefaultEndpoints();  

Now if you run the console host application, you will see that endpoint with relative address basic is displaying with the overridden named binding configuration WithMtom while the other two default endpoints are displaying with the build-in default binding configuration for BasicHttpbinding on the console window. Actually the build-in default binding configuration for BasicHttpbinding is picked from the machine.config file.

Image 3

Now I've defined a default binding configuration by omitting the name along with previous one in order to support Basic Authentication on endpoint(s) with BasicHttpBinding in the app.config file as-

ASP.NET
<binding name=""> <!-- no name attribute -->
   <security>
       <transport proxyCredentialType="Basic" /> 
   </security>
</binding>

and run the console host application and you'll see that now default endpoints are displaying with the overridden default binding configuration on the console window while other one with named binding configuration.

Image 4

One more experiment. Just remove the named binding configuration from the endpoint with relative address basic and run the console host application again and you'll find that now all endpoints are displaying with default binding configuration defined earlier.

Image 5

So it is a great feature in WCF 4.0/4.5. One important note that, don't try to define two default binding configurations otherwise you'll get ConfigurationErrorsException "A child element named 'binding' with same key already exists at the same configuration scope. Collection elements must be unique within the same configuration scope (e.g. the same application.config file). Duplicate key value: ''".

Default Behavior Configurations

In WCF 4.0/4.5, there is another good feature called default behavior configurations. You can define a default behavior which can be shared across all services or endpoints running on a machine or within a solution through machine.config file / application configuration file.

In WCF 3.x, you have to define named behavior configurations first, then you apply the same explicitly to the service and points through the “behaviorConfiguration” attribute. Below is a typical WCF 3.x configuration file-

ASP.NET
<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="meta">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="WelcomeService.Greeting" behaviorConfiguration="meta">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration=""
          contract="WelcomeService.IHello" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services> 
</system.serviceModel>

But in case of WCF 4.0/4.5, you can define default behavior configurations by omitting the name in the configuration definition. If you add these default behaviors to machine.config file, those will get reflect to all services or endpoints hosted on the machine. If you add these default behaviors to app.config file, those will get reflect only within the scope of the host application.

Let's consider a default behavior I've defined below-

ASP.NET
<behaviors>
      <serviceBehaviors>
        <behavior name=""> <!-- no name attribute -->
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
</behaviors>

This is an example of default service behavior that enables service metadata not having an explicit behavior configuration. If we run our console host application with the above default configuration, we can retrieve service WSDL definition with the help of service's http base address. Please see the screen shot below-

Image 6

If you also want to include exception details in SOAP faults for debugging purpose, you can define a default behavior as shown below-

ASP.NET
<behavior name=""> <!-- no name attribute -->
   <serviceMetadata httpGetEnabled="true" />
   <serviceDebug includeExceptionDetailInFaults="true" />
</behavior>

Support of Inheritance in Behavior Configurations

In WCF 4.0/4.5, behavior configurations also support an inheritance model. Means if you define an application-specific behavior configuration using the same name as one already defined in the machine.config, the application-specific behavior configuration will be merged with the machine level configuration by adding any additional behaviors to the derived composite behavior configuration.

Let's realise this feature. Suppose that you want to enable service metadata implicitly for all services hosted in your machine and further want to include exception details in SOAP faults explicitly for a particular service hosted on the same machine. In order to do the same, you'll need to utilise inheritance model of behavior configurations as I've explained above.

First define a named service behavior say "metaData" in machine.config file under the system.serviceModel section to enable service metadata like below-

ASP.NET
<system.serviceModel>
 <behaviors>
      <serviceBehaviors>
        <behavior name="metaData">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
 </behaviors>

... 

Second define another named service behavior "metaData" in a particular service's app.config file using the same name as you have already defined in the machine.config file like below-

ASP.NET
<behaviors>
      <serviceBehaviors>
        <behavior name="metaData">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
/behaviors>

   ...

Then apply the named service behavior "metaData" to your service like below-

ASP.NET
<services>
     <service name="WelcomeService.Greeting" behaviorConfiguration="metaData">
       <endpoint address="basic" binding="basicHttpBinding" contract="WelcomeService.IHello" />
       <host>
         <baseAddresses>
           <add baseAddress="http://localhost:8080/greeting" />
         </baseAddresses>
       </host>
     </service>
</services>

Now if we run our console host application with the above named service behaviors defined, we can retrieve our service (Greeting) WSDL definition with the help of service's http base address. We can also verified that the value of includeExceptionDetailInFaults is true form the console host window ensuring that exception details would be included in the SOAP faults. Please see the screen shots below-

Image 7
Image 8

So here you have seen that the application-specific behavior configuration is merged with the machine level configuration by adding any additional behaviors to the derived composite behavior configuration at run time.

File-less Activation

As you know with the help of .svc files, it is easy to host WCF services in IIS/WAS. But there is another even easier approach to expose WCF services by defining virtual activation endpoints within the Web.config, hence removing the need of physical .svc files.

In WCF 4.0/4.5, you can define virtual service activation endpoints in the web.config that map to your service types. This makes it possible to activate WCF services without having to maintain physical .svc files. This is known as file-less activation.

Let's host our Greeting service in IIS to grasp this concept. I've created a demo WCF Service Web Site and added the reference of WelcomeService project (WCF project) to it and deleted the service.svc file. Then I've defined an activation endpoint in the web.config file like below-

ASP.NET
<serviceHostingEnvironment >
      <serviceActivations>
        <add relativeAddress="Greeting.svc" service="WelcomeService.Greeting"/>
      </serviceActivations>      
</serviceHostingEnvironment>

With the above configuration, it’s possible to activate the Greeting service using a relative path of “Greeting.svc” (relative to the base address of the Web application).

Finally I've hosted Greeting service in IIS without .svc file. now you can browse to http://localhost/greetings/Greeting.svc without actually having a physical .svc file. Please see the screenshot below-

Image 9

Standard Endpoints

It is another new feature in WCF 4.0/4.5. A standard endpoint is a common preconfigured endpoint definition provided by the WCF 4.0/4.5. Standard endpoints enable us to define an endpoint configuration that is not typically going to be changed, but it can be if needed.

Table down below (from msdn) consisting of standard endpoints shipped with WCF 4.0/4.5 describing standard endpoint definitions for some of the most common WCF features and communication scenarios-

Element Description

<announcementEndpoint>

Defines a standard endpoint with a fixed announcement contract. A service can optionally announce its availability by sending an online and offline announcement message when it is opened or closed respectively. A Windows Communication Foundation (WCF) service specifies the announcement endpoints in the <serviceDiscovery> element and uses the AnnouncementClient to perform the announcements. A client wishing to listen for the announcement from other service is actually acting as a WCF service; thus you have to configure the announcement endpoints for that client in the <services> section.

<discoveryEndpoint>

Defines a standard endpoint with a fixed discovery contract. When added to the service configuration, it specifies where to listen for the discovery messages. When added to the client configuration it specifies where to send the discovery queries.

<dynamicEndpoint>

This configuration element defines a standard endpoint that contains information to enable an application to function as a client program that can find the endpoint address dynamically at runtime.

<mexEndpoint>

Defines a standard endpoint with a fixed IMetadataExchange contract. Since all metadata exchange endpoints specify IMetadataExchange as their contract, you can use this standard point instead of defining one for yourself.

<udpAnnoucementEndpoint>

Defines a standard endpoint that is used by services to send announcement messages over a UDP binding. It has a fixed contract and supports two discovery versions. In addition it has a fixed UDP binding and a default address value as specified in the WS-Discovery specifications (WS-Discovery April 2005 or WS-Discovery version 1.1). You can specify the multicast address to use for sending and receiving the announcement messages.

<udpDiscoveryEndpoint>

Defines a standard endpoint that is pre-configured for discovery operations over a UDP multicast binding. This endpoint has a fixed contract and supports two WS-Discovery protocol versions. In addition, it has a fixed UDP binding and a default address as specified in the WS-Discovery specifications (WS-Discovery April 2005 or WS-Discovery V1.1).

<webHttpEndpoint>

Defines a standard endpoint with a fixed <webHttpBinding> binding that automatically adds the <webHttp> behavior. Use this endpoint when writing a REST service.

<webScriptEndpoint>

Defines a standard endpoint with a fixed <webHttpBinding> binding that automatically adds the <enableWebScript> behavior. Use this endpoint when you are writing a service that is called from an ASP.NET AJAX application.

<workflowControlEndpoint>

Defines a standard endpoint for controlling the execution of workflow instances (create, run, suspend, terminate, etc).

You can leverage any of the above standard endpoints in your service configurations by simply referencing them by name as per your need.

Let's consider an example, suppose that you want to configure a MEX endpoint for your service host. in this case, you'll always need to specify IMetadataExchange service contract and you'll most likely to use HTTP protocol (You can use TCP/NamedPipe/HTTPS too). So a typical MEX endpoint would be-

ASP.NET
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

But with WCF 4.0/4.5, you can configure your service host for a MEX endpoint with a standard endpoint definition for the metdata exchange called “mexEndpoint” using the new "kind" atrribute of the <endpoint> <endpoint><endpoint> element like below-

ASP.NET
<endpoint address="mex" kind="mexEndpoint" /> 

Now If we run our service console host application with the above standard endpoint definition for the metadata exchange, you can see the MEX endpoint on the console window-

Image 10

You can generate a configuration file and a code file containing the client class using this MEX endpoint with the help of svcutil.exe like below-

C#
svcutil.exe http://localhost:8080/greeting/mex

Although the standard endpoints hide most of the configuration details but there might be some scenario where one want to use standard endpoints with somewhat different configuration. It can be done by overriding the standard endpoint configuration by following two steps.

First you will need to use the <standardEndpoints> section to override the standard endpoint configuration. Second you'll need to reference that overridden standard endpoint configuration during defining a new <endpoint> via the endpointConfiguration attribute as described down below-

ASP.NET
<services>
      <service name="WelcomeService.Greeting">
        <endpoint address="basic" binding="basicHttpBinding" contract="WelcomeService.IHello" />
        <endpoint address="mex" kind="mexEndpoint" endpointConfiguration="lock" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/greeting" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <standardEndpoints>
      <mexEndpoint>
        <standardEndpoint name="lock"  lockItem="true" />
      </mexEndpoint>
    </standardEndpoints>

Conclusion

So in this post, I've tried my level best to explain concepts related to default binding/behavior configurations, inheritance model in behavior configurations, file-less activation and standard endpoints in WCF 4.0/4.5. In the next post, I'll cover more WCF topics. Happy coding!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)