Introduction
Windows
Communication Foundation (WCF) is a framework for building service-oriented
applications. It allows developers to configure services using configuration
files or code. Though the configuration settings can be defined through code,
it would be easier after being deployed for administration if we put these
settings in a configuration file. But when the configuration file becomes too
large, the pain comes in. Usually the WCF Configuration Schema is complex and
provides user with many hard to find features. WCF 4.0 comes with new features
“Simplified Configuration” to remove this
pain through support for default endpoints, binding and behavior
configurations. In this article, I am going to introduce WCF 4.0 configuration
model updates. I will explain step by step the followings features:<o:p>
WCF 3.x required at least one endpoint, otherwise you would get an
exception. In WCF 4.0, services originate with default endpoints, that is,
runtime automatically adds one or more default endpoints making the service available
without any configuration. The runtime will add default endpoints based on the
combination of each service contract implemented by the service and base
addresses. Say, if the service implements a single contract and the host is
configured with a single base address, the runtime will add a single default
endpoint. If we configure the host with two base addresses and the service
implements a single contract, it will add two default endpoints. As an example, please have a look at the code given below.
Service Contract
[ServiceContract]
public interface IMessageService
{
[OperationContract]
string GetMessage(string submittedMsg);
}
Implementation
public class MessageService:IMessageService
{
public string GetMessage(string submittedMsg)
{
if(!string.IsNullOrEmpty(submittedMsg))
{
return submittedMsg;
}
return string.Empty;
}
}
Host Configuration
using(var host=new ServiceHost(typeof(MessageService),
new Uri("net.tcp://localhost/netTCP"),
new Uri("http://localhost/http")))
{
host.Open();
host.Description.Endpoints.ToList().ForEach((endPoint)=>
Console.WriteLine(endPoint.ListenUri));
Console.WriteLine("Press Enter to Exit");
Console.Read();
}
In the above code
portion, we see that the service implements a
single contract. And host is configured with two base addresses, one for TCP and
the other for Http. In this case, runtime will automatically add two default
endpoints.
WCF
decides which binding to use for a particular based address depending on a
default protocol mapping between transport protocol schemes and the built-in
WCF bindings. The default protocol mapping is found in the .NET 4
machine.config.comments file and it looks like this:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="basicHttpBinding" bindingConfiguration="" />
<add scheme="net.tcp" binding="netTcpBinding" bindingConfiguration=""/>
<add scheme="net.pipe" binding="netNamedPipeBinding" bindingConfiguration=""/>
<add scheme="net.msmq" binding="netMsmqBinding" bindingConfiguration=""/>
</protocolMapping>
...
We can
override these mappings at the machine level by adding this section to
machine.config
and changing the mapping for each protocol scheme. Or if we'd
only like to override it within the room of an application, we can override
this section within our application/web configuration file. In our demo project,
we map the Http
to wsHttpBinding
.
<protocolMapping>
<remove scheme="http"/>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
Once WCF
determines which binding to use via the protocol mapping table, it uses the
default binding configuration when configuring the default endpoint.
We can define
default binding by simply defining the binding without a name. This binding
will take consequence for anything not assigned a specific binding. We can
define it in a different scope like machine.config. For example, if we add the
following app.config file to our demo application, the default HTTP endpoints
will pick up this default configuration, which enables MTOM.
<bindings>
<wsHttpBinding>
<binding messageEncoding="Mtom"/>
</wsHttpBinding>
</bindings>
In WCF 3.x, we have to define named behavior configurations that we explicitly apply to services and endpoints through the “behaviorConfiguration
” attribute. Likewise default binding, we can also define default behavior by simply defining the behavior without a name, which can shorten stuff when we need to share a standard default behavior configuration across all services or endpoints. The following code portion turns on service metadata for any services that don’t come with an explicit behavior configuration.
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
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. WCF 4.0 also comes
with several preconfigured standard endpoints which cover some of the most
common usage scenarios by simply reusing them as-is without change. For example,
in the case of a MEX endpoint, we will always need to specify
IMetadataExchange
for the service contract and are most likely to choose HTTP.
So instead of doing manually, WCF provides a standard endpoint definition for metadata
exchange called “mexEndpoint
” that’s easy to use. We can refer to the standard endpoints
by name using the kind attribute.
<services>
<service name="MessageService">
<endpoint kind="mexEndpoint" address="/mex"/>
</service>
</services>
Although .svc files make it easy to expose WCF services, with WCF
4.0 we no longer need physical .svc file to activate services. Instead, we can define
a virtual mapping in config. The following example shows how to configure an
activation endpoint:
<services>
<service name="FileLessActivationDemo.NoSvc">
<endpoint kind="webHttpEndpoint"
contract="FileLessActivationDemo.IMessageService"/>
<endpoint kind="mexEndpoint" address="/mex"/>
</service>
</services>
It’s
now possible to activate the NoSvc
using a relative path of “NoSvc.svc
”
(relative to the base address of the Web application).
Using the Solutions
To see the output of demo application, you need to run Rashim.RND.WCF.ConfigurationModel.Server
first and then run Rashim.RND.WCF.ConfigurationModel.Client
.
In the app.config file of Rashim.RND.WCF.ConfigurationModel.Server
,
you will see some new things that I have already described above. The
configuration file looks like below:
="1.0"="utf-8"
<configuration>
<system.serviceModel>
<protocolMapping>
<remove scheme="http"/>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding messageEncoding="Mtom"/>
</wsHttpBinding>
</bindings>
<services>
<service name="MessageService">
<endpoint kind="mexEndpoint" address="/mex"/>
</service>
</services>
</system.serviceModel>
</configuration>
To see the output of File-less activation, please run the project FileLessActivationDemo
and you will see the directory list where there is no NoSvc.svc file. But if you write in the addressbar
like http://localhost...../NoSvc.svc, you will see that the NoSvc.svc is activated. The configuration file for this application looks like:
="1.0"
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="True">
<serviceActivations>
<add service="FileLessActivationDemo.NoSvc" relativeAddress="NoSvc.svc"/>
</serviceActivations>
</serviceHostingEnvironment>
<protocolMapping>
<remove scheme="http"/>
<add scheme="http" binding="wsHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="FileLessActivationDemo.NoSvc">
<endpoint kind="webHttpEndpoint" contract="FileLessActivationDemo.IMessageService"/>
<endpoint kind="mexEndpoint" address="/mex"/>
</service>
</services>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
References
That's It
That's it for now. I hope this article will help you to know updates of WCF 4.0 configuration model.