20071217

WCF and Building your own Awesome WCF Web Service Proxy

Hate using the svcutil.exe to generate your proxy for a WCF web service? Ever wondered if you can make it generic? You came to the right place!

I can't stand the MPP WCF Service Factory, I don't like svcutil, so I tried to make it pimp!

So for this example, we will be getting 3 pimp names from a wcf web service. If you are not familliar with WCF, here are some things that I did:


  1. Used BasicHttpBinding to be backwards compatible with classic ASP.net
  2. Implemented impersonation (refer to the web.config in the clientcredential type)
  3. Did not use a *.config file on the client end, and hand rolled an awesome factory class that does some WCF kungfu!
  4. Ofcourse, NUnit skillz
Let's start with the service

PimpNameService.svc

<%@ ServiceHost Language="C#" Debug="true" Service="AwwYeaFoo.PimpNameService" CodeBehind="PimpNameService.cs" %>


<%@ ServiceHost Language="C#" Debug="true" Service="AwwYeaFoo.PimpNameService" CodeBehind="PimpNameService.cs" %>


PimpNameService.cs

using System.Collections.Generic;

using System.ServiceModel;

using AwwYeaFoo.Interface;

namespace AwwYeaFoo

{

public class PimpNameService : IPimpNameService

{

[OperationBehavior(Impersonation = ImpersonationOption.Required)]

public IEnumerable<string> GetAllPimpNames()

{

IList<string> pimpNames = new List<string>();

pimpNames.Add("Python");

pimpNames.Add("Diamond Trim");

pimpNames.Add("Reverend J Fresh");

return pimpNames;

}

}

}



IPimpNameService.cs

using System.Collections.Generic;

using System.ServiceModel;

namespace AwwYeaFoo.Interface

{

[ServiceContract]

public interface IPimpNameService

{

[OperationContract]

IEnumerable<string> GetAllPimpNames();

}

}



web.config

<configuration>

<system.serviceModel>

<services>

<service behaviorConfiguration="returnFaults" name="AwwYeaFoo.PimpNameService">

<endpoint binding="basicHttpBinding" bindingConfiguration="PimpBinding"

name="PimpNameServiceEndPoing" contract="AwwYeaFoo.Interface.IPimpNameService" />

</service>

</services>

<behaviors>

<serviceBehaviors>

<behavior name="returnFaults">

<serviceMetadata httpGetEnabled="true" />

</behavior>

</serviceBehaviors>

</behaviors>

<bindings>

<basicHttpBinding>

<binding name="PimpBinding">

<security mode="TransportCredentialOnly">

<transport clientCredentialType="Windows" />

</security>

</binding>

</basicHttpBinding>

</bindings>

</system.serviceModel>

</configuration>



The Test

[Test]

public void Should_get_all_pimp_names_using_the_AwesomeWCFWebServiceProxy()

{

using (AwesomeWCFWebServiceProxy<IPimpNameService> proxy =

new AwesomeWCFWebServiceProxy<IPimpNameService>(@"http://localhost/AwwYeaFoo/pimpnameservice.svc"))

{

IEnumerable<string> pimpNames = proxy.GetProxy().GetAllPimpNames();

foreach (string pimpName in pimpNames)

{

Console.Out.WriteLine(pimpName);

}

}

}



AwesomeWCFWebServiceProxy.cs


public class AwesomeWCFWebServiceProxy<WCFWebServiceInterface> : IDisposable

{

private BasicHttpBinding binding;

private ChannelFactory<WCFWebServiceInterface> factory;

protected WCFWebServiceInterface proxy;

private readonly string url;

public AwesomeWCFWebServiceProxy(string url)

{

this.url = url;

InitializeHTTPBinding();

InitializeChannelFactory();

InitializeProxy();

}

private void InitializeHTTPBinding()

{

binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);

binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

}

private void InitializeChannelFactory()

{

factory = new ChannelFactory<WCFWebServiceInterface>(

binding, new EndpointAddress(url));

factory.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;

}

private void InitializeProxy()

{

proxy = factory.CreateChannel();

}

public WCFWebServiceInterface GetProxy()

{

return proxy;

}

public void Dispose()

{

((IChannel)proxy).Close();

factory.Close();

}

}

0 comments: