There had to be some significant changes made to how a
client consumes a service if Microsoft wanted to preserve the boundaries are
explicit tenet. If you look at how an ASMX client works today, you do not
make any explicit decisions about how you want to communicate with a service.
Of course, I should mention that there were not a variety of options like there
are today with WCF services.
Another primary tenet of service orientation is that
communication is policy-based. The configuration at the client will specify
all of the policy settings that have to match the service features in order for
communication to occur. The following is an example of a client configuration
file (App.config), a simple command window client (ShowMeTheFunny.cs), and a
generated proxy class (FamilyGuyQuotes.cs).
App.config
<system.serviceModel>
<client>
<endpoint configurationName="default"
address="http://tomlaptop/Service/FamilyGuyQuotes.svc"
bindingConfiguration="IFamilyGuyGoodies" bindingSectionName="customBinding"
contractType="IFamilyGuyGoodies">
<addressProperties identityData="" identityType="None" isAddressPrivate="false" />
</endpoint>
</client>
<bindings>
<customBinding>
<binding configurationName="IFamilyGuyGoodies">
<contextFlow transactions="Ignore" transactionHeaderFormat="OleTx" logicalThreadId="Ignore" locale="Ignore" />
<httpTransport manualAddressing="false" maxMessageSize="65536"
authenticationScheme="Anonymous" bypassProxyOnLocal="false"
hostnameComparisonMode="StrongWildcard" mapAddressingHeadersToHttpHeaders="true"
proxyAuthenticationScheme="Anonymous" realm="" transferTimeout="00:01:00"
useSystemWebProxy="true" />
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap11Addressing1" encoding="utf-8" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
ShowMeTheFunny.cs
using (FamilyGuyGoodiesProxy
proxy = new FamilyGuyGoodiesProxy("default"))
{
string
s = Console.ReadLine();
string
result = proxy.GetQuote(s);
Console.WriteLine("Quote From {0} is: {1}", s, result);
}
FamilyGuyQuotes.cs (Generated Proxy)
[System.ServiceModel.ServiceContractAttribute(Namespace="http://familyguyquotes")]
public interface IFamilyGuyGoodies
{ [return:]
string
GetQuote(string familyGuyCharacter);
}
public partial class FamilyGuyGoodiesProxy
: System.ServiceModel.ProxyBase<IFamilyGuyGoodies>, IFamilyGuyGoodies
{
public
FamilyGuyGoodiesProxy(string configurationName)
:
base(configurationName)
{
}
public
string GetQuote(string
familyGuyCharacter)
{
return
base.InnerProxy.GetQuote(familyGuyCharacter);
}
}
What will probably stand out initially with the code above
is the confusing nature of the app.config. Not to worry, this is simply the
default that is generated from the SvcUtil.exe that comes with WCF. It is my
understanding that this will be simplified in an upcoming release.
Notice that it specifies a custom binding for me and set
every property possible. What would be better is if it would have allowed me
to specify the Basic Profile binding and set the configuration correctly to
reflect that. I am sure this is something the WCF team is looking into.
The code that actually invokes the service is very simple.
Notice, we specify the configuration section that will give us all of the
detail we need to invoke the actual request to the service. This is, of
course, a configuration-based approach. Also notice that the service is
wrapped in a using() block. This is because services written with WCF have
explicit Close() operations that release the resources being held by the
client. Please note, this is a subset of the code sample available for download.
The last code snippet above is the generated proxy class
named FamilyGuyQuotes.cs. I have removed many of the attributes in this class
to help improve readability. If you want to get the full picture, you will
need to look at the code available for
download. What you should be able to recognize from this snippet is the
utilization of generics for creating the proxy as the same type I defined in
the service called IFamilyGuyGoodies. You probably will also notice some other
significant differences to the ASMX proxies. Notice there are no Begin and
End methods defined by default. These methods are only created if you are
explicitly using async communication. Also, youll notice I have only used
simple types at this time, so there are no data elements defined. If I had,
you would have seen that the existing limitations with proxy type creation have
been resolved. The proxy types will not use fields when properties are defined;
in previous versions of VS.NET, the proxies would be converted to public fields
by default. This issue caused some headaches when attempting to bind those
types to server controls in ASP.NET.
Doesnt This Seem a Little Excessive?
On the surface this does appear to be a little
overwhelming. The configuration is very explicit, and the proxy is using some
very new features found in .NET 2.0. I will add that VS.NET 2005 still has
very little support for working with WCF services. What you will find is that
youll have to spend a lot of time working with the command window, and youll
spend some time mapping file types to VS.NET because it really doesnt
understand what a .svc is. Fortunately, in my conversations with the WCF team,
they have committed to making these things much easier by the time they RTM.
The Add Reference capability will be there at some point, and the
configuration detail will be simplified to include only those items that are
necessary for communication.
What I do hope is that they do not oversimplify things.
This is a huge step toward requiring explicit definition of the communications
between clients and services. This helps a client reinforce that it does
understand its boundaries at the time it adds a reference and wants to start
invoking operations.