Click here to Skip to main content
Click here to Skip to main content

Creating your own (customized) standard endpoints in WCF 4

, 2 Feb 2012
Rate this:
Please Sign up or sign in to vote.
Creating customized standard endpoints in WCF 4.

Lately I’ve been writing and speaking a lot about WCF 4.5, but while delivering my “What’s new in WCF 4” session in Visual Studio Live yesterday I realized that there is one feature of WCF 4 that most people are not aware of, and do not really understand how useful it is – Standard Endpoints.

In WCF we always have to specify a set of address+binding+contract (ABC) for our endpoints. If our endpoints also need to be configured, for example – change the binding configuration, or the endpoint behavior, then we need to add some more configuration. We can use default configuration (another feature of WCF 4), but if we have two common settings, we cannot set two defaults and we’re back to square one.

Standard endpoints change the way we define endpoints – with standard endpoints we specify a special “kind” name in our endpoint, which automatically sets our endpoint’s address, binding, contract, binding configuration, and endpoint behavior.

For example – if we define the following endpoint:

<endpoint address="mex" kind="mexEndpoint"/>

The above endpoint will automatically be set with the mexHttpBinding and the IMetadataExchange contract.

If we define the following endpoints:

<endpoint code="web" kind="webHttpEndpoint" contract="MyNS.IMyContract"/>

We will get an endpoint which uses webHttpBinding, and automatically gets the webHttp endpoint behavior.

Although this is quite nice, this is the least we can do with standard endpoints. The real use of standard endpoints is when you create some of your own.

Image the following – you are a part of an infrastructure team in your organization and you need to explain to the dev teams which endpoint configuration they should use in their projects – “Please use NetTcp binding, with increased message size limits, with either security none or transport, and don’t forget to increase the send timeout”.

One way to do this is to send a memo to all the dev teams, hoping everyone follow your instructions to the letter. Another way you can do that is to create your own standard endpoint with all of the above configuration and just send it to the dev teams to use.

First of all you need to create your custom endpoint:

   1:  public class CompanyNameStandardEndpoint : ServiceEndpoint
   2:  {
   3:      private bool _isSecured;
   4:   
   5:      public CompanyNameStandardEndpoint(ContractDescription contract)
   6:          : base(contract)
   7:      {
   8:          this.Binding = new NetTcpBinding();
   9:          ResetBindingConfiguration(this.Binding);
  10:          this.IsSystemEndpoint = false;
  11:      }
  12:   
  13:      public bool IsSecured
  14:      {
  15:          get
  16:          {
  17:              return _isSecured;
  18:          }
  19:          set
  20:          {
  21:              _isSecured = value;
  22:              if (_isSecured)
  23:              {
  24:                  (this.Binding as NetTcpBinding).Security.Mode = SecurityMode.Transport;
  25:              }
  26:              else
  27:              {
  28:                  (this.Binding as NetTcpBinding).Security.Mode = SecurityMode.None;
  29:              }
  30:          }
  31:   
  32:      }
  33:   
  34:      // Receive a dynamic object instead of creating separate methods
  35:      // for netTcp, basicHttp, WSHttpBinding...
  36:      private void ResetBindingConfiguration(dynamic binding)
  37:      {
  38:          binding.SendTimeout = TimeSpan.FromMinutes(5);
  39:          binding.MaxReceivedMessageSize = Int32.MaxValue;
  40:          binding.MaxBufferSize = Int32.MaxValue;
  41:      }
  42:  }

Line 8 makes sure that your endpoint will use NetTcp binding.

Line 9 will call a method that initializes the binding settings (lines 36-41).

Note: the ResetBindingConfiguration method receives a dynamic object because for some reason some of the binding properties such as the MaxReceivedMessageSize and the MaxBufferSize are defined in each of the bindings instead of being defined in a base Binding class. The dynamic will allow us to change our code later on to support both TCP and HTTP bindings without duplicating our method for overloads.

Line 10 specifies that this is a user-defined endpoint and not a system endpoint.

Lines 13-32 are responsible of handling the user’s selection to whether the endpoint is secured or not by changing the security mode to either Transport or None.

So now we have a new standard endpoint that initializes the binding to NetTcpBinding, sets the timeout and message size, and knows to set the security according to the user’s selection. We can now add this endpoint in code to our service by calling the following code:

   1:  CompanyNameStandardEndpoint newEndpoint = new CompanyNameStandardEndpoint(
   2:          ContractDescription.GetContract(typeof(IService1)));
   3:   
   4:  newEndpoint.IsSecured = false;
   5:  newEndpoint.Address = new EndpointAddress(tcpBaseAddress + "companyUnsecured");
   6:   
   7:  host.AddServiceEndpoint(newEndpoint);            

To be able to add this endpoint configuration in the config file, you will need to add some boilerplate code:

   1:  public class CompanyNameStandardEndpointCollectionElement :
   2:         StandardEndpointCollectionElement<CompanyNameStandardEndpoint, 
              CompanyNameStandardEndpointElement>
   3:  {
   4:  }
   5:   
   6:  public class CompanyNameStandardEndpointElement : StandardEndpointElement
   7:  {
   8:      protected override ServiceEndpoint CreateServiceEndpoint(ContractDescription contractDescription)
   9:      {
  10:          return new CompanyNameStandardEndpoint(contractDescription);
  11:      }
  12:   
  13:      public bool IsSecured
  14:      {
  15:          get { return (bool)base["isSecured"]; }
  16:          set { base["isSecured"] = value; }
  17:      }
  18:   
  19:      protected override ConfigurationPropertyCollection Properties
  20:      {
  21:          get
  22:          {
  23:              ConfigurationPropertyCollection properties = base.Properties;
  24:              properties.Add(new ConfigurationProperty("isSecured", 
                              typeof(bool), false, ConfigurationPropertyOptions.None));
  25:              return properties;
  26:          }
  27:      }
  28:   
  29:      protected override Type EndpointType
  30:      {
  31:          get { return typeof(CompanyNameStandardEndpoint); }
  32:      }
  33:   
  34:      protected override void OnApplyConfiguration(ServiceEndpoint endpoint, 
                     ServiceEndpointElement serviceEndpointElement)
  35:      {
  36:          CompanyNameStandardEndpoint customEndpoint = (CompanyNameStandardEndpoint)endpoint;
  37:          customEndpoint.IsSecured = this.IsSecured;            
  38:      }
  39:   
  40:      protected override void OnApplyConfiguration(ServiceEndpoint endpoint, 
                     ChannelEndpointElement channelEndpointElement)
  41:      {
  42:          CompanyNameStandardEndpoint customEndpoint = (CompanyNameStandardEndpoint)endpoint;
  43:          customEndpoint.IsSecured = this.IsSecured;            
  44:      }
  45:   
  46:      protected override void OnInitializeAndValidate(
                     ServiceEndpointElement serviceEndpointElement)
  47:      {
  48:              
  49:      }
  50:   
  51:      protected override void OnInitializeAndValidate(
                     ChannelEndpointElement channelEndpointElement)
  52:      {
  53:             
  54:      }
  55:  }

The above code is a basic configuration element code. The most important part is lines 13-17 in which you need to repeat each of the properties you created in the custom standard element (for a mapping between XML and CLR) and line 24 where you add all the properties that can be set in the configuration file, so the configuration can be validated.

Once you create the above code, you need just on more step to use the new endpoint kind in your configuration – you need to tell WCF that you have a new service endpoint. To do that you add the following XML in your <system.serviceModel> section:

   1:  <extensions>
   2:      <endpointExtensions>
   3:          <add
   4:        name="companyNameEndpoint"
   5:        type="TestWcfStandardEndpoints.CompanyNameStandardEndpointCollectionElement, 
                   TestWcfStandardEndpoints"/>
   6:      </endpointExtensions>
   7:  </extensions>

Note: On MSDN you can find a good explanation on standard endpoints, but the extensions configuration part is incorrect, the above configuration is the correct one (the correct element in the <extensions> is <endpointExtensions> and not <standardEndpointExtensions> as it appears in the article).

Now you are ready to declare your new endpoints and configure them:

   1:  <services>
   2:      <service name="TestWcfStandardEndpoints.Service1">
   3:          <endpoint binding="basicHttpBinding"
   4:              contract="TestWcfStandardEndpoints.IService1"/>
   5:          <endpoint address="mex"
   6:              kind="mexEndpoint" />
   7:          <endpoint address="companySecured"
   8:              kind="companyNameEndpoint"
   9:              endpointConfiguration="securedEndpoint"
  10:              contract="TestWcfStandardEndpoints.IService1"/>
  11:      </service>
  12:  </services>
  13:   
  14:  <standardEndpoints>
  15:      <companyNameEndpoint>
  16:          <standardEndpoint isSecured="true" name="securedEndpoint"/>
  17:      </companyNameEndpoint>
  18:  </standardEndpoints>

In lines 7-10 we define the endpoint with the new “kind” (line 9) and specify where we configure the rest of the endpoint (line 10).

Lines 14-18 contains the configuration of the standard endpoint which we created.

So to conclude, standard endpoints are an easy way to create fully-configured endpoints with binding configuration, contract settings, and endpoint behaviors. It’s mostly useful when wanting to create the same endpoint over and over again in multiple projects (which happens in 99.99% of the time).

Don’t bother copy pasting all the above code – you can just download the complete solution from here.

License

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

Share

About the Author

Ido Flatow
Architect Sela Group
Israel Israel
Web developer since 1997. I'm a senior architect at Sela Group in Israel. I'm a consultant, trainer (Microsoft MCT), and a speaker in conferences worldwide.
My main fields are WCF, ASP.NET, Windows Azure, IIS, Entity Framework, and Silverlight.
Follow on   Twitter

Comments and Discussions

 
QuestionSQL CLR function, missing Endpoint Pinmemberjo@risc15-Mar-13 0:24 
GeneralMy vote of 5 PinmemberKarthik Bahiradan3-Nov-12 7:14 
GeneralMy vote of 5 Pinmembermanoj kumar choubey25-Apr-12 21:03 
GeneralMy Vote of 5 Pinmembermkernbach12-Feb-12 1:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140827.1 | Last Updated 2 Feb 2012
Article Copyright 2012 by Ido Flatow
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid