Hi,
Few days back I was trying to add custom behaviour to my WCF service and found out that many users have issues in adding these behaviour to the congig file so I thought of sharing the code to implment IEndpointBehavior and IServiceBehavior and adding these behaviors to the WCF service configuration file.
In the code below I have implemented Validate method to throw an exception at runtime when the contract is two way. So we will get an exception at the runtime during host.Open().
I have also shared the App.config file where these behaviors are added to EndpointBehaviours and ServiceBehaviours sections.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Configuration;
using System.ServiceModel;
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
ServiceHost serviceHost = new ServiceHost(typeof(ServiceContracts));
serviceHost.Open();
Console.WriteLine("Service is running..");
Console.Read();
}
}
public class ServiceContracts : IServiceContract
{
public void Method1()
{
return;
}
}
public class EndpointBehaviorMessageInspector : BehaviorExtensionElement, IDispatchMessageInspector, IClientMessageInspector, IEndpointBehavior
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
Console.WriteLine("AfterReceiveRequest called.");
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Console.WriteLine("BeforeSendReply called.");
}
public override Type BehaviorType
{
get { return typeof(EndpointBehaviorMessageInspector); }
}
protected override object CreateBehavior()
{
return new EndpointBehaviorMessageInspector();
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
return;
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
return "";
}
// IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
{
behavior.MessageInspectors.Add(new EndpointBehaviorMessageInspector());
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new EndpointBehaviorMessageInspector());
}
public void Validate(ServiceEndpoint serviceEndpoint)
{
if (serviceEndpoint.Contract.Operations[0].IsOneWay.Equals(false))
{
throw new ArgumentException("One way is not allowed");
}
}
}
public class EnforceGreetingFaultBehavior : BehaviorExtensionElement, IServiceBehavior, IEndpointBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
return;
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint se in serviceDescription.Endpoints)
{
if (se.Contract.Operations[0].IsOneWay.Equals(false))
{
throw new ArgumentException("Sorry, contract needs to be two way");
}
}
}
public override Type BehaviorType
{
get { return typeof(EnforceGreetingFaultBehavior); }
}
protected override object CreateBehavior()
{
return new EnforceGreetingFaultBehavior();
}
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
return;
}
public void Validate(ServiceEndpoint endpoint)
{
throw new NotImplementedException();
}
}
[ServiceContract]
public interface IServiceContract
{
[OperationContract(IsOneWay = false)]
void Method1();
}
}
Application configuration file to add behaviour is below.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttpConfig">
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="MyNamespace.ServiceContracts" behaviorConfiguration="metadataSupport">
<host>
<baseAddresses>
<add baseAddress="http://localhost:50002/MyAddressOn"/>
</baseAddresses>
</host>
<endpoint contract="MyNamespace.IServiceContract" bindingName="basicHttpConfig" binding="basicHttpBinding"
bindingConfiguration="basicHttpConfig" address="http://localhost:50002/MyAddressOn"
behaviorConfiguration="MyEndpointBehavior">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadataSupport">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:50002/MyAddressOn"/>
<!–Add the new custom service behaviour to service behavior–>
<MyServiceBehavior/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehavior">
<!–add the custom endpointbehavior to endpoint behavior–>
<MyEndpointBehavior/>
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<!–Type here is typeof(EndpointBehaviorMessageInspector).AssemblyQualifiedName–>
<add name="MyEndpointBehavior" type="MyNamespace.EndpointBehaviorMessageInspector, Blog1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<add name="MyServiceBehavior" type="MyNamespace.EnforceGreetingFaultBehavior, Blog1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
Thanks,