WELCOME

This blog is where I post about my consulting work with Microsoft Technologies, and other random tidbits that don't fit in my Photo Blog or my Iraq Blog.

Thursday, July 24, 2008

Implementing a simple HelloWorld service in WCF using Interfaces and generic proxies

I needed a complete end to end demonstration of a .NET service implemented in WCF and taking advantage of Interface based contracts and generic proxies. I found lots of bits and pieces on the web, but I thought I would post my complete demo here in case somebody else finds value in it...

First the interface that defines our service contract:


using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

namespace SandBox.SharedClassLibrary

{

[ServiceContract]

public interface IHelloWorld

{

[OperationContract]

string GetHelloWorld(string Request);

}

}



The service itself (note in this case we are hosting the service in a ASP.NET project on IIS 7.0):


using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.Text;

using SandBox.SharedClassLibrary;

namespace SandBoxWeb

{

public class HelloWorldService : IHelloWorld

{

public string GetHelloWorld(string Request)

{

return Request + DateTime.Now.ToShortTimeString();

}

}

}



The web.config for the service:


<system.serviceModel>

<behaviors>

<serviceBehaviors>

<behavior name="SandBoxWeb.Service1Behavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

</behavior>

</serviceBehaviors>

</behaviors>

<services>

<service behaviorConfiguration="SandBoxWeb.Service1Behavior" name="SandBoxWeb.HelloWorldService">

<endpoint address="" binding="wsHttpBinding" contract="SandBox.SharedClassLibrary.IHelloWorld">

<identity>

<dns value="localhost"/>

</identity>

</endpoint>

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

</service>

</services>

</system.serviceModel>



The client application which is a console application:

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using System.ServiceModel;

namespace SandboxConsole

{

class Program

{

static void Main(string[] args)

{

Console.WriteLine(SandBox.SharedClassLibrary.ServiceClient.CallServiceByName("WSHttpBinding_HelloWorldService"));

Console.WriteLine(SandBox.SharedClassLibrary.ServiceClient.CallServiceByAddress("http://localhost:3456/HelloWorldService.svc"));

Console.ReadLine();

}

}

}




public class ServiceClient

{

public static string CallServiceByName(string EndPointName)

{

using (GenericProxy<IHelloWorld> service = new GenericProxy<IHelloWorld>(EndPointName))

{

return service.Channel.GetHelloWorld("Test by Name");

}

}

public static string CallServiceByAddress(string EndPointAddress)

{

Binding _binding = new WSHttpBinding();

EndpointAddress _endpointAddress = new EndpointAddress(EndPointAddress);

using (GenericProxy<IHelloWorld> service = new GenericProxy<IHelloWorld>(_binding, _endpointAddress))

{

return service.Channel.GetHelloWorld("Test by Address");

}

}

}



The (optional) app.config for the console application. This very verbose version was created for demonstration purposes using the "Create Service Reference" command.

Note: The second version of our call doesn't use the app.config at all.


<system.serviceModel>

<bindings>

<wsHttpBinding>

<binding name="WSHttpBinding_HelloWorldService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">

<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>

<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>

<security mode="Message">

<transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/>

<message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/>

</security>

</binding>

</wsHttpBinding>

</bindings>

<client>

<endpoint address="http://localhost:3456/HelloWorldService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_HelloWorldService" contract="SandBox.SharedClassLibrary.IHelloWorld" name="WSHttpBinding_HelloWorldService">

<identity>

<dns value="localhost"/>

</identity>

</endpoint>

</client>

</system.serviceModel>



Finally our GenericProxy class that creates the Channel that we use to call the service:


public class GenericProxy<T> : System.ServiceModel.ClientBase<T> where T : class

{

T _serviceInstance;

public GenericProxy(string endpointName)

: base(endpointName)

{

}

public GenericProxy(Binding ServiceBinding, EndpointAddress ServiceEndpointAddress)

: base(ServiceBinding, ServiceEndpointAddress)

{

}

public new T Channel

{

get

{

if (_serviceInstance == null)

{

//this.ChannelFactory.Credentials.UserName.UserName = "user";

//this.ChannelFactory.Credentials.UserName.Password = "123456";

_serviceInstance = this.ChannelFactory.CreateChannel();

}

return _serviceInstance;

}

}

}

No comments: