Friday, May 15, 2009

Exposing 2 EndPoints for same WCF service using different Bindings

The main attraction of WCF, when I started was it’s ability to expose a service using more than 1 endpoint with different bindings.Yesterday I just created a simple which exposes a service through 2 different endpoints which uses different bindings.One is basicHttpBinding and another using wsHttpBinding.

Before continuing please have a look at these links about ABC ,only if you are not aware of WCF yet.

http://msdn.microsoft.com/en-us/library/aa480190.aspx
http://bloggingabout.net/blogs/dennis/archive/2006/10/18/WCF-Part-1-_3A00_-Services-ABC.aspx
http://en.csharp-online.net/WCF_Essentials%E2%80%94What_Is_WCF%3F

Specifying 2 EndPoints

If you have a basic idea about WCF you can easily understand the below configuration in web.config which exposes  Uploader service through 2 different end points.

<services>
<service behaviorConfiguration="DemoMTOM.Web.UploaderBehavior" name="DemoMTOM.Web.Uploader">
<endpoint address="bh" binding="basicHttpBinding" contract="DemoMTOM.Web.IUploader">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="wh" binding="wsHttpBinding" contract="DemoMTOM.Web.IUploader">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>

In the sample the url to the basicHttpBinding endpoint is http://localhost:64738/Uploader.svc/bh and the url to the wsHttpBinding endpoint is http://localhost:64738/Uploader.svc/wh. You can check this by adding a service reference in to a WPF application.


Creating ServiceClient to call the service in WPF
When we create service reference in the WPF application, the app.config in the WPF application will get 2 entries.One for basicHttpBinding and another for wsHttpBinding.See the sample app.config below.


<client>
<endpoint address="http://localhost:64738/Uploader.svc/bh" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IUploader" contract="UploadServiceReference.IUploader"
name="BasicHttpBinding_IUploader" />
<endpoint address="http://localhost:64738/Uploader.svc/wh" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IUploader" contract="UploadServiceReference.IUploader"
name="WSHttpBinding_IUploader">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>


So at the calling side there will be confusion of course in selecting the end point.So to resolve that confusion we have to specify the endPointConfigurationName at the time of creating client.See code below which uses the basicHttpBinding.


UploadServiceReference.UploaderClient cli = new UploadServiceReference.UploaderClient("BasicHttpBinding_IUploader");
string res = cli.DoWork("Joy");


UploadServiceReference.UploaderClient cli = new UploadServiceReference.UploaderClient("WSHttpBinding_IUploader");
string res = cli.DoWork("Joy");

The second code snippet uses wsHttpBinding to call the service.

Hosting service using 2 endpoints in a Console Application

static void Main(string[] args)
{
try
{
ServiceHost serviceHost = new ServiceHost(typeof(Uploader),
new Uri("http://localhost:64738/Uploader.svc"));

serviceHost.AddServiceEndpoint(typeof(IUploader), new BasicHttpBinding(), "bh");
serviceHost.AddServiceEndpoint(typeof(IUploader), new WSHttpBinding(), "wh");

ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(smb);

ServiceDebugBehavior sdb = serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;

serviceHost.Open();

Console.WriteLine("Service running below are the Endpoints :");
foreach (ServiceEndpoint se in serviceHost.Description.Endpoints)
{
Console.WriteLine(se.Address.ToString());
}
Console.WriteLine("Press any key to quit...");
Console.ReadLine();

serviceHost.Close();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error :{0}", ex.Message));
Console.ReadLine();
}
}

In the sample when you try to run the console application it will throw an error because the asp.net application also runs and uses the same port.So run the console application from command line or explorer.

There is no need to change the reference in the WPF application since both these console application and asp.net service host is using same url.

Silverlight application in the sample is created using Silverlight 3.Remove that project if you don’t have Silverlight 3 installed in your machine.
Download sample from here.

No comments: