2005 2006 2007 2008 2009 2010 2011 2015 2016 2017 aspnet azure csharp debugging elasticsearch exceptions firefox javascriptajax linux llblgen mongodb powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

Understanding WCF Versioning ("My Random Notes" Edition)

I never got around to putting the following into something pretty and eloquent... and might not blog any more, but here are my raw notes I would have used to write something more full.


WCF Service Contract Versioning

Clients calls a service interface, not an implemenation. It identifies a particular interface via the WCF namespace set on the service contract on the service. As long as the client calls an interface with a particular namespace on the service side, the call will be allowed.

Strong Versioning

For example, if a client is using the following service contract, it can only call this contract using its full XML namespace. The namespace is specified with the Namespace property of the ServiceContract attribute. However, the interface that is called is the specified namespace suffixed with the interface name. This gives a feel very similar to that of .NET's namespace system which allows for namespaces for organization and full types as the types namespace suffixed with the type name.

As an example, see the following interface is accessed via the "http://www.abccorp.com/services/sample01/2007/02/IServiceV1" identifier.

[ServiceContract(Namespace="http://www.abccorp.com/services/sample01/2007/01")]
public interface IServiceV1
{
    [OperationContract]
    String GetData(Int32 value);
}

If, however, the month portion of a namespace is changed from version 01 to 02, as the following example demonstrate, the client would immediately break as it would still be calling via the old identifier.

[ServiceContract(Namespace="http://www.abccorp.com/services/sample01/2007/02")]
public interface IServiceV1
{
    [OperationContract]
    String GetData(Int32 value);
}

On the service-side there is no "magic" that allows one service to be access over another. The client accesses a specific interface and that specific iterface is of course assigned as a WCF endpoint. Therefore, each version requires it's own endpoint. However, an endpoint doesn't mean another entire host, power, or base URI. In an HTTP environment, this simply means that the endpoint identifier is suffixed to the actual service URI.

For example, instead an address of "" (blank), the address is an arbitrary endpoint identifier as seen below:

Before

<endpoint address="" binding="basicHttpBinding" contract="IService" />

After

<endpoint address="v1" binding="basicHttpBinding" contract="IServiceV1" />
<endpoint address="v2" binding="basicHttpBinding" contract="IServiceV2" />

This will be mentioned in a bit more detail in a later section.

Lax Versioning

Assume the following service service contract, implementation, and endpoint:

[ServiceContract(Namespace = "http://www.abccorp.com/services/sample01/2007/02")]
public interface IServiceV1
{
    [OperationContract]
    String GetData(Int32 value);
}

public class Service : IServiceV1
{
    public String GetData(Int32 value) {
        return String.Format("You send {0}.", value);
    }
}

<endpoint address="v1" binding="wsHttpBinding" contract="IServiceV1" />

At this point, if the client gets the service metadata and creates a proxy, the client may send the following:

using (ServiceV1Client client = new ServiceV1Client("WSHttpBinding_IServiceV1")) {
    Console.WriteLine(client.GetData(3));
}

Now, assume the service changes from Int32 to String with no version change.

[ServiceContract(Namespace = "http://www.abccorp.com/services/sample01/2007/02")]
public interface IServiceV1
{
    [OperationContract]
    String GetData(String value);
}

public class Service : IServiceV1
{
    public String GetData(String value) {
        return String.Format("You send {0}.", value);
    }
}

With updating the service proxy on the client, the client is strongly typed to an Int32. Therefore, the client will not be able to send a String to the server. However, the client will still function as the service implicitly converts the value to a String.

The reverse of this situation can also be true. If the service started out using a String and was changed to use an Int32, the client, even though it is bound to a String type, can send data to the server as long as it is castable to an Int32. See the following for an example:

// This will work
using (ServiceV1Client client = new ServiceV1Client("WSHttpBinding_IServiceV1")) {
    Console.WriteLine(client.GetData("4"));
}

// This will NOT work
using (ServiceV1Client client = new ServiceV1Client("WSHttpBinding_IServiceV1")) {
    Console.WriteLine(client.GetData("four"));
}

Strong and Lax Together

A service may serve service contracts as the following demonstrates

public class Service : IServiceV1, IServiceV2
{
    // ...
}

The service contracts have the same essence, but their operation signatures will differ.

[ServiceContract(Namespace = "http://www.abccorp.com/services/sample01/2007/02")]
public interface IServiceV1
{
    [OperationContract]
    String GetData(Int32 value);
}

[ServiceContract(Namespace = "http://www.abccorp.com/services/sample01/2007/02")]
public interface IServiceV2
{
    [OperationContract]
    String GetData(Int32 value, String code);
}

In this case, the namespace is the same, but this is in no way a requirement. Any portion of the namespace can change as they are two completely different contracts.

These two contracts also share a method with the same name. This is legal in .NET, but there is no such thing as "service overloading". That is, the overloading is only in .NET and does not transfer to the service. Therefore, as has been previously mentioned, each contract must have its own endpoint. Given that each endpoint is for the same service, only the following is requires:


When a client will specify which endpoint to call when it creates its service proxy. For example,

using (ServiceV1Client client = new ServiceV1Client("WSHttpBinding_IServiceV1")) {
    Console.WriteLine(client.GetData(4));
}

using (ServiceV2Client client = new ServiceV2Client("WSHttpBinding_IServiceV2")) {
    Console.WriteLine(client.GetData(3, "hello"));
}

The client's application configuration will contain references to each endpoint. For example, this client may have the following:

<endpoint
  address="http://localhost:2352/Website/Service.svc/v1"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV1"
  name="WSHttpBinding_IServiceV1" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v2"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV2"
  name="WSHttpBinding_IServiceV2" />

The client also needs a specific strongly typed proxy for each endpoint, but it is also trivial. Below is an example of a complete proxy; other proxies are created following the same pattern. The properties set in the attributes should be easy to comprehend. However, it should be explicitly stated that the ConfigurationName property of the ServiceContract attribute matches the contract stated in the client application configuration.

[ServiceContract(Namespace="http://www.abccorp.com/services/sample01/2007/02", ConfigurationName="ServiceReference1.IServiceV1")]
public interface IServiceV1 {
    
    [OperationContract(Action="http://www.abccorp.com/services/sample01/2007/02/IServiceV1/GetData", ReplyAction="http://www.abccorp.com/services/sample01/2007/02/IServiceV1/GetDataResponse")]
    String GetData(Int32 value);
}

public interface IServiceV1Channel : IServiceV1, IClientChannel {
}

public partial class ServiceV1Client : ClientBase, IServiceV1 {
    public ServiceV1Client() {
    }
    
    public ServiceV1Client(String endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }

    public ServiceV1Client(String endpointConfigurationName, String remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }

    public ServiceV1Client(String endpointConfigurationName, EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }
    
    public ServiceV1Client(Binding binding, EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }

    public String GetData(Int32 value) {
        return base.Channel.GetData(value);
    }
}

Given the simplicity of WCF, there is no reason to ever use tools like Visual Studio or svcutil.exe for proxy or configuration creation. Also, be aware that not all of the constructors for the proxy ("ServiceV1Client") are required.

It should also be explicitly stated that nothing that nothing here forbids the use of different bindings on each of the endpoints. For example, the following are legal endpoints on the client and Server:

Server

>endpoint address="v1" binding="basicHttpBinding" contract="IServiceV1" /<
>endpoint address="v2" binding="wsHttpBinding" contract="IServiceV2" //<

Client

>endpoint address="http://localhost:2352/Website/Service.svc/v1" binding="basicHttpBinding" contract="ServiceReference1.IServiceV1" name="WSHttpBinding_IServiceV1" /<
>endpoint address="http://localhost:2352/Website/Service.svc/v2" binding="wsHttpBinding" contract="ServiceReference1.IServiceV2" name="WSHttpBinding_IServiceV2" /<
If there are multiple bindings (B) and multiple contracts (C), then there needs to be B*C endpoints. For example, you may have the following: Server:
<endpoint address="v1/basic" binding="basicHttpBinding" contract="IServiceV1" />
<endpoint address="v2/basic" binding="basicHttpBinding" contract="IServiceV2" />
<endpoint address="v3/basic" binding="basicHttpBinding" contract="IServiceV3" />
<endpoint address="v4/basic" binding="basicHttpBinding" contract="IServiceV4" />

<endpoint address="v1/wshttp" binding="wsHttpBinding" contract="IServiceV1" />
<endpoint address="v2/wshttp" binding="wsHttpBinding" contract="IServiceV2" />
<endpoint address="v3/wshttp" binding="wsHttpBinding" contract="IServiceV3" />
<endpoint address="v4/wshttp" binding="wsHttpBinding" contract="IServiceV4" />

Client

<endpoint
  address="http://localhost:2352/Website/Service.svc/v1/basic"
  binding="basicHttpBinding"
  contract="ServiceReference1.IServiceV1"
  name="WSHttpBinding_IServiceV1_Basic" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v2/basic"
  binding="basicHttpBinding"
  contract="ServiceReference1.IServiceV2"
  name="WSHttpBinding_IServiceV2_Basic" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v3/basic"
  binding="basicHttpBinding"
  contract="ServiceReference1.IServiceV3"
  name="WSHttpBinding_IServiceV3_Basic" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v4/basic"
  binding="basicHttpBinding"
  contract="ServiceReference1.IServiceV4"
  name="WSHttpBinding_IServiceV4_Basic" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v1/wshttp"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV1"
  name="WSHttpBinding_IServiceV1_WSHttp" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v2/wshttp"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV2"
  name="WSHttpBinding_IServiceV2_WSHttp" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v3/wshttp"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV3"
  name="WSHttpBinding_IServiceV3_WSHttp" />
<endpoint
  address="http://localhost:2352/Website/Service.svc/v4/wshttp"
  binding="wsHttpBinding"
  contract="ServiceReference1.IServiceV4"
  name="WSHttpBinding_IServiceV4_WSHttp" />

Notice that neither the service contract, the service, nor the client proxy know anything about the bindings or the endpoints.

WCF Data Contract Versioning

If a v2 service sends a populated Person object to a v1 client, then the client will see a series of default values with the actual values being in the ExtensionData object. If the client sets its own data and sends that to the server, these values are effectively ignored.

For example, if the v2 service sends the following v2 data to the v1 client, the v1 client will see null.

return new Person()
{
    FirstName = "John",
    LastName = "Doe",
    Address1 = "1827 North South Street",
    City = "Winchestertonfieldville",
    State = "IA",
    Zip = "50182",
    Id = id
};

If the v1 client then proceeds to populate the v1 object and send it to the v2 service, the v2 service will completely ignore everything the v1 client has set because it is setting v1 data that the v2 service knows nothing about. The following client data, for example, is meaningless:

Person p = client.GetPerson(3);
p.Address = "Blank";
p.FirstName = "Jane";
client.SavePerson(p);

The v2 service will simply receive the same data it had previously send. That is, FirstName will still say "John".

The v2 service will accept the data from the v1 client if the v1 client had previously obtained that data from a v2 service. This is true even if the v2 data contract has a newly added data member which has IsRequired set to true.

However, if the client attempts to send a new v1 object to the v2 service, which has a v2 contract with a newly added data member with IsRequired set to true, a service fault will be thrown.

Client Data Contract

The data contract on the service is the same as the data contract on the client. Therefore the following is usable on both ends:

[DataContract(Namespace = "http://www.abccorp.com/services/sample01/datacontracts/2007/02")]
public class Person
{
    [DataMember]
    public Int32 Id { get; set; }

    [DataMember]
    public String FirstName { get; set; }

    [DataMember]
    public String LastName { get; set; }

    [DataMember(IsRequired=true)]
    public String Address1 { get; set; }

    [DataMember]
    public String Address2 { get; set; }

    [DataMember]
    public String City { get; set; }

    [DataMember]
    public String State { get; set; }

    [DataMember]
    public String Zip { get; set; }
}

This means that if the service sends an instance of this data contract to the client and does not have the Address1 property, a fault will occur. Given that IsRequired is checked at the destination, the fault will occur immediately when the client requests the data from the service.

In order to obtain data that is not strongly typed in the data member, you must implement the IExtensibleDataObject interface. This allows data that is unknown at the destination to be encapulated in an object. This is usable on both the client and service end. The data will be placed into the ExtensionData object which is of type ExtensionDataObject.

For example, if the server adds more data members to its data contract than what the client expects, the client will obviously not be able to populate this data into any local object. However, if the client data contract implements the IExtensibleDataObject interface, then any excess data members which the server sends to the client are placed into the ExtensionData property of the data contract instance. The functionality can be provided in a reverse manner as well. That is, if the client sends more information to ther service, if the service data contract implements the IExtensibleDataObject interface, then it will have the data encapulsated in a ExtensionData property. The IDesign standard, written by the designers of WCF, states that you should always implement this interface.

INotifyPropertyChanged

When using the Visual Studio generation tool, the data contracts that are created implement the INotifyPropertyChanged interface and have special logic in their set accessors to allow the client to monitor changes to properties. This in no way has any affect on the operations of WCF and are not required. Furthermore, given that the client service contract creation is trivial and that the data contract on the client is the same as the data contract on the server, it's recommended that all proxies be created by hand without use of Visual Studio or svcutil.exe.

Understanding WCF Faults in Silverlight

If you like this document, please consider writing a recommendation for me on my LinkedIn account.

Contents

Introduction

Regardless of what platform you are working with, you need some mechanism for dealing with errors.  When it comes to using WCF in Silverlight we are all very fortunate to be able to build out solutions on the back of many tried and true techniques for error management. When working in this context, we are dealing with basic SOAP messages (that is, XML) and WCF's abstraction of those messages, neither of which are new to the world.

If you haven't done so already, you should read the first part of this document entitled Understanding WCF Services in Silverlight (here after "previous document").  You may consider this document an appendix to that one.  That document explains WCF and its integration into the world of Silverlight from a very low level. This document extends that one to explain error management in the world of Silverlight 3. Understanding of the previous document is a prerequisite for understanding this one.

SOAP Review

Before we take a look at error management over SOAP services, we will take a moment to review SOAP messaging. SOAP messaging is based on the concept of sending SOAP messages back and forth between client and service. A SOAP message is the package by which a client and a service communicate. Web services (a.k.a. SOAP services) are not "connected" like a chat channel. Instead, they are "disconnected" like an e-mail system. The client sends the service a message and the service, optionally, sends the client message back (depending on if the client requested a message; one way messaging is very common). Below is a sample message sent from a client to the service:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetPersonData xmlns="http://www.netfxharmonics.com/service/Contact/2009/07/">
      <personGuid>F488D20B-FC27-4631-9FB9-83AF616AB5A7</personGuid>
    </GetPersonData>
  </s:Body>
</s:Envelope>

Essentially, this message is calling the "GetPersonData" operation on the service, sending "personGuid" as a parameter. This is stored in the message body (which is distinct from, say, a message header, which is not present in this example). The body is then stored in an envelope. When this message is sent via an HTTP POST to, for example, /Person.svc with the SOAP-Action HTTP header set to the name of the SOAP operation, WCF calls the appropriate operation (set by the SOAP-Action HTTP header).  For more information on the mechanics of WCF and how to work with WCF directly see my XmlHttp Service Interop series at http://www.netfxharmonics.com/2007/05/XmlHttp-Service-Interop-Part-3-XML-Serialization).

Here is a message the service could possibly send back to the client:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetPersonDataResponse xmlns="http://www.netfxharmonics.com/service/Contact/2008/11/">
      <GetPersonDataResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <City>Unknown</City>
        <FaultDetail i:nil="true" xmlns:a="http://schemas.datacontract.org/2004/07/General.Service"/>
        <FirstName>John</FirstName>
        <Guid>89DEA4C5-84A0-45db-A60D-CE49F214EA50</Guid>
        <LastName>Doe</LastName>
        <PostalCode>66062</PostalCode>
        <State>KS</State>
      </GetPersonDataResult>
    </GetPersonDataResponse>
  </s:Body>
</s:Envelope>

Here we have the data for "GetPersonData" in a result object, wrapped in a response container. This is then, once again, wrapped in a standard SOAP body, inside a standard SOAP envelope. Pretty simple stuff. Someone sends a message, the receiver sends something back. The question now becomes... what happens when something goes wrong?

Handling Errors

When doing error management with SOAP-based WCF, you are doing just that: error management. You are NOT doing exception management. Exceptions don't exist over the wire. How can an exception from WCF being handled by a PHP client? How can System.InvalidOperationException be handled by a Java client? These scenarios make no sense. Therefore, in the world of SOAP services, you have no exceptions. Instead, you have a concept called a "fault".  A fault is a SOAP error.  WCF, Java, and PHP can all deal with SOAP (since SOAP is just XML), thus, they each can deal with faults with no problem. Given this, we may adjust our terminology at this point from "error management" to "fault management".

In reality, a fault is nothing more than a piece of XML formatted in a specific way. One side sends it, the other side receives it. It's a really simple setup. (As a side note, please keep in mind that this is not a document on the internal mechanics of SOAP. That's a discussion for a different document. Fortunately, though, the understanding of faults in SOAP doesn't require deep SOAP knowledge.)

When an exception is thrown in a SOAP-based WCF service, typically a fault is sent over the wire. A SOAP-based client (be it WCF, WCF in Silverlight, PHP, or Java), then obtains it, parses it and handles it accordingly. So what's a SOAP fault look like? (you'll see later that this is an example of a very poor practice, but it's a good fault example.)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Really descriptive message here.</faultstring>
      <detail>
        <InvalidOperationException xmlns="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
          <ClassName i:type="x:string" xmlns="">System.InvalidOperationException</ClassName>
          <Message i:type="x:string" xmlns="">Really descriptive message here.</Message>
          <Data i:nil="true" xmlns=""/>
          <InnerException i:nil="true" xmlns=""/>
          <HelpURL i:nil="true" xmlns=""/>
          <StackTraceString i:nil="true" xmlns=""/>
          <RemoteStackTraceString i:nil="true" xmlns=""/>
          <RemoteStackIndex i:type="x:int" xmlns="">0</RemoteStackIndex>
          <ExceptionMethod i:nil="true" xmlns=""/>
          <HResult i:type="x:int" xmlns="">-2146233079</HResult>
          <Source i:nil="true" xmlns=""/>
        </InvalidOperationException>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Notice that even this fault is a SOAP message: the contents are in a SOAP body, wrapped in a SOAP envelope. So, all we really did is use a concept we already knew and added something to it. By sending a "Fault" XML element in a message body, you are effectively telling the client that some error occurred on the service-side. This is a well-known pattern that all SOAP services follow.

If you look closely at this SOAP message (which, of course, is also a fault), you will notice that the "Fault" element has three children: "faultcode", "faultstring" and "detail". You may recognize some parts of this specific fault.  That is, you see the name "InvalidOperationException" as well as the "Message", "InnerException", and other elements as well-known properties of exceptions. Keep in mind, though, that none of these have anything to do with faults. These are in the "detail" section of the fault, not in any part that actually matters.  Clear as mud?

Faults don't rely on the detail element. The information in this block is simply for the end developer to obtain custom information. Since WCF doesn't rely on this information, neither should you (i.e. it won’t always be there). A fault is defined by the "faultstring" element, not the "detail" element. The "faultstring" element contains is the actually message that you will want to look at when debugging.

Not even the "faultcode" element isn’t directly used by most people. This is a well-defined enumeration with the possible values of "Client", "Server", "VersionMismatch", and "MustUnderstand" (prefixed with the XML namespace). These help you to get some idea of the category of error that occurred, but, in the majority of cases, you won't be working with it directly.  This is all to reinforce the fact that it’s faultstring that contains the actual error, not faultcode or details.

Applying to WCF

In the world of WCF for .NET, all of this is essentially internal mechanics that most mid-level or entry-level developers will only see on a senior-level developer's whiteboard (i.e. they won't use it directly). This is because WCF knows to look for faults and knows how to handle them: it will take the content from faultstring and set that as the Message in a System.ServiceModel.FaultException object. This instance of a FaultException object is developers directly work with.

Now pay attention very closely: you can't just throw an exception in a WCF service and expect it to show up on your client (or to show up over the wire for that matter!) Why is this? Thikn about it... do you really want an exception which contains the entire stack trace and, therefore, a snapshot of the private internal mechanics of your system thrown to a client computer? Obviously not. Since WCF knows is a horrible security violation to send stack traces over the wire, it's not going to allow this.  In fact, that fault SOAP-message shown early is hopefully a picture from fiction, not reality (you kind of figured there were a lot of unneeded xml elements, didn't you?)

What you actually do, is you throw one of two special exceptions: System.ServiceModel.FaultException or System.ServiceModel.FaultException<T> (which inherits from the first one). When you throw an exception which isn't one of these, like System.InvalidOperationException, you will see the following over the wire (i.e. throw new System.InvalidOperationException("This is my error message.")):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
      <faultstring xml:lang="en-US">The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

You may think "not pretty". Trust me, that IS pretty. Ugly would be showing your internal stack trace over the wire. Thank you WCF for protecting us from ourselves.

Now, if you throw System.ServiceModel.FaultException instead of System.InvalidOperationException (i.e. throw new System.ServiceModel.FaultException("This is my error message."), you will see this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">This is my error message.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

Very simple and to the point. You told it "This is my error message." and it sent "This is my error message." Can't get much simpler than that.  In fact, the simplicity stays even when you work with the exception on the client side.  Over there, the client will also have a FaultException.  The “faultstring” from the SOAP message will be places into the Message property of the FaultException object on the client.  An example of this will be shown in a bit.

Let's make this a bit more complex (read: more useful/powerful) by changing things up slightly.

As I've said, there are two fault exception types in WCF: one generic, one not. Use of the generic one allows you to send more information to the client by allowing entire objects to be serialized over the wire as part of the fault "detail" element. To see an example of this, take a look at the following custom type:

namespace Contact.Service
{
    [DataContract]
    public class FaultDetail
    {
        //- @ErrorCode -//
        /// <summary>
        /// Custom business-specific error code.
        /// </summary>
        [DataMember]
        public Int32 ErrorCode { get; set; }
        //- @Type -//
        /// <summary>
        /// Specifies the type of error.
        /// </summary>
        [DataMember]
        public String Type { get; set; }
    }
}

Now, instead of throwing the non-generic fault exception, let's throw the generic one, using the above type as the generic parameter. For example:

//- @GetPersonData -//
public Person GetPersonData(String personGuid)
{
    //+ ...validation here...     
    FaultDetail faultDetail = new FaultDetail
    {
        Type = "Validation",
        ErrorCode = 63873928
    };     //+ throw     
    throw new FaultException<FaultDetail>(faultDetail, "Invalid guid.");
    //+ ...more logic here...
}

Given this, we now have this over the wire:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

As you can see, using the generic FaultException type, you can send all kinds of stuff over the wire.

Fault Contracts

While this is great for dynamically typed systems (i.e. PHP and JavaScript), we don't yet have a complete solution for strong-typed ones (i.e. .NET). What’s that? Again, think about it: How does the other end know what type is "FaultDetail". Is that ABCCorp.Web.FaultDetail? ABCCorp.Service.FaultDetail? What's the namespace? In what assembly?

To make this happen in .NET, we have to introduce something called a "fault contract". As you recall from the previous document, WCF has service contracts and operation contracts. Fault contracts are just another contract type in the contact family.

These are setup by applying the System.ServiceModel.FaultContractAttribute attribute to various operations of your service contract.  When you apply this attribute, you must tell it what type you would like to allow to be thrown from that specific operation.  This is simply done by giving the constructor of the fault contract attribute to type object of your fault detail type.  For example, below is our operation contract with the fault contract applied.

//- GetPersonData -//
[OperationContract]
[FaultContract(typeof(FaultDetail))]
Person GetPersonData(String personGuid);

If you're following along and paying close attention you should be thinking "How in the WORLD does that help the client? This is on the server! The same SOAP data is going to come over the wire and the client has no more information." Well, as you recall from the previous document, the contracts must be both on the service-side and on the client-side. In the case of .NET, these are the same types since the contracts are in an assembly shared by both client and service (remember, use of the "Add Service Reference" for .NET-to-.NET communication provides ZERO value and only complicates life).

So, if you are doing .NET-to-.NET, your client contract DOES have this and WCF on the client will automatically know to use that specific type when deserializing the “detail” part of the fault SOAP message.  Let's see this in action.

First, let's review our previous setup:

//+ basicHttpBinding
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");

This is all that's required to make a .NET-to-.NET WCF call. Setup a address-binding-contract combination to create a channel, then call the operation through the channel. Not a big deal. Now let's add one level of fault handing:

//+ basicHttpBinding
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
try
{
    Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException ex)
{
    //+ without fault contract     
    WriteToOutput("There was an error...(FaultException)");
    //+ this is the message from “faultstring” in the SOAP message     
    WriteToOutput(ex.Message);
}

This example shows handling a fault exception without having the first clue what type is being sent. We can, however, access the fault message by accessing Message property of the fault.  So, in this case, “ex.Message” will contain “Invalid guid.”.  Now let’s go one step further:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
try
{
    Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException<FaultDetail> ex)
{
    WriteToOutput("There was an error...(FaultException<FaultDetail>");
    //+
    FaultDetail detail = ex.Detail;
    WriteToOutput("ErrorCode: " + detail.ErrorCode.ToString());
    WriteToOutput("Type: " + detail.Type);
    //+ again, this is the message from “faultstring” in the SOAP message
    WriteToOutput(ex.Message);
}
catch (FaultException ex)
{
    WriteToOutput("There was an error...(FaultException)");
    WriteToOutput(ex.Message);
}

In this example, we are taking advantage of the fault contract on the client operation.  Notice that we have access to the  actual detail content that was sent over the wire.  Not only that, but we can access it as a true type via the Detail property of our generic fault exception. This makes things a lot easier.

Remember, the only difference these two examples is the presence of the fault contract on the client operation. If the fault contract were NOT on the client operation, then the "FaultException" catch-block would be caught, not the generic one.

Throwing Exceptions (Bad!)

At this point, you should be able to see that the original fault SOAP message I showed you involving the InvalidOperationException is, in fact, not entirely fictional. It is possible to send an exception over the wire. All you would need to do is something like this (in addition to setting up a fault contract on the client operation):

String message = "Invalid guid.";
throw new FaultException<InvalidOperationException>(new InvalidOperationException(message), message);

Having said this, throwing an exception over the wire is very poor form. It's not as bad as publicly exposing a private field, using the "var" C# keyword for non-anonymous types, or camelCasing() .NET method names, but it's still viewed as a very poor practice. Why? Well, you tell me. Take a look at the following two examples:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Really descriptive message here.</faultstring>
      <detail>
        <InvalidOperationException xmlns="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema">
          <ClassName i:type="x:string" xmlns="">System.InvalidOperationException</ClassName>
          <Message i:type="x:string" xmlns="">Really descriptive message here.</Message>
          <Data i:nil="true" xmlns=""/>
          <InnerException i:nil="true" xmlns=""/>
          <HelpURL i:nil="true" xmlns=""/>
          <StackTraceString i:nil="true" xmlns=""/>
          <RemoteStackTraceString i:nil="true" xmlns=""/>
          <RemoteStackIndex i:type="x:int" xmlns="">0</RemoteStackIndex>
          <ExceptionMethod i:nil="true" xmlns=""/>
          <HResult i:type="x:int" xmlns="">-2146233079</HResult>
          <Source i:nil="true" xmlns=""/>
        </InvalidOperationException>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

... and ... 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Notice that the first example (the exception) has many items going over the wire that are never even used, thus wasting serialization and deserialization processing time as well as bandwidth, not to mention making the SOAP message more difficult to read. Notice also that each of the elements in the second example (the fault detail) relate to the task at hand. Therefore, you should always define a fault detail type when dealing with fault exceptions.

Applying to Silverlight

Everything we discussed so far relating to the service applies to Silverlight. That is, you may use the same service for both Silverlight and .NET.  However, if you would like to use the strongly typed fault details in Silverlight as we discussed in .NET, then you need to apply the fault contract attribute to the Silverlight async operation (note: technically this has nothing to do with Silverlight; if you are using async calls in .NET, then Silverlight and .NET will share those).  More specifically, the "Begin" method of your operation contract. Here's an example:

//- BeginGetPersonData -//
[OperationContract(AsyncPattern = true)]
[FaultContract(typeof(FaultDetail))]
IAsyncResult BeginGetPersonData(String personGuid, AsyncCallback callback, Object state);

Note also that since Silverlight is NOT .NET, you have to get the fault detail from the .NET world over to the Silverlight world.  Now, given that nothing about the type is different in the .NET and Silverlight worlds, you can easily share it between the two.  On way to do this is by using the “Add As Link” feature in Visual Studio.  More more ways of sharing types and assemblies between .NET and Silverlight see my document entitled Reusing .NET Assemblies in Silverlight.

Now given this setup, you can upgrade your service access by wrapping your call to the "End" method in a try/catch block.

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost.:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    try { Person person = ((IPersonService)result.AsyncState).EndGetPersonData(result); Write(person.FirstName); }
    catch (FaultException<FaultDetail>)
    {
        Write("There was an error...(FaultException<FaultDetail)");
    }
    catch (FaultException)
    {
        Write("There was an error...(FaultException)");
    }
    catch (Exception)
    {
        Write("There was an error...(Exception)");
    }
};

When you run this, barring any other problems, you can expect that the FaultException<FaultDetail> catch block be called, since that's what's going on the .NET side.  Everything will work the same from here on out.  In fact, if you are doing async calls in the .NET world, your code won’t have any differences at all.

Service Modification for Silverlight

Notice that when I said that the FaultException<FaultDetail> catch block would be called, I said “barring any other problems”.  This is a very important little phrase.  In fact, if you did actually try to run the above example, you would see something rather shocking: the FaultException<FaultDetail> block was NOT hit.  Instead, the Exception block was.  At this point, if you are confused... then you’re probably following along just fine.

Thus, you begin debugging. First, you check the exception message (ex.Message). It says "The remote server returned an error: NotFound.". What? Whatever. Then you realize that you need to see what WCF sent back. So, you open fiddler and rerun the example. You see the following:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode>s:Client</faultcode>
      <faultstring xml:lang="en-US">Invalid guid.</faultstring>
      <detail>
        <FaultDetail xmlns="http://schemas.datacontract.org/2004/07/Contact.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
          <ErrorCode>63873928</ErrorCode>
          <Type>Validation</Type>
        </FaultDetail>
      </detail>
    </s:Fault>
  </s:Body>
</s:Envelope>

Well, that's correct. WCF is sending the correct data back. At this point, you go to the next step of debugging by proceeding to bang you head against a wall.

What's the problem?

Here it is: Silverlight a browser plugin. Therefore, Silverlight must obey the rules of plugins and are also limited to the information given to them by their host browser. In the case of fault exceptions, faults are send over an HTTP connect with a non-200 HTTP status code. This makes sense since 200 means “OK” and fault means “not-OK”. Browsers do not send this kind of information to plugins. Thus, not Microsoft’s fault (so, stop cursing them—redirect any and all of that to the IE team). Once we see this truth about the internal mechanics, we can see a glimpse of hope.

How so? Well, the problem clearly has nothing to do with faults. It has to do with the HTTP non-200 status code. Therefore, in order for Silverlight to see the fault exception we need to make sure the service with which the Silverlight client is communicating sends a 200 HTTP status code at all times, regardless of a success or not. This is incredibly easy in WCF using a concept known as an ErrorHandler.

ErrorHandlers are classes which implement the System.ServiceModel.Dispatcher.IErrorHandler interface. One of the required methods that this interface requires for you to implement has the following signature:

void ProvideFault(Exception error, MessageVersion version, ref Message fault)

By implementing this method and registering the ErrorHandler to WCF, you can effectively change the HTTP status code. Below is one implementation of this (notice that name is HttpStatusCode200ErrorHandler not SilverlightErrorHandler-- this can be used for anything that doesn't support non-HTTP 200 codes):

#region Copyright
//+ Themelia Pro 2.0 - Core Module
//+ Copyright © Jampad Technology, Inc. 2007-2009
#endregion
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
//+
namespace Themelia.ServiceModel.Behavior
{
    /// <summary>
    /// Sets the HTTP code to 200 for faults.
    /// </summary>
    public class HttpStatusCode200ErrorHandler : IErrorHandler
    {
        //- @ServiceType -//
        public Type ServiceType { get; set; }

        //+
        //- @Ctor -//
        public HttpStatusCode200ErrorHandler(Type serviceType)
        {
            ServiceType = serviceType;
        }

        //+
        //- @HandleError -//
        public bool HandleError(Exception error)
        {
            return false;
        }

        //- @ProvideFault -//
        public virtual void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            fault.Properties[HttpResponseMessageProperty.Name] = new HttpResponseMessageProperty
            {
                StatusCode = System.Net.HttpStatusCode.OK
            };
        }
    }
}

As you can see, on the created fault there is a Properties bag. By adding our own HttpResponseMessageProperty to this bag under the name of HttpResponseMessageProperty.Name, we can effectively change the HTTP status code.

To install an error handler, just create a service behavior.  A service behavior is much like an operation behavior, but, as you may have guessed, is for a service.  These are really just classes that implement the System.ServiceModel.Description.IServiceBehavior interface.  In our case, all we care about is using the ApplyDispatchBehavior method to install our error handler (this should all sound very familiar since we did something very analogous with an operation behavior and invoker earlier.)  Here’s a sample behavior to install the error handler:

#region Copyright
//+ Themelia Pro 2.0 - Core Module
//+ Copyright © Jampad Technology, Inc. 2007-2009
#endregion
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
//+
namespace Themelia.ServiceModel.Behavior
{
    /// <summary>
    /// Applies HttpStatusCode200ErrorHandler.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public class HttpStatusCode200Behavior : Attribute, IServiceBehavior
    {
        //- @AddBindingParameters -//
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            //+ blank
        }

        //- @ApplyDispatchBehavior -//
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(new HttpStatusCode200ErrorHandler(serviceDescription.ServiceType));
            }
        }

        //- @Validate -//
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            //+ blank
        }
    }
}

Now we just need to install the behavior. You can do this in a number of different ways, but I almost always use the service host factory approach.

The purpose behind one of these is to create a service host, which in turn hosts... (drum roll, please)... a service.  As with most WCF features, these are very powerful.  We use them to do all kinds of programmatic service alterations.  For example, we can add custom endpoints, setup metadata, apply more security, or, in our case, install a service behavior (which, in turn, installs our error handler).

A service host factory is simply a class which inherits from System.ServiceModel.Activation.ServiceHostFactory.  To create our service host factory , we are going override the following signature of a newly created service host factory:

ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

In this method, we are going to create our service host, add our behavior to that host, then return it. Here's the end result:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
//+
namespace Contact.Service.Activation
{
    public class PersonServiceHostFactory : WebServiceHostFactory
    {
        //- @CreateServiceHost -//
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = new ServiceHost(serviceType, baseAddresses);
            //+ HTTP 200
            host.Description.Behaviors.Add(new Themelia.ServiceModel.Behavior.HttpStatusCode200Behavior());
            //+
            return host;
        }
    }
}

Now, we just need our service host to use this factory. Your service host in the context of the web is the /SOMETHING.svc file. All we need to do is open this file and set the service directive "Factory" property to the name of our factory. For example:

<%@ ServiceHost Service="Contact.Service.PersonService" Factory="Contact.Service.Activation.PersonServiceHostFactory" %>

Now we are done.  When your access this service, the service host factory will create the host and add the error handler.  Then, when any error occurs,t he error handler will catch the error and set the HTTP status code to 200.  Thus, the browser will send the fault message to Silverlight and we’ll finally see that the correct FaultException<FaultDetail> catch block is hit.

Conclusion

In sum, WCF provides a very straight-forward, easy to implement fault management solution, which retains the idioms of C# and the purity of the SOAP standard. Not only that, but with a simple flip of a switch Silverlight works flawlessly with the feature that WCF has had since its first release.

Faults are really nothing more than SOAP messages of a certain format.  If there is an error, WCF is smart enough to not just serialize some exception, but, instead, send a fault SOAP message over the wire.  Thus, making the entire error handling process end-to-end very streamlined.

Whereas Silverlight 2 requires some extra massaging in order to get fault contracts implemented, Silverlight 3 has the feature built right in. Using the techniques described in this document, Silverlight 3 developers should be able to keep with the streamlined nature of WCF without the need for any custom fault management.

Samples for this document may be found here.

Understanding WCF

If you like this document, please consider writing a recommendation for me on my LinkedIn account.

Contents

Introduction

One of the most beautiful things about the Windows Communication Foundation (WCF) is that it's a completely streamlined technology.  When you can provide solutions to myriad of diverse problems using the same principles, you know you're dealing with a work of genius.  This is the case with WCF.  With a single service implementation, you can provide access to ASMX, PHP, Java, TCP, named pipe, and JSON-based services by add a single XML element for each type of connection you want to support.  On the flip side, with a single WCF client you can connect to each of these types of services, again, by adding a single like of XML for each.  It's that simple and streamlined.  Not only that, this client scenario works the same for both .NET and Silverlight.

In this document, I'm going to talk about how to access WCF services using Silverlight 2 without magic.  There will be no proxies, no generated code, no 3rd party utilities, and no disgusting "Add Service Reference" usage.  Just raw WCF.  This document will cover WCF connectivity in quite some depth.  We will talk about service setup, various WCF, SOA, and Silverlight paradigms, client setup,  some security issues, and a few supplemental features and techniques to help you aide and optimize service access.  You will learn about various WCF attributes, some interfaces, and a bunch of internals.  Though this document will be in depth, nothing will ever surpass the depth of MSDN.  So, for a more full discussion on any topic, see the WCF documentation on MSDN.

Even though we're focusing on Silverlight, most of what will be explained will be discussed in a .NET context and then applied to Silverlight 2.  That is, instead of learning .NET WCF and Silverlight WCF, you will .NET WCF and how to vary this for Silverlight.  This comparative learning method should help you both remember and understand the concepts better.  Before we begin, though, let's begin with a certain WCF service setup.  After all, we you don't have a service, we can't talk about accessing it.

Service Setup In Depth

When working with WCF, you are working with a completely streamlined system.  The most fundamental concept in this system is the ABC.  This concept scales from Hello World to the most complex sales processing system.  That is, for all WCF communication, you need an address, a binding, and a contract.  Actually, this is for any communication anywhere, even when talking to another person.  You have to know to whom, how, and what.  If you don't have these three, then there can't be any communication.

With these three pieces of information, you either create a service-side endpoint which a client will access or a client-side channel which the client will use to communicate with the service.

WCF services are setup using a 3 step method:

  • First, create a service contract with one or more operation contracts.
  • Second, create a service implementation for those contracts. 
  • Third, configure a service host to provide that implementation with an endpoint for that specific contract.

Let's begin by defining a service contract.  This is just a simple .NET interface with the System.ServiceModel.ServiceContractAttribute attribute applied to it.  This interface will contain various operation contracts, which are simply method signatures with the System.ServiceModel.OperationContractAttribute applied to each.  Both of these attributes are in the System.ServiceModel assembly.

Do not under any circumstances apply the ServiceContract attribute directly to the implementation (i.e. the class).  The ability to do this is probably the absolute worst feature in WCF.  It defeats the entire purpose of using WCF: your address, your binding, your contract and your implementation are complete separate.  Because this essentially makes your implementation your contract, all your configuration files will be incredibly confusing to those of us who know WCF well.  When I look for a contract, I look for something that starts with an "I".  Don't confuse me with "PersonService" as my contract.  Person service means person... service.  Not only that, but later on you will see how to use a contract to access a service.  It makes no sense to have my service access my service; thus with the implementation being the contract, your code will look painfully confusing to anyone who knows WCF.

Here's the sample contract that we will use for the duration of this document:

using System;
using System.ServiceModel;
//+
namespace Contact.Service
{
    [ServiceContract(Namespace = Information.Namespace.Contact)]
    public interface IPersonService
    {
        //- GetPersonData -//
        [OperationContract]
        Person GetPersonData(String personGuid);
    }
}

Keep in mind that when you design for WCF, you need to keep your interfaces as simple as possible.  The general rule of thumb is that you should have somewhere between 3 to 7 operations per service contract.  When you hit the 12-14 mark, it's seriously time to factor out your operations.  This is very important.  As I'll mention again later, in any one of my WCF projects I'll have upwards of dozens of service contracts per service.  You need to continuously keep in mind what your purpose is for creating this service, filtering those purposes through the SOA filter.  Don't design WCF services like you would a framework, which, even then shouldn't have many access points!

The Namespace property set on the attribute specified the namespace used to logically organize services.  Much like how .NET uses namespaces to separate various classes, structs, and interfaces, SOAP services use namespaces to separate various actions.  The name space may be arbitrarily chosen, but the client and service must just agree on this namespace. In this case, the namespace is the URI http://www.netfxharmonics.com/service/Contact/2008/11/.  This namespace will also be on the client.  This isn't a physical URL (universal resource locator), but a logical URI (universal resource identifier).  Despite what some may say, both terms are in active use in daily life.  Neither is more important than the other and neither is "deprecated".  All URLs are URIs, but not all URIs are URLs as you can see here.

Notice in this interface, there is a method interface that returns Person.  This is a data contract.  Data contracts are classes which have the System.Runtime.Serialization.DataContractAttribute attribute applied to them.  These have one or more data members, which are public or private properties or fields that have the System.Runtime.Serialization.DataMemberAttribute attribute applied to them.  Both of these attributes are in the System.Runtime.Serialization assembly.  This is important to remember; if you forget, you will probably assume them to be in the System.ServiceModel assembly and your contract will never compile.

Notice I said that data members are private or public properties or fields.  That was not a typo.  Unlike the serializer for the System.SerializableAttribute attribute, the serializer for DataContract attribute allows you to have private data members.  This allows you to hide information from developers, but allow services to see it.  Related to this is the how classes with the DataContract attribute differ from classes with the Serializable attribute.  When you use the Serializable attribute, you are using an opt-out model.  This means that when the attribute is applied to the class, each members is serializable.  You then opt-out particular fields (not properties; thus one major inflexibility) using the System.NonSerializedAttribute attribute.  On the other hand, when you apply the DataContract attribute, you are using an opt-in model.  Thus, when you apply this attribute, you must opt-in each field or property you wish to be serialized by applying the DataMember attribute.  Now to finally look at the Person data contract:

[DataContract(Namespace = Information.Namespace.Contact)]
public class Person
{
    //- @Guid -//
    [DataMember]
    public String Guid { get; set; }

    //- @FirstName -//
    [DataMember]
    public String FirstName { get; set; }

    //- @LastName -//
    [DataMember]
    public String LastName { get; set; }

    //- @City -//
    [DataMember]
    public String City { get; set; }

    //- @State -//
    [DataMember]
    public String State { get; set; }

    //- @PostalCode -//
    [DataMember]
    public String PostalCode { get; set; }
}

Note how simple this class is.  This is incredibly important.  You need to remember what this class represents: data moving over the wire.  Because of this, you need to make absolutely sure that you are sending only what you need.  Just because your internal "business object" has 10,000 properties doesn't mean that your service client will ever be able to handle it.  You can't get blood from a turnip.  Your business desires will never change the physics of the universe.  You need to design with this specific scenario of service-orientation in mind.  In the case of Silverlight, this is even more important since you are dealing with information that needs to get delegated through a web browser before the plug-in ever sees it.  Not only that, but every time you send an extra property over the wire, you are making your Silverlight application that less responsive.

When I coach architects on database design, I always remind them to design for the specific system which they'll be using (i.e. SQL Server) and always keep performance, space, and API usability in mind (this is why it's the job of the architect, not the DBA, to design databases!)  In the same way, if you are designing a system that you know will be used over the wire, account for that scenario ahead of time.  Much like security, performance and proper API design aren't "features", they're core parts of the system.  Do not design 10 different classes, each representing a property which will be used in another class which, in turn, will be serialized and sent over the wire.  This will be so absolutely massive that no one will ever be able to handle it.  If you have more than around 15 properties in your entire object graph, it's seriously time to rethink what you want to send.  And, never, ever, ever send an instance of System.Data.DataSet over the wire.  There has never been, is not now, and never will be any reason to ever send any instance of this type anywhere.  It's beyond massive and makes the 10,000 property data transfer object seem lightweight.  The fact that something is serializable doesn't mean that it should be.

This is main reason you should not apply the Serializable attribute to all classes.  Remember, this attribute follows an opt-out model (and a weak one at that).  If you want your "business objects" to work in your framework as well as over the wire, you need to remove this attribute and apply the DataContract attribute.  This will allow you to specify via the DataMember attribute which properties will be used over the wire, while leaving your existing framework completely untouched.  This is the reason the DataContract attribute exists!  Microsoft realized that the Serializable attribute is not fine grained enough for SOA purposes.  They also realized that there's no reason to force everyone in the world to write special data transfer objects for every operation.  Even then, use DataContract sparingly.  Just as you should keep as much private as possible and as much internal as possible, you want to keep as much un-serializable as possible.  Less is more.

In my Creating Streamlined, Simplified, yet Scalable WCF Connectivity document, I explain that these contracts are considered public.  That is, both the client and the service need the information.  It's the actual implementation that's private.  The client needs only the above information, where as the service needs the above information as well as the service implementation.  Therefore, as my document explains, everything mentioned above should be in a publicly accessible assembly separate from the service implementation to maximize flexibility.  This will also allow you to rely on the original contracts instead of relying on a situation where the contracts are converted to metadata over the wire and then converted to sloppily generated contracts.  That's slower, adds latency, adds another point of failure, and completely destroys your hand crafted, highly-optimized contracts.  Simply add a reference to the same assembly on both the client and server-side and you're done.  If multiple people are using the service, just hand out the public assembly.

At this point, many will try to do what I've just mentioned in a Silverlight environment to find that it doesn't seem to work.  That is, when you try to add a reference to a .NET assembly in a Silverlight project, you will get the following error message:

DotNetSilverlightReferenceMessageBox

Fortunately, this isn't the end of the world.  In my document entitled Reusing .NET Assemblies in Silverlight, I explain that this is only a Visual Studio 2008 constraint.  There's absolutely no technical reason why Silverlight can't use .NET assemblies.  Both the assembly and module formats are the same for Silverlight and .NET.  When you try to reference an assembly in a Silverlight project, Visual Studio 2008 does a check to see what version of mscorlib the assembly references.  If it's not 2.X.5.X, then it says it's not a Silverlight assembly.  So, all you need to do is modify your assembly to have it use the appropriate mscorlib file.  Of course, then it's still referencing the .NET System.ServiceModel and System.Runtime.Serialization assemblies.  Not a big deal, just copy/paste the Silverlight references in.  My aforementioned document explains everything you need to automate this procedure.

Therefore, there's no real problem here at all.  You can reuse all your contracts on both the service-side and on the client-side in both a .NET Silverlight environment.  As you will see a bit later, Silverlight follows an async communication model and, therefore, must use async-compatible service contracts.  At that time you may begin to think that you can't simply have a one-stop shop for all your contract needs.  However, this isn't the case.  As it turns out .NET can do asynchronous communication too, so when you create that new contract, you can keep it right next to your original service contract.  Thus, once again, you have a single point where you keep all your contracts.

Moving on to step 2, we need to use these contracts to create an implementation.  The service implementation is just a class which implements a service contract.  The service implementation for our document here is actually incredibly simple:

using System;
//+
namespace Contact.Service
{
    public class PersonService : Contact.Service.IPersonService
    {
        //- @GetPersonData -//
        public Person GetPersonData(String personGuid)
        {
            return new Person
            {
                FirstName = "John",
                LastName = "Doe",
                City = "Unknown",
                Guid = personGuid,
                PostalCode = "66062",
                State = "KS"
            };
        }
    }
}

That's it.  So, if you already have some logic you know is architecturally sound and you would like to turn it into a service.  Create an interface for your class and add some attributes to the interface.  That's your entire service implementation.

Step 3 is to configure a service host with the appropriate endpoints.  In our document, we are going to be using an HTTP based service.  Thus after we setup a new web site, we create a Person.svc file in the root and add to it a service directive specifying our service implementation.  Here's the entire Person.svc file:

<%@ ServiceHost Service="Contact.Service.PersonService" %>

No, I'm not joking.  If you keep your implementation in this class as well, then you are not using WCF properly.  In WCF, you keep your address, your binding, your contract, and your implementation completely separate.  By putting your implementation in this file, you are essentially tying the address to the implementation.  This defeats the entire purpose of WCF.  So, again, the above code is all that should ever be in any svc file anywhere.  Sometimes you may have another attribute set on your service directive, but this is basically it.

This is an unconfigured service host.  Thus, we must configure it.  We will do this in the service web site's web.config file.  There's really only one step to this, but that one step has a prerequisite.  The step is this: setup a service endpoint, but this requires a declared service.  Thus, we will declare a service and add it to an endpoint.  An endpoint specifies the WCF ABC: an address (where), a binding (how), and a contract (what).  Below is the entire web.config file up to this point:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Contact.Service.PersonService">
        <endpoint address="" binding="basicHttpBinding" contract="Contact.Service.IPersonService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

This states that there can be "basicHttpBinding" communication through Contact.Service.IPersonService at address Person.svc to Contact.Service.PersonService.  Let's quickly cover each concept here.

The specified address is a relative address.  This means that the value of this attribute is appended onto the base address.  In this case the base address is the address specified by our web server.  In the case of a service outside of a web server, then you can specify an absolute address here.  But, remember, when using a web server, the web server is going to control the IP address and port bindings.  Our service is at Person.svc, thus we have already provided for us the base URL.  In this case the address is blank, but you will use this address attribute if you add more endpoints as you will see later.

The binding specifies how the information is to be format for transfer.  There's actually nothing too magical about a binding, though.  It's really just a collection of binding elements and pre-configured parameter defaults, which are easily changed in configuration.  Each binding element will have at a minimum two binding elements.  One of these is a message encoding binding element, which will specify how the message is formatted.  For example, the message could be text (via the TextMessageEncodingBindingElement class; note: binding elements are in the System.ServiceModel.Channels namespace), binary (via the BinaryMessageEncodingBindingElement class), or some other encoding.  The other required binding element is the transport binding element, which specified how the message is to go over the wire.  For example, the message could go over HTTP (via the HttpTransportBindingElement), HTTPS (via the HttpsTransportBindingElement), TCP (via the TcpTransportBindingElement), or even a bunch of others.  A binding may also have other binding elements to add more features.  I'll mention this again later, when we actually use a binding.

The last part of an endpoint, the contract, has already been discussed earlier.  One thing that you really need to remember about this though is that you are communication through a contract to the hosted service.  If you are familiar with interface based development in .NET or COM, then you already have a strong understanding of what this means.  However, let's review.

If a class implements an interface, you can access the instantiated object through the interface.  For example, in the following code, you are able to access the Dude object through the ISpeak interface:

interface ISpeak
{
    void Speak(String text);
}

class Dude : ISpeak
{
    public void Speak(String text)
    {
        //+ speak text
    }
}

public class Program
{
    public void Run()
    {
        ISpeak dude = new Dude();
        dude.Speak("Hello");
    }
}

You can think of accessing a WCF service as being exactly like that.  You can even push the comparison even further.  Say the Dude class implemented IEat as well.  Then we can access the instantiated Dude object through the IEat interface.  Here's what I mean:

interface ISpeak
{
    void Speak(String text);
}

interface IEat
{
    void Eat(String nameOfFood);
}

class Dude : ISpeak, IEat
{
    public void Speak(String text)
    {
        //+ speak text
    }
}

public class Program
{
    public void Run()
    {
        IEat dude = new Dude();
        dude.Eat("Pizza");
    }
}

In the same way, when configuring a WCF service, you will add an endpoint for contract through which you would like your service to be accessed.

Though it's beyond the scope of this document, WCF also allows you to version contracts.  Perhaps you added or removed a parameter from your contract.  Unless you want to break all the clients accessing the service, you must keep the old contract applied to your service (read: keep the old interface on the service class) and keep the old endpoint running by setting up a parallel endpoint.

You will add a new service endpoint every time you change your version, change your contract, or change your binding.  On a given service, you have have dozens of endpoints.  This is good thing.  Perhaps you provide for four different bindings with two of them having two separate configurations each, three different contracts, and 2 different versions of one of the contracts.  In this document, we are going to start out with one endpoint and add more later.

Now we have setup a complete service.  However, it's an incredibly simple service setup, thus not requiring too much architectural attention.  When you work with WCF in a real project, you will want to organize your WCF infrastructure to be a bit more architecturally friendly.  In my document entitled Creating Streamlined, Simplified, yet Scalable WCF Connectivity, I explain streamlining and simplifying WCF connectivity and how you can use a private/public project model to simplify your WCF connectivity.  See that document for more information on streamlining WCF services.

Service Access Without Magic

Now we may turn our attention to the client application.  To begin, let me start off by reminding everyone that you shouldn't ever use "Add Service Reference" in Visual Studio for magical service client creation.  The code is incredibly verbose, hard to manageable, edits are prone to being overwritten, and it's almost always used as an excuse to not actually learn WCF.  There are few things worse than having to deal with people who thing they know a product simply because they know how to use a mouse.  There are reasons why Juval Lowy, in all his books and talks, repeatedly tells people to avoid using this flawed feature.  Fortunately, as professionals, we have the ability to understand how to do things without magic.

As I've mentioned many times already, WCF relies on the concept of the ABC.  We've seen how we configure a WCF host by creating an endpoint specifying an address, binding and contract.  As it turns out, this is all that's required on the client side as well.  For both .NET and Silverlight, you merge an address and a binding with a contract in a channel factory to create a channel.  This isn't just fancy conceptual architect speak, this is exactly what your code would look like (the sign of really good architecture!)  Below is the .NET version of what I mean:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");

In this you have an address (the EndpointAddress object), a binding (BasicHttpBinding), and a contract (IPersonService) meeting in System.ServiceModel.ChannelFactory<TServiceContract> to create a channel which implements the IPersonService interface (and others).  We can then call through our local interface to the channel, which then calls the remote service through the service interface.  No magic is required.  You don't need any "proxy" or anything.  WCF is literally all about the ABC on the service and on the client.

A few moments ago I mentioned that a binding is nothing more than a series of binding elements.  At this time I would like to prove this to you.  In the above sample, we are using a BasicHttpBinding on the client to communicate to a BasicHttpBinding on the service.  This is slightly "magical".  Let's peel back the covers to see what's really going on.  The BasicHttpBinding is the WCF implementation of the WS-I Basic Profile standard used by ASMX services and most PHP clients.  In other words, it's the basic SOAP binding.  Internally though, it's really nothing more than a combination of the TextMessageEncodingBindingElement and, depending on your settings, either HttpTransportBindingElement or HttpsTransportBindingElement with the message version set to SOAP 1.1.

To prove this, let's completely remove the BasicHttpBinding from our client.  Then let's create an instance of the System.ServiceModel.Channels.CustomBinding class.  This class allows us to make our own bindings from our own or preexisting binding elements.  In this case, all we want to do is add the TextMessageEncodingBindingElement, setting the message version to SOAP 1.1 and add the HttpTransportBindingElement.  With this, we have creating a binding that fits exactly what our service expects.  Here's what we're talking about:

CustomBinding customBinding = new CustomBinding();
customBinding.Elements.Add(new TextMessageEncodingBindingElement
{
    MessageVersion = MessageVersion.Soap11
});
customBinding.Elements.Add(new HttpTransportBindingElement());
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
//+
IPersonService personService = new ChannelFactory<IPersonService>(customBinding, endpointAddress).CreateChannel();

If you think that's wild, you will be in shock when you realize that you don't even need to use code to create a custom binding.  Let's completely remove the CustomBinding and address from our code and just do the exact same thing in web.config.  Here is our new code:

IPersonService personService = new ChannelFactory<IPersonService>("PersonServiceCustomHttpBinding").CreateChannel();

Doesn't get much simpler than that.  Now take a look at our web.config:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="HttpTextCustomBinding">
        <textMessageEncoding messageVersion="Soap11" />
        <httpTransport/>
      </binding>
    </customBinding>
  </bindings>
  <client>
    <endpoint name="PersonServiceCustomHttpBinding" 
              bindingConfiguration="HttpTextCustomBinding" 
              address="http://localhost:1003/Person.svc" 
              binding="customBinding" 
              contract="Contact.Service.IPersonService" />
  </client>
</system.serviceModel>

Believe it or not, our service still works perfectly.

Up to this point we have been discussing WCF in general, it's now time to move towards Silverlight.  The ABC and channel concepts still apply, but, since we are in the world of the web, there's one difference in how we access the services from our clients: we are dealing with asynchronous calls.

The Async Pattern

If you are familiar with the concepts of AJAX calls, then you should already be familiar with what I'm talking about.  To put it simply, instead of calling a "do" method, you basically set a callback and call "beginDo".  Then, instead of obtaining a response from "beginDo", we wait for a callback from the service.  Think of it like phone tag between two people who never answer their phone.  Person A calls person B and says "call me back at X".  Then Person B calls Person A back at X; you don't sit there on someone's voicemail waiting for them to pick up (...like we did in the days of answering machines.)

When this idea is brought to the .NET/Silverlight world, we have something called the Async Pattern, which states that asynchronous methods are to follow the following pattern:

public IAsyncResult BeginOperation(/* <parameters> */, AsyncCallback callback, Object state)
public /* <return> */ EndOperation(IAsyncResult result)

If you're never seen this before, then, it's high time you become deeply familiar with it.  This pattern is used all over the place in myriad of different contexts.  You can use MSDN to find various examples involving this pattern, or just keep reading to see how it's used to get the general idea.  If you are going to take Silverlight seriously, then you absolutely must master this pattern.

Not only that, but you must also be very proficient with asynchronous call chains.  This is when you call one async operation, wait for the callback, then that callback begins another async operation, whose callback may call another async operation.  You just chain the async calls down the line to have a steady, deterministic program flow.  This, of course, requires knowledge of the Async Pattern to which we now return our focus.

When working with in Silverlight, this Async Pattern is the type of call pattern that you will be using for just about all service access with or without WCF.  For example, there will be no GetPersonData method which returns a Person object.  Instead, there will be a BeginGetPersonData method which returns an IAsyncResult object (which you may or may not use).  Then, you wait for a callback, which has an IAsyncResult again which you use to obtain a result from EndGetPersonData.  This actually means that our service contract in Silverlight will look slightly different than our service contract for .NET.  Here's our Silverlight version:

using System;
using System.ServiceModel;
//+
namespace Contact.Service
{
    [ServiceContract(Namespace = Information.Namespace.Contact)]
    public interface IPersonService
    {
        //- BeginGetPersonData -//
        [OperationContract(AsyncPattern = true)]
        IAsyncResult BeginGetPersonData(String personGuid, AsyncCallback callback, Object state);

        //- LoadPerson -//
        Person EndGetPersonData(IAsyncResult result);
    }
}

Notice that we are now following the Async Pattern and that the OperationContract attribute has declaratively stated that we are following the pattern via the AsyncPattern property.  We may now rewrite our original .NET service-call code to follow the new paradigms and service contract to allow Silverlight interaction.  Here's our new code:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
//+
AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    Person person = ((IPersonService)result.AsyncState).EndGetPersonData(result);
    this.Dispatcher.BeginInvoke(delegate
    {
        spMain.Children.Add(new TextBlock
        {
            Text = person.FirstName
        });
    });
};
personService.BeginGetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6", asyncCallBack, personService);

Notice the first three lines are identical.  After this, not much remains the same.  Instead of doing a simple service-call with a synchronous response, we must set a callback and begin a request.  In this particular example, the asyncCallBack object is being given an anonymous method to the BeginGetPersonData method.  This anonymous method block will be called when the service calls returns a response back.

Take note of the third parameter in the BeginGetPersonData.  Per the Async Pattern, this is "state".  This is similar to the Tag object found in VB and in WPF.  You can use this to place just about anything you want to send back to the callback.  In this case, since we're it's an anonymous method, it's optional, but if the callback were a named method, then the callback may obtain that state by pulling the AsyncState property from the IAsyncResult object passed to the callback.  In this example, I'm sending the channel itself as the state so that I can access the channel from the callback.  This is important because this is how I'm able to call the EndGetPersonData method and retrieve the service operation response data, a Person object in this case.

Notice also also that the callback has a call to Dispatcher.BeginInvoke.  You must do this if you are on a visual element and want to access visual elements in your callback.  This will grant you access to the UI thread.  Without this, an exception will be thrown.  In this case we are adding a TextBlock to a StackPanel.  For the duration of this document, the following method will be used to write our output to the StackPanel:

//- $Write -//
private void Write(String text)
{
    this.Dispatcher.BeginInvoke(delegate
    {
        spMain.Children.Add(new TextBlock
        {
            Text = text
        });
    });
}

External Web Site Access

Having said all that, if you were to try and run the code I sent to you based on our current service configuration, nothing would actually work.  Why's that?  Because in our original service-setup the service is hosted in a different web site than the web site itself.  The service web site does nothing but WCF hosting, while our application web site hosts our Silverlight application.  This basically allows you to keep all your entities highly cohesive and reusable.  However, in this case, we are running up against a security wall.  By default, you cannot use Silverlight to access a web site which differs by domain, IP address, or port number. 

Fortunately, there's an easy way around this: you just need to add a ClientAccessPolicy.xml file in the service root.  Here's a sample ClientAccessPolicy.xml file:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from>
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

This particular example basically allows everyone everywhere to access the service, granting access to everything.  This may be what you want or, perhaps, you want to lock it down a bit by placing a URI of the format http://www.tempuri.org/ in place of the *.  Perhaps you even want to add multiple domain elements or, on the other end of the spectrum, restrict access to only a particular service path.

Now while this file looks all well and good, our Silverlight service call still won't work. Why in the world not?  Because for WCF in Silverlight to call a service outside of the local web site, you must also specify what headers to allow.  In our case, we want to allow the SOAPAction header.  The SOAPAction header is what a SOAP service uses to specify what action to run on the service.

Here's our new policy:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers="SOAPAction">
        <domain uri="*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

Now our WCF Silverlight service will work flawlessly.

For all the information you would ever need on this file, see Network Security Access Restrictions in Silverlight 2 on MSDN.

Configuration Based Access

Our service client call at this point is fully programmatic.  This is nice, but perhaps you would like to utilize WCF configuration instead of creating Binding and Endpoint elements manually.  This is a great idea, but how in the world do we access configuration in Silverlight when Silverlight is on the client-side, running in a web browser?  As it turns out, Silverlight actually does include a configuration file, which gets embedded in to the final XAP file, the ServiceReferences.ClientConfig file.

To utilize this configuration feature, we first need to create the file and add it to our Silverlight project.  Then, we must set its build action to Content.  In Visual Studio 2008, you do this in the properties window for that file.  This will force the file to be zipped in with the rest of the contents of the XAP file, which, if you didn't know, is really nothing more than a ZIP file readable by any ZIP client, much like Word 2007's DOCX format.

At this point, you may just copy/paste the configuration from a .NET WCF client to this Silverlight configuration file.  Here's basically what it will look like at this point:

<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:1003/Person.svc" binding="basicHttpBinding" contract="Contact.Service.IPersonService" name="BasicHttpBinding_IPersonService" />
    </client>
  </system.serviceModel>
</configuration>

At this point can change our code to use the configuration instead of the created binding and endpoint address objects:

IPersonService personService = new ChannelFactory<IPersonService>("BasicHttpBinding_IPersonService").CreateChannel();
//+
AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    Person person = ((IPersonService)result.AsyncState).EndGetPersonData(result);
    Write(person.FirstName);
};
personService.BeginGetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6", asyncCallBack, personService);

Now, once again, while this looks nice, when you compile and run the Silverlight application you will notice that it doesn't even pretend to work.  Why? For some reason, you actually need to declare a basicHttpBinding element in the configuration file.  Here's the new configuration file:

<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding />
    </bindings>
    <client>
      <endpoint address="http://localhost:1003/Person.svc" binding="basicHttpBinding" contract="Contact.Service.IPersonService" name="BasicHttpBinding_IPersonService" />
    </client>
  </system.serviceModel>
</configuration>

At this point, the Silverlight client will have full connectivity with the service.

Strongly Typed Client

At this point we could stop.  The thing works.  Mission Accomplished.  However, when designing software, you want to make sure people call fall into success.  In this case, a developer might forget how to create a WCF channel.  Even then, system internals have nothing to do with the core competency of what's going on.  Business developers need to be working on providing a business solution, not writing WCF interaction code.  Thus, it's often a good idea to hide the internals of something before anyone else uses it.  Even I, as a non-business developer, who love internals and gets great benefits from their understanding, prefer not to see internals in my every day development.  Therefore, I normally hide the internal mechanics of the WCF channel by creating a client abstraction.

As with WCF in .NET, you may use the System.ServiceModel.ClientBase<T> class to create an abstraction of the internal WCF channel mechanics.  However, due to the Async Pattern, using ClientBase in Silverlight is drastically different how I described it's usage for .NET in "Creating Streamlined, Simplified, yet Scalable WCF Connectivity".  Creating a concrete ClientBase class is still fairly straightforward though.

The first thing we need to do is create a class that inherits from ClientBase<IYourServiceContract> where IYourServiceContract is, well, your service contract.  However, unless you want a very complicated class, do not implement the IYourServiceContract on this ClientBase like you would normally do in .NET.  Instead, for each operation in your service contract, create a method in this class.  Don't worry about following the Async Pattern.  Our point in creating this abstraction is to hide the internals mechanics, not to simply rearrange them.  Having said that, you still need to have a callback parameter if your method returns a response.

In addition to this, make sure your method names make sense.  By convention, you should suffix each operation method in your ClientBase with "Async".  Then, inside the method, call your method prefixed with "Begin" on the channel created by the ClientBase class.  Totally confused?  Here's what I mean:

//- @GetPersonDataAsync -//
public void GetPersonDataAsync(String personGuid, EventHandler<ClientEventArgs> callback)
{
    Channel.BeginGetPersonData(personGuid, GetPersonDataCallback, callback);
}

In reality, all you're doing is taking a call and passing it to the Channel with different parameters.  Essentially you are hiding the Async Pattern used by this channel method with something that's more natural to developers.  In this channel call, the second parameter, GetPersonDataCallback, is the WCF callback which is called when the actual service call is complete and the third parameter is the state for the Async Pattern.  Here's the GetPersonDataCallback method:

//- $GetPersonDataCallback -//
private void GetPersonDataCallback(IAsyncResult result)
{
    EventHandler<ClientEventArgs> callBack = result.AsyncState as EventHandler<ClientEventArgs>;
    if (callBack != null)
    {
        callBack(this, new ClientEventArgs
        {
            Object = EndGetPersonData(result)
        });
    }
}

Since we set the callback as the state in the service call, it follows that we can pull that out and use it to send the response data back to the calling method using the standard .NET event pattern.  In this case, the ClientEventArgs class is a simple EventArgs class which holds the response object:

public class ClientEventArgs : EventArgs
{
    //- @Object -//
    public Object Object { get; set; }
}

Now notice that when we are populating this newly created ClientEventArgs, we are setting it's Object property to the result of the EndGetPersonData, which is the second of the two Async Pattern components.  It's implementation is extremely simple:

//- $EndGetPersonData -//
private Person EndGetPersonData(IAsyncResult result)
{
    return Channel.EndGetPersonData(result);
}

Notice also that our ClientBase callback and End methods are private, thus completely concealing the internal WCF mechanics from developers.

There's at least one more method we need to add to our class for it to be complete: the constructors.  Personally, I like to add a constructor which accepts a System.ServiceModel.Channels.Binding object and a System.ServiceModel.EndpointAddress object as well as an overload which accepts a string representing the endpoint configuration name.  These constructors basically do nothing but bridge to the base class:

//- @Ctor -//
public PersonClient(String endpointConfigurationName)
    : base(endpointConfigurationName) { }
public PersonClient(System.ServiceModel.Channels.Binding binding, EndpointAddress address)
    : base(binding, address) { }

Thus, we have successfully created a ClientBase class to abstract the internal mechanics for developers.  To sum up, here's the complete class:

using System;
using System.ServiceModel;
//+
namespace SilverlightClient
{
    public class PersonClient : ClientBase<Contact.Service.IPersonService>
    {
        //- @Ctor -//
        public PersonClient(String endpointConfigurationName)
            : base(endpointConfigurationName) { }
        public PersonClient(System.ServiceModel.Channels.Binding binding, EndpointAddress address)
            : base(binding, address) { }

        //+
        //- @GetPersonDataAsync -//
        public void GetPersonDataAsync(String personGuid, EventHandler<ClientEventArgs> callback)
        {
            Channel.BeginGetPersonData(personGuid, GetPersonDataCallback, callback);
        }

        //- $GetPersonDataCallback -//
        private void GetPersonDataCallback(IAsyncResult result)
        {
            EventHandler<ClientEventArgs> callBack = result.AsyncState as EventHandler<ClientEventArgs>;
            if (callBack != null)
            {
                callBack(this, new ClientEventArgs
                {
                    Object = EndGetPersonData(result)
                });
            }
        }

        //- $EndGetPersonData -//
        private Contact.Service.Person EndGetPersonData(IAsyncResult result)
        {
            return Channel.EndGetPersonData(result);
        }
    }
}

If you need to add more operations, and you most definitely will, all you need to do is copy/paste this pattern and do a which rename of a new things here and there.  You could create a Visual Studio code snippet to setup this pattern as well.  Using this class is now as simple as the following:

PersonClient personClient = new PersonClient("BasicHttpBinding_IPersonService");
personClient.GetPersonDataAsync("F488D20B-FC27-4631-9FB9-83AF616AB5A6", OnServiceCallback);

Then, of course, there's the callback method:

//- $OnServiceCallback -//
private void OnServiceCallback(Object sender, ClientEventArgs ea)
{
    Person person = ea.Object as Person;
    if (person == null)
    {
        return;
    }
    //+
    Write(person.FirstName);
}

As simple as this is, though, you could actually keep the simplicity of this usage and still upgrade the class to be a bit more general.  For this reason, I created my ObjectClient<TServiceContract> class.  Here's an example of using it:

ObjectClient<IPersonService> objectClient = new ObjectClient<IPersonService>("BasicHttpBinding_IPersonService");
objectClient.Begin("GetPersonData", OnObjectServiceCallback, null, "F488D20B-FC27-4631-9FB9-83AF616AB5A6");

Then, here's the service callback:

//- $OnObjectServiceCallback -//
private void OnObjectServiceCallback(Object sender, ObjectClient<IPersonService>.ClientEventArgs ea)
{
    Person person = ea.LoadResult<Person>();
    Write(person.LastName);
}

The mechanics of this class follow the same idea as the previous ClientBase, but this one does not use ClientBase, but, rather, creates the channel itself.  Then, when the "Begin" method is called, the class internally passes the parameters to the proper "BeginMethodName" method property via dynamic invocation.  Internally, the service callback also uses dynamic invocation to call "EndMethodName" to obtain the result.  The result is then passed to the original callback using the same ClientEventArgs as seen in the PersonClient example.

Below is the ObjectClient code in its entirety:

#region Copyright
//+ Copyright © Jampad Technology, Inc. 2008
//++ Lead Architect: David Betz [MVP] <dfb/davidbetz/net>
#endregion
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
//+
namespace Nalarium.ServiceModel
{
    public class ObjectClient<TServiceContract> where TServiceContract : class
    {
        //- @ClientEventArgs -//
        public class ClientEventArgs : EventArgs
        {
            //- @Object -//
            public Object Object { get; set; }

            //- @UserState -//
            public Object UserState { get; set; }

            //+
            //- @LoadResult -//
            public TResult LoadResult<TResult>()
            {
                if (this.Object is TResult)
                {
                    return (TResult)this.Object;
                }
                //+
                return default(TResult);
            }
        }

        //- $ObjectClientState -//
        private class ObjectClientState
        {
            //- @Callback -//
            public EventHandler<ClientEventArgs> Callback { get; set; }

            //- @MethodName -//
            public String MethodName { get; set; }

            //- @UserState -//
            public Object UserState { get; set; }
        }

        //+
        //- $Channel -//
        private TServiceContract Channel { get; set; }

        //- $ContractType -//
        private Type ContractType { get; set; }

        //+
        //- @Ctor
        private ObjectClient()
        {
            ContractType = typeof(TServiceContract);
        }
        public ObjectClient(Binding binding, EndpointAddress address)
            : this()
        {
            Channel = new ChannelFactory<TServiceContract>(binding, address).CreateChannel();
        }
        public ObjectClient(String endpointConfigurationName)
            : this()
        {
            Channel = new ChannelFactory<TServiceContract>(endpointConfigurationName).CreateChannel();
        }

        //+
        //- @Begin -//
        public void Begin(String methodName, Object state, params Object[] parameterArray)
        {
            Begin(methodName, null, state, parameterArray);
        }
        public void Begin(String methodName, EventHandler<ClientEventArgs> callback, Object state, params Object[] parameterArray)
        {
            if (parameterArray != null)
            {
                Array.Resize<Object>(ref parameterArray, parameterArray.Length + 2);
            }
            else
            {
                parameterArray = new Object[2];
            }
            parameterArray[parameterArray.Length - 1] = new ObjectClientState
            {
                Callback = callback,
                MethodName = methodName,
                UserState = state
            };
            parameterArray[parameterArray.Length - 2] = new AsyncCallback(OnCallback);
            ContractType.InvokeMember("Begin" + methodName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, Channel, parameterArray);
        }

        //- $OnCallback -//
        private void OnCallback(IAsyncResult result)
        {
            ObjectClientState state = result.AsyncState as ObjectClientState;
            if (state == null)
            {
                return;
            }
            Object obj = ContractType.InvokeMember("End" + state.MethodName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, Channel, new Object[] { result });
            if (state.Callback != null)
            {
                state.Callback(this, new ClientEventArgs
                {
                    Object = obj,
                    UserState = state.UserState
                });
            }
        }
    }
}

Feel free to upgrade it, modify it, or use it however you would like.

Security - Communication over SSL

At this point I would like to turn out attention to a critical part of WCF development: security. Many times, if not most of the time, you will be dealing with some sort of sensitive information in your application. This goes for Silverlight as much as it does for .NET. Fortunately, secure WCF interaction is essentially the same for both.  Before we begin though, we need to update our service in order for it to handle secure connectivity.  To do this, we are going to create a separate service from our Person service, called SecurePersonService.  In most situations, you would just have a single service to handle both, but for the sake of this document we're going to keep them separate.

Before we add security to our service though, we need to have an SSL certificate installed on the server.  This is the same type of certificate you would have if you wanted to provide a checkout experience on an e-commerce web site.  If you already have an SSL certificate, great, if not, then you will need to go through the motions to install one.  To install one for IIS6 or IIS7, just follow the instructions at http://blog.functionalfun.net/2008/05/how-to-create-server-certificate-for.html.  This post explains how you can easily get a free 90-day signed SSL certificate from a certificate provider.

Once you have the certificate installed, you need to then configure the service for SSL.  We haven't yet created the service, but that's OK.  We know what it's going to be called.  To configure our BasicHttpBinding service for SSL you essentially need to set the security mode to Transport in a binding configuration and specify the certificate in a service behavior.  Here's the new configuration:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="SecureBasicHttpBinding">
          <security mode="Transport" />
        </binding>
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="SecurePersonServiceBehavior">
          <serviceCredentials>
            <serviceCertificate 
              findValue="localhost" 
              storeLocation="LocalMachine" 
              storeName="My" 
              x509FindType="FindBySubjectName" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="Contact.Service.PersonService">
        <endpoint address="" binding="basicHttpBinding" contract="Contact.Service.IPersonService" />
      </service>
      <service name="Contact.Service.SecurePersonService" behaviorConfiguration="SecurePersonServiceBehavior">
        <endpoint bindingConfiguration="SecureBasicHttpBinding" 
                  address="" binding="basicHttpBinding" contract="Contact.Service.IPersonService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

There are two conceptual notes that should probably be mentioned at this point:

First, a binding configuration changes the defaults of a particular binding.  As I mentioned earlier, a binding is really just a collection of binding elements with some pre-set parameters.  In this case, we are applying a particular binding configuration to an endpoint to change the security from "None" to "Transport" (which is SSL in this case).

Second, behaviors essentially allow you to declaratively, either via configuration or programmatically via attributes, modify how a particular part of your service operates.  You can have all kinds of different behaviors at different levels.  For example, you can use an operation behavior to modify something about an operation.  We will see this later when we use an operation behavior to apply operation-level security.  In our configuration here, we are applying a service behavior to modify the service to use a particular certificate.

Next, for the time being, let's copy/paste our PersonService implementation as a new class called SecurePersonService.  Again, this is only for the sake of this demo.  In reality, there's no reason to use the word "Secure" for this service.  Then, let's create a SecurePerson.svc file in our service web site root and insert the following service declaration:

<%@ ServiceHost Service="Contact.Service.SecurePersonService" %>

At this point we have an SSL BasicHttpBinding service setup.  We can now alter alter our Silverlight client to use SSL.  This is really just a matter of setting the BasicHttpBinding security more to Transport and changing the URL from the HTTP based URL to the HTTPS one.  Here's how we have modified our previous Silverlight WCF client to allow SSL access:

BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
//+ step 1 of 2: set security mode
basicHttpBinding.Security.Mode = BasicHttpSecurityMode.Transport;
//+ step 2 of 2: set to https _and_ set proper relative endpoint
EndpointAddress endpointAddress = new EndpointAddress("https://localhost/SecurePerson.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();

Those two steps are the only steps involved.  Silverlight is not set to use the new SSL service.

Having said that, if you try to run the Silverlight client, it won't work.  Why?  Well, as Tim Heuer, Senior Program Manager for Silverlight points out, you can't rely on the existing ClientAccessPolicy.xml configuration we used previously.  Previously we allowed the "*" domain, which allows all non-secure clients in.  This does not include HTTPS clients.  Thus, we need to specify them explicitly.  Here is our new ClientAccessPolicy.xml file:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
    <policy>
      <allow-from http-request-headers= "SOAPAction">
        <domain uri="http://*"/>
        <domain uri="https://*"/>
      </allow-from>
      <grant-to>
        <resource path="/" include-subpaths="true"/>
      </grant-to>
    </policy>
  </cross-domain-access>
</access-policy>

Now our Silverlight client will communicate successfully with the service over SSL.  But, SSL only secures the data going over the wire, it doesn't say anything about who can access the data.  For this we need to add some form of authentication.

Security - UserName Authentication

If we were working in .NET, we could just use the WsHttpBinding to use the WS-Security standard to send our username and password to our service.  Silverlight 2.0, however, doesn't include this binding.  This doesn't mean we can't make username/password authentication happen.  We could actually use a WebRequest technique that we will cover later to communicate with a WsHttpBinding service, but let's keep with BasicHttpBinding for the time being.  In this case, all we need to do is add the username and password to the message to be sent over our secure SSL connection and have it checked at the other end.  This is really as easy as it sounds.

Regardless of whether you are on the service-side or the client-side, you will have something called an operation context.  This houses the information for the current operation.  You can think of it as a the WCF operation version of HttpContext in ASP.NET.  In fact, much like HttpContext, the OperationContext object is a single.  You access it via System.ServiceModel.OperationContext.Current. As you progress in your WCF projects, you will find yourself going to the operation context time and time again for various reason.  It's an incredibly important feature of WCF that provides much value to service development on both the service and client side.

Of the many properties in this context, there is one called OutgoingMessageHeaders of type System.ServiceModel.Channels.MessageHeaders.  As the name suggestions this houses the message headers that are being sent out.  Likewise there's also an IncomingMessageHeaders object of the same type, which contains the header information that has been received.  These are just opposite sides of the coin.  Both outgoing and incoming headers are like request headers in the web world.  Outgoing headers are the "request headers" being sent and incoming headers are the "request headers" received on the other end.  This works the same for both the service-side and client-side.

To enable authorization, we just need to add both the username and password to the OutgoingMessageHeader object on the client and read them from the IncomingMessageHeader object on the service.  In Silverlight, this looks like this:

MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
messageHeadersElement.Add(MessageHeader.CreateHeader("UserName", "", "JohnDoe"));
messageHeadersElement.Add(MessageHeader.CreateHeader("Password", "", "MyPassword"));

Notice there is no mention of the service we are going to access.  When the service-call happens, the information will automatically be applied in the background and sent over the wire.

Now while this sounds great, we see a reoccurring theme: it doesn't work.  Why?  If you try to do this, you will find that OperationContext.Current is null.  The singleton has not yet been created.  Well, that kind of throws a wrench in things.  Fortunately, though, this is easily remedied.  All we need to do is declare an operation context scope.  This basically means instantiating a System.ServiceModel.OperationContextScope object, passing it an existing operation context or something which implements the System.ServiceModel.IContextChannel interface.  We obviously don't have the former, but what about the latter?

As it turns out, the channel created by our channel factory doesn't only implement our service contract (IPersonService), but it also implements IContextChannel.  Thus, we are able to pass this to the operation context scope, which will then create the operation context, allowing us to add the headers and make our call.  Here's our new service call:

using (OperationContextScope scope = new OperationContextScope((IContextChannel)personService))
{
    MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
    messageHeadersElement.Add(MessageHeader.CreateHeader("UserName", "", "JohnDoe"));
    messageHeadersElement.Add(MessageHeader.CreateHeader("Password", "", "MyPassword"));
    //+
    Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}

Note that the operation context scope implements the System.IDisposable interface, thus allowing you to wrap it in a using block in C#.

At this point we can turn our attention to the service.  This is actually about as simple as what we did on the client-side, if not simpler.  All we need to do is see if the IncomingMessageHeaders object on our operation context contains our UserName and Password headers.  If they do, then extract them and validate them.  If all if well, then run the service logic.

To check to see if a particular message header is in the IncomingMessageHeaders object, use the FindHeader method.  This will return the index of the header or -1 if the header was not found.  Since both of our headers must exist, the sum of the indexes must be at least 0.  -1 would mean that one of the two headers is missing whereas -2 would mean that both are missing.  Therefore, if the sum is at least 0, we can grab the header information, which we do using the GetHeader<T> method.  This is a generic method, so specify the type that you would like your header value to be as T.  In our case they will both be System.String.  Once we have pulled the username and password, we can validate them and run our service logic.  Here's our entire service up to this point:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
//+
namespace Contact.Service
{
    public class SecurePersonService : Contact.Service.IPersonService
    {
        //- @GetPersonData -//
        public Person GetPersonData(String personGuid)
        {
            MessageHeaders messageHeadersElement = OperationContext.Current.IncomingMessageHeaders;
            Int32 id = messageHeadersElement.FindHeader("UserName", "") + messageHeadersElement.FindHeader("Password", "");
            if (id > -1)
            {
                String username = messageHeadersElement.GetHeader<String>("UserName", "");
                String password = messageHeadersElement.GetHeader<String>("Password", "");
                if (username == "JohnDoe" && password == "MyPassword")
                {
                    return new PersonService().GetPersonData(personGuid);
                }
            }
            //+
            return null;
        }
    }
}

Now at this point we could reuse this same technique to secure each operation in our service.  However, the technical term for doing this is insanity.  This is absolutely crazy.  There absolutely has to be a better way of doing this than dealing with the internal mechanics of message headers for each and every single operation in your service.  We need something that will validate the username and password information before our logic ever runs so that we never, ever have to see it.  Fortunately, there is.  This is exactly the value an operation behavior provides.  They are also incredibly straightforward to implement.

Before we do that though, we need to create operation invoker.  We do this by creating a class which implements the System.ServiceModel.Dispatcher.IOperationInvoker interface.  There are many member signatures in this interface, but we only care about the Invoke method.  Every time you call an operation, you "invoke" the operation much like how you "invoke" a method via reflection.  Earlier we saw how we passed an anonymous method to an Invoke method in WPF so we could access the UI thread.  This is the same idea.  When you run something, you "invoke" it.  For an operation invoker, when an operation is called, the Invoke method is called to run the actual operation logic.  Our mission is to house validation logic in our invoker and, if validation succeeds, have the invoker call the original service operation invoker.

We install an operation invoker using an operation behavior.  An operation behavior is a class which implements the System.ServiceModel.Description.IOperationBehavior interface.  This interface has four method signatures, but we really only care about one of them.  Not only that, but the only thing this method will do is set our Invoker.  Before this can matter though, we have to have a way to apply our bit to our operation.  The operation behavior may set the operation invoker, but who sets the operation behavior?  As it turns out, operation behaviors may be applied declaratively through attributes.  This is rather interesting as it allows us to have our operation behavior class inherit from System.Attribute, thus making our operation behavior completely self-sufficient.

It's that time again to move from the lecture hall to the lab.  We will first turn our attention to the operation behavior.  Below is the entire operation behavior:

using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
//+
namespace Contact.Service.Behavior
{
    [AttributeUsage(AttributeTargets.Method)]
    public class SecurityOperationBehavior : Attribute, IOperationBehavior
    {
        //- @AddBindingParameters -//
        public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
            //+ blank
        }

        //- @ApplyClientBehavior -//
        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
            //+ blank
        }

        //- @ApplyDispatchBehavior -//
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.Invoker = new SecurityOperationInvoker(dispatchOperation.Invoker);
        }

        //- @Validate -//
        public void Validate(OperationDescription operationDescription)
        {
            //+ blank
        }
    }
}

As you can see, it's just a simple attribute whose attribute usage states that it may only be applied to methods.  Notice also that the only method we care is the ApplyDispatchBehavior method and, as mentioned before, the only thing were doing is setting the new invoker, passing the original invoker to its constructor.  Let's now turn to our operation invoker:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
//+
namespace Contact.Service.Behavior
{
    public class SecurityOperationInvoker : IOperationInvoker
    {
        //- $InnerOperationInvoker -//
        private IOperationInvoker InnerOperationInvoker { get; set; }

        //+
        //- @Ctor -//
        public SecurityOperationInvoker(IOperationInvoker operationInvoker)
        {
            this.InnerOperationInvoker = operationInvoker;
        }

        //+
        //- @AllocateInputs -//
        public Object[] AllocateInputs()
        {
            return InnerOperationInvoker.AllocateInputs();
        }

        //- @Invoke -//
        public Object Invoke(Object instance, Object[] inputs, out Object[] outputs)
        {
            //+ authorization
            MessageHeaders messageHeadersElement = OperationContext.Current.IncomingMessageHeaders;
            Int32 id = messageHeadersElement.FindHeader("UserName", "") + messageHeadersElement.FindHeader("Password", "");
            if (id > -1)
            {
                String username = messageHeadersElement.GetHeader<String>("UserName", "");
                String password = messageHeadersElement.GetHeader<String>("Password", "");
                SecurityValidator.Authenticate(username, password);
                //+
                return InnerOperationInvoker.Invoke(instance, inputs, out outputs);
            }
            //+
            throw new FaultException<InvalidOperationException>(new InvalidOperationException(SecurityValidator.Message.InvalidCredentials), SecurityValidator.Message.InvalidCredentials);
        }

        //- @InvokeBegin -//
        public IAsyncResult InvokeBegin(Object instance, Object[] inputs, AsyncCallback callback, Object state)
        {
            return InnerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
        }

        //- @InvokeEnd -//
        public Object InvokeEnd(Object instance, out Object[] outputs, IAsyncResult result)
        {
            return InnerOperationInvoker.InvokeEnd(instance, out outputs, result);
        }

        //- @IsSynchronous -//
        public Boolean IsSynchronous
        {
            get { return InnerOperationInvoker.IsSynchronous; }
        }
    }
}

At first glance it may seem like there's a lot going on here, but if you look closely you will see that there are only three things of note here.  First, there is the InternalOperationInvoker property.  This just hold the original operation invoker so we can call it later.  Second, every other member except Invoke does nothing but call the invoker in InternalOperationInvoker.  Third, the Invoke method is not really doing anything but what we've already seen in the service operation.  The only difference is that upon validation, instead of doing the actual logic, the Invoke method just calls the Invoke method of our InternalOperationInvoker property.  So, it's not really all that busy after all.

With our operation behavior created, we can now return to modify our service operation.  All we need to do is remove all the validation logic and apply our new SecurityOperationBehavior attribute.  Our service operation now looks like this:

//- @GetPersonData -//
[SecurityOperationBehavior]
public Person GetPersonData(String personGuid)
{
    return new PersonService().GetPersonData(personGuid);
}

That's a lot better than before, isn't it?  With this new toy at your disposal, whenever you want to secure a new operation in your service, just apply the attribute and move on. 

Before moving on, note that if you would like to see another example of using operation behaviors, see my Minima Blog Engine 3.1 source code.  Minima is my training software to demonstrate many areas of .NET and it relies heavily on WCF.

Handling Exceptions

We now have an authentication model for our WCF connectivity in our Silverlight application.  There is one more thing we could do to improve this.  Returning null from a service when validation failed is a good way to cause no end to confusion.  The worst error is seeing no error.  Therefore, we need to throw an exception if validation fails.  Continuing in how we have been discussing things, let's move our attention back to the .NET world to discuss some concepts and theory.  Then let's angle our knowledge a bit to make way for the Silverlight world.

To begin, you need to understand that the concept of an exception is a .NET concept.  The messages over the wire have absolutely nothing to do with .NET and, therefore, have no idea what an exception is.  Instead, messages over the wire and service-oriented architecture in general have a concept called a fault, which essentially serves the same purpose as an exception.  Therefore, if you were to throw an exception in a service, the SOA world won't have the first clue what you're talking about.  Not only that, but when your client hears about the exception, it won't see an exception, but, rather a signal that there was some sort of a catastrophic error, thus closing your client channel (our IPersonService instance).  In other words, the following in the service will break your client:

String message = "Invalid credentials";
throw new System.InvalidOperationException(message);

You can, however, get around this by telling your WCF service to include exception information in fault.  You can set this in configuration or in your service host factory.  I'm not going to demonstrate this because I don't want to encourage this cop-out technique.  This is only to be used for debugging.  Do you really want the fully-detailed exception message and stack trace to go out into all the world to see?  This would be even worst than turning ASP.NET custom errors off.  This is the image of a security flaw.

WCF provides the proper mechanism for dealing with exceptions with the System.ServiceModel.FaultException<T> class.  This allows us to to throw exceptions as fault.  There's also a System.ServiceModel.FaultException, from which FaultException<T> inherits.  You can either throw the non-generic one to send a simple message or you can use the generic one to send a message and the exception type.  The generic one will probably be the one you use most often.

To use FaultException<T>, first instantiate the exception you would like to throw then pass that object as well as the exception message to the FaultException<T> instance.  Then you may throw the FaultException<T> instance.  That is, instead of throwing the InvalidOperationException as seen in the last example, do the following:

String message = "Invalid credentials";
throw new FaultException<System.InvalidOperationException>(new System.InvalidOperationException(message), message);

This will allow your client code to catch the exception gracefully and won't send your private stack trace for the world to see.  Here's the code to handle this:

try
{
    person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException ex)
{
    Response.Write(ex.Message);
}

At this point our service-side fault exception code is the same as the following:

throw new FaultException("Invalid credentials");

As I've already mentioned, using the FaultException class will send back a message.  This is exactly what FaultException<T> at this point too.  To make FaultException<T> work the way it was designed, you need to declare a fault contract on your service-side service contract.  You do this by applying the System.ServiceModel.FaultContract attribute to your operation contract.  Here's our new service contract:

using System;
using System.ServiceModel;
//+
namespace Contact.Service
{
    [ServiceContract(Namespace = Information.Namespace.Contact)]
    public interface IPersonService
    {
        //- GetPersonData -//
        [OperationContract]
        [FaultContract(typeof(InvalidOperationException))]
        Person GetPersonData(String personGuid);
    }
}

Now we are able to catch the various different fault exceptions a service may return:

try
{
    person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (FaultException<InvalidOperationException> ex)
{
    Response.Write(ex.Message);
}

At this point some may suggest that, since we are only interested in security validation, we should turn our attention toSystem.Security.SecurityException as follows:

throw new System.Security.SecurityException("Invalid credentials");

This special exception will actually be a fault over the wire, give you graceful error handling, and it also doesn't publish your stack trace.  One thing you need to remember about this exception, though, is that you don't catch the same exception that has been thrown.  You actually catch System.ServiceModel.Security.SecurityAccessDeniedException.  Not only that but the message that was sent from the service, isn't the message that will show in your client.  The client side exception will always say "Access is denied.".  Here's an example:

try
{
    person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
}
catch (System.ServiceModel.Security.SecurityAccessDeniedException ex)
{
    Response.Write(ex.Message);
}

You probably shouldn't rely on this mechanism though.  WCF will replace the SecurityException with a Fault over the wire, but not in all places.  For example, the above code will work beautifully if you are throw the exception from an operation, but if you throw it in an operation behavior, your client will see, not SecurityAccessDeniedException, but rather a FaultException (not the generic one either).  You should use FaultException<SecurityException> either as this can cause the real exception to be System.Net.Sockets.SocketException, which is absolutely catastrophic.  For a security validation error, I use FaultException<InvalidOperationException> as we've already seen.

Now, I must apologize at this point for getting you excited about all the awesomeness of faults handling in WCF, because... none of that works in Silverlight.  Yeah.  I know.  It's like "why didn't you say that earlier!!??"  Well, it's important to understand the underlying mechanics of the ideal, before you can work around them into the real-- otherwise, you're just making stuff up as you go.  Not only that, you need to make sure you understand WCF in general before you understand WCF in Silverlight.  Chances are that your WCF services will do more than simply serve Silverlight.

The reason none of this works in the Silverlight world is because has absolutely no concept of a fault.  It actually can't.  With this specific service, when your service call fails validation, your Silverlight application will only see a 404 error with the text "The remote server returned an error: NotFound".  When a fault is thrown, regardless of how pretty you make it, the HTTP status code is not 200, where 200 means that everything went OK.  This is a problem for Silverlight.

Silverlight, as we know, runs in the context of a web browser.  Because of this, Silverlight is only provided the information that a web browser allows it.  When a response is returned to Silverlight with a status code other than 200, the web browser intercepts it and never tells Silverlight about it.  It's kind of like when you're at the office and you go to search for a critical piece of information only to find that your company's content filter blocks that particular technology web site thinking it was inappropriate.

There are various ways around this and every single technique that I know of requires you to modify your service.  The method we are going to use modifies the service a tiny bit, but it does so in a reusable way.  We are essentially going to create a custom FaultDetail class which we will implement in our Person data contract.  If an exception is thrown on the service, a fault detail will be created and added to our Person object.  Then, when we receive a response on the client side, we can check to see if FaultDetail is null.  If not, then there was a fault. 

However, I don't want to do this for all my service-clients.  Service clients that can handle service faults are going to see the real fault.  There's no reason to confuse whoever is accessing our service by having a separate FaultDetail.  Having an error in two places can lead to disasters and mass confusion.  Mindless consistency is often the fastest way to catastrophic disaster.  You can't say you drive 40 miles per hour at all times because you strive for consistency.  This can kill pedestrians in school zones and kill you on the interstate.  We must be flexible to the context of each situation.  We must seek congruency, not consistency.  Therefore, we will only set the FaultDetail object when a specific message header is present.  For our service, we will call this message header "DoesNotHandleFault".  Note this isn't "IsSilverlight".  This makes our FaultDetail technique reusable for other technologies that do not handle faults.

Enough lecture, back to the lab.  First, let's create our FaultDetail object.  This can simply be a class with some properties.  In this example, I have a Message property as well two constructors, one to accept a message and open to accept an exception:

using System;
using System.ServiceModel;
//+
namespace General.Service
{
    public class FaultDetail
    {
        //- @Message -//
        public String Message { get; set; }

        //+
        //- @CreateFaultDetail -//
        public static FaultDetail CreateFaultDetail(Exception exception)
        {
            return CreateFaultDetail(exception.Message);
        }
        public static FaultDetail CreateFaultDetail(String message)
        {
            return new FaultDetail
            {
                 Message = message
            };
        }
    }
}

At this point, you could take this idea further and iterate through the InnerExceptions of the exception and add nested FaultDetail messages.  That's a mission for you, if you choose you accept it.

Next, let's create an interface that will signal to us that a particular service-side data contract can handle a FaultDetail:

namespace General.Service
{
    public interface IContainsFaultDetail
    {
        FaultDetail FaultDetail { get; set; }
    }
}

Let's now implement the interface:

using System;
using System.Runtime.Serialization;
//+
using General.Service;
//+
namespace Contact.Service
{
    [DataContract(Namespace = Information.Namespace.Contact)]
    public class Person : IContainsFaultDetail
    {
        //++
        //+ more properties here
        //++
        //- @FaultDetail -//
        [DataMember]
        public FaultDetail FaultDetail { get; set; }
    }
}

You may be curious to know how this service-side data contract change will affect the rest of the clients which consume this service.  It's actually really simple: it doesn't.  The client will not break simply because it doesn't know how to deserialize something.  Actually, in .NET, if the client-side data contract didn't have data members the service was sending back to it, but implemented System.Runtime.Serialization.IExtensibleDataObject, the data would go into the data contract's ExtensionData property, or as I like to call it "the data member bucket". So, you aren't breaking anything by adding data members to your service-side data contracts.  As a side note, this works the other way too.  If your client sends more information than the service knows about, the service won't break either and, if its data contract implemented IExtensibleDataObject on a service-side data contract, the data will likewise go into the ExtensionData property.  Like I said though, this is in .NET.  Silverlight does not support this interface.  Of course, Silverlight can still send extra stuff to the service, which will be in .NET.

The last task on the service-side is to add the FaultDetail functionality to our service.  We could either add the functional to each and every single operation or we could simply extend the operation behavior that we had already created.  I'm voting for the later.  Essentially what we are going to do is wrap all the logic in our operation invoker Invoke logic in a try-catch block.  Then, if an exception is thrown, we can check to see if the "DoesNotHandleFault" message header is set.  If it is, set the FaultDetail on the return object.  If it isn't, then simply rethrow the exception.

This all seems pretty simple, right?  Well, there are some problems with this.  First, you want to make this reusable.  Therefore, you cannot assume anything about the operation return type other than the fact that everything inherits from System.Object.  You could easily get around this by checking to see if our IContainsFaultDetail interface is on the object.  If it is, then you can set the FaultDetail through this interface.  You don't even need to know the actual type.  However, what if the object is null?  Just instantiate it first, right?  Again, you don't know the type.  Fortunately, however, the wonderful world of reflection is at our disposal.

To get around this problem, we need to first see if there is even a problem at all.  This means checking to see if our return object is null.  If not, then you're all set to check for the interface and set the FaultDetail through that interface.  If it is null, then we need to use reflection to obtain the type of the return object.  This is actually hidden in our InnerOperationInvoker which we saved when we instantiated our operation invoker.  To be more specific, inside our InnerOperationInvoker is a property named Method.  This method is of type System.Reflection.MethodInfo, which, in turn, has a property named ReturnType of type System.Type which is exactly what we need.  Then, we use the System.Activator::CreateInstance method to create an instantiated object using the value of ReturnType.  At this point we are able to check for our IContainsFaultDetail interface and setting the FaultDetail.

Once more, let's switch from lecture to lab.  Below is our new Invoke method for our operation invoker based on the concepts I've just explained:

//- @Invoke -//
public Object Invoke(Object instance, Object[] inputs, out Object[] outputs)
{
    outputs = new Object[] { };
    MessageHeaders messageHeadersElement = OperationContext.Current.IncomingMessageHeaders;
    Object returnObject = null;
    try
    {
        //+ authorization
        Int32 id = messageHeadersElement.FindHeader("UserName", "") + messageHeadersElement.FindHeader("Password", "");
        if (id > -1)
        {
            String username = messageHeadersElement.GetHeader<String>("UserName", "");
            String password = messageHeadersElement.GetHeader<String>("Password", "");
            SecurityValidator.Authenticate(username, password);
            //+
            return InnerOperationInvoker.Invoke(instance, inputs, out outputs);
        }
        //+
        throw new FaultException<InvalidOperationException>(new InvalidOperationException(SecurityValidator.Message.InvalidCredentials), SecurityValidator.Message.InvalidCredentials);
    }
    catch (Exception ex)
    {
        if (messageHeadersElement.FindHeader("DoesNotHandleFault", "") > -1)
        {
            if (returnObject == null)
            {
                Type invokerType = InnerOperationInvoker.GetType();
                PropertyInfo pi = invokerType.GetProperty("Method");
                MethodInfo mi = (MethodInfo)pi.GetValue(InnerOperationInvoker, null);
                Type returnType = mi.ReturnType;
                Type interfaceType = returnType.GetInterface("General.Service.IContainsFaultDetail");
                if (interfaceType != null)
                {
                    returnObject = Activator.CreateInstance(returnType);
                }
            }
            if (returnObject != null && returnObject is IContainsFaultDetail)
            {
                ((IContainsFaultDetail)returnObject).FaultDetail = FaultDetail.CreateFaultDetail(ex.Message);
            }
        }
        else
        {
            throw;
        }
    }
    //+
    return returnObject;
}

The explanation that I have already provided should help you understand each part of what's going on here.  There is, however, one part of this that may cause you problems if you don't implement this technique correctly.  Notice the Invoke method accepts an out parameter named outputs.  And out parameter is an incredibly powerful C# feature that requires the method on which it is placed to give the parameter a value, which the method caller may then.  If your method does not give the parameter a value, your code will not compile.  In many cases, setting an out parameter to null will be sufficient.  In this case, this will cause a serialization error when the service reply is created.  Therefore, in this example, I'm setting the outputs parameter to an empty object array.  This will satisfy both the compiler as well as WCF.

At this point, we can move to the client-side.  The first thing we need to do is copy our FaultDetail, IContainsFaultDetail, and new Person data contract to our Silverlight project.  Note that you do NOT need to do this for any other clients for the reasons I've already already mentioned.  The only clients that need these changes are the clients which are going to use the FaultDetail directly.

Next, let's add our "DoesNotHandleFault" message header in our Silverlight client.  You can do this in the same place you set your other message headers:

using (OperationContextScope scope = new OperationContextScope((IContextChannel)personService))
{
    MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
    messageHeadersElement.Add(MessageHeader.CreateHeader("UserName", "", "JohnDoe"));
    messageHeadersElement.Add(MessageHeader.CreateHeader("Password", "", "MyPassword12341234"));
    //+ allows returning of a FaultDetail object
    messageHeadersElement.Add(MessageHeader.CreateHeader("DoesNotHandleFault", "", true));
    //+
    personService.BeginGetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6", asyncCallBack, personService);
}

Then, in our callback, check for the FaultDetail object:

AsyncCallback asyncCallBack = delegate(IAsyncResult result)
{
    Person person = ((IPersonService)result.AsyncState).EndGetPersonData(result);
    String text = String.Empty;
    if (person.FaultDetail != null)
    {
        text = person.FaultDetail.Message;
    }
    else
    {
        text = person.FirstName;
    }
    //+ the rest of your callback here
};

Now you have the ability to catch faults in Silverlight 2.  There's, however, one quite serious problem with this method though.  What happens when your operation doesn't return a data transfer object (DTO) like our Person class?  There's no setting a FaultDetail on an array, a list, an Int32, or a string.

Though it's generally a redundant and architecturally questionable idea, in these cases you really need to create a wrapper response class.  As a service-oriented architect, I only care about the service contracts.  If the service contracts have nothing more than a bunch of request response messages, then I'm seriously slowed down.  They tell me absolutely nothing.  How can I know anything about an operation's response by looking at GetPersonDataResponse?  In these situations, it takes me much longer to get at the heart of what's going on because I need to understand with X number of methods and (2 * X) number of custom objects (and look them up on a chart every time I forget what's what!)

Thus, though services are to accept a very specific set of parameters and return a very specific element.  For our scenario, however, you need to do this.  To create a DTO, just create a class which contains a property for your operation return object and as well as a FaultDetail property.  As I've mentioned, this is incredibly redundant as what I've just described is exactly what SOAP envelope does with a fault.  But, since Silverlight will never see those messages, we are rather forced to emulate them.

JSON Service Connectivity

If you've been paying attention to the examples thus far, we have only been using the BasicHttpBinding binding.  This is because Silverlight doesn't handle bindings like WsHttpBinding, NetTcpBinding, or NetNamedPipeBinding.  However, since we're on the web, we might create a Silverlight application to replace an AJAX component which used JSON to communicate to a WebHttpBinding WCF service endpoint.  Or, perhaps, you just prefer to use a WebHttpBinding on your WCF service.  Therefore, we need the ability to access JSON services efficiently.  To do this, we turn to the System.Net namespace, namely the WebRequest class.

Essentially what we want to do is create an instance of the System.Net.WebRequest class and setup an async call chain.  If you recall, an async chain is when the callback of one call makes another call and its callback may potentially make another call.  Before you can do any of this, though, you need to know the full URI you are going to access.  This URI is the base endpoint address of the service combined with the relative endpoint address combined with the name of the service operation you are going to access.

We know from our service setup that the base address of our service is http://localhost:1003/Person.svc.  The relative address is configured on the service side.  Here's a configuration snippet from the service:

<service name="Contact.Service.PersonService">
  <endpoint address="json" binding="webHttpBinding" contract="Contact.Service.IPersonService" behaviorConfiguration="JsonEndpointBehavior" />
</service>

The endpoint address, "json", is the second piece of information required, the relative endpoint address.  The third piece of information in our case is "GetPersonData".  Thus the full URI we need to pass to our WebRequest object is http://localhost:1003/Person.svc/json/GetPersonData.

Once we create a WebRequest object, we need to make sure the content type is set to "application/json" and make sure the HTTP method is set to POST.  Without both of these set, we will get nothing but errors all over the place.  With these set, we are then able to enter into an async chain of the steps that occur in a WebRequest.

The process begins by calling the BeginGetRequestStream method on our WebRequest object, passing it a callback.  When that callback is called, we are then, per the Async Pattern, we able to call the EndGetRequestStream, which, if you recall, requires the IAsyncResult which was passed to our callback.  At this point we are able to write information to the service and call BeginGetResponse, passing it another callback.  Then, when that callback is called, we can call the EndGetResponse, passing it the new IAsyncResult object to obtain a System.Net.WebResponse object.  Finally, we call GetResponseStream on this WebResponse object, which gives us the response data sent back to us from the service.  Here is a complete example of using the WebRequest object in this way:

using System;
using System.Collections.Generic;
using System.Json;
using System.Net;
//+
namespace SilverlightClient
{
    public class WcfJsonClient
    {
        //- @JsonValueEventArgs -//
        public class JsonValueEventArgs : EventArgs
        {
            //- @JsonValue -//
            public JsonValue JsonValue { get; set; }

            //- @JsonType -//
            public JsonType JsonType { get; set; }

            //- @ValueAsText -//
            public String ValueAsText
            {
                get
                {
                    System.Text.StringBuilder builder = new System.Text.StringBuilder();
                    System.IO.StringWriter writer = new System.IO.StringWriter(builder, System.Globalization.CultureInfo.CurrentCulture);
                    JsonValue.Save(writer);
                    //+
                    return builder.ToString();
                }
            }
        }

        //- @Complete -//
        public event EventHandler<JsonValueEventArgs> Callback;

        //+
        //- $PostJsonData -//
        private String PostJsonData { get; set; }

        //+
        //- @PostHttpRequest -//
        public void PostHttpRequest(String endpoint, String methodName)
        {
            PostHttpRequest(endpoint, methodName, String.Empty, null);
        }
        public void PostHttpRequest(String endpoint, String methodName, String jsonData)
        {
            PostHttpRequest(endpoint, methodName, jsonData, null);
        }
        public void PostHttpRequest(String endpoint, String methodName, String jsonData, Dictionary<String, String> headerDictionary)
        {
            WebRequest request = WebRequest.Create(new Uri(endpoint + "/" + methodName));
            this.PostJsonData = jsonData;
            request.Method = "POST";
            request.ContentType = "application/json";
            if (headerDictionary != null)
            {
                foreach (String key in headerDictionary.Keys)
                {
                    request.Headers[key] = headerDictionary[key];
                }
            }
            request.BeginGetRequestStream(new AsyncCallback(OnPostBegin), request);
        }

        //- $OnPostBegin -//
        private void OnPostBegin(IAsyncResult result)
        {
            WebRequest request = result.AsyncState as WebRequest;
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(request.EndGetRequestStream(result)))
            {
                if (!String.IsNullOrEmpty(this.PostJsonData))
                {
                    writer.Write(this.PostJsonData);
                }
                writer.Close();
                //+ response
                request.BeginGetResponse(new AsyncCallback(OnPostComplete), request);
            }
        }

        //- $OnPostComplete -//
        private void OnPostComplete(IAsyncResult result)
        {
            WebRequest request = result.AsyncState as WebRequest;
            using (WebResponse response = request.EndGetResponse(result))
            {
                OnComplete(new System.IO.StreamReader(response.GetResponseStream()).ReadToEnd());
            }
        }

        //- #OnComplete -//
        protected void OnComplete(String data)
        {
            if (Callback != null)
            {
                JsonValue jsonValue = (JsonValue)JsonObject.Load(new System.IO.StringReader(data))["d"];
                Callback(this, new JsonValueEventArgs
                {
                    JsonValue = jsonValue,
                    JsonType = jsonValue is JsonArray ? JsonType.Array : JsonType.Object
                });
            }
        }
    }
}

Here you can see the WebRequest setup as well as the async chain.  Notice also how this example accepts a System.Collections.Generic.Dictionary<T1, T2> object.  Using this we are able to set custom HTTP headers on to our client.  Using HTTP headers is an awesome way of communicating with a service.  We have already seen that SOAP services use the SOAPAction header to specify what operation to run at the other end.  You could do something similar in your JSON services as well.

Normally at this point I would like show you an example of using this client, but we aren't done explaining it.  One part of this client example that we haven't discussed is how to deal with the response JSON data.  At this point our JSON data is just raw text.  Ideally, we would take this raw text, run it through deserialization and be done with things.  However, one hitch here is that an unmodified WCF JSON service likes to send back JSON with full namespaces for each member.  Here's an example of what I mean:

{
    "d": {
        "__type": "Person:http:\/\/www.netfxharmonics.com\/service\/Contact\/2008\/11\/",
        "City": "Unknown",
        "FirstName": "John",
        "Guid": "F488D20B-FC27-4631-9FB9-83AF616AB5A6",
        "LastName": "Doe",
        "PostalCode": "66062",
        "State": "KS"
    }
}

This kind of gets in the way of simple deserialization.  Fortunately, that's not a problem as Silverlight 2 provides a different way to access JSON data through it's System.Json.JsonObject housed in the System.Json assembly.  Be careful, though, every time you add an assembly to your Silverlight application, you increase the size of the Silverlight XAP file.  When you add the 52k System.JSON assembly, you add 21k to the size of the XAP file.  In this case, this takes the size of the XAP file from 12k to 33k.  That's a huge increase.  So, think ahead on how and if you really want to access JSON WCF services using this technique.

If you notice from the client, when we the last client callback is called, the static System.Json.JsonObject.Load method is called to load a stream or TextReader into a System.Web.JsonValue object.  This gives us a representation we can use to access any information we want by accessing the indexer of the object.  Before we can access our data, though, we need to open the data envelope.  This is that "d" section in the WCF JSON response message.  This is as simple as accessing the "d" indexer on the JsonValue object as this example shows:

JsonValue jsonValue = (JsonValue)JsonObject.Load(new StringReader(data))["d"];

This JsonValue object created here contains the WCF response information.  The JsonValue class itself is the base class for System.Json.JsonArray and System.Json.JsonObject. Unless you know what your service is returning, you need to test which type the JsonObject.Load class created.  This is as simple as the following:

JsonType jsonType = value is JsonArray ? JsonType.Array : JsonType.Object;

If you're working with a JsonObject, you may then access any member of the JSON data you want.  You do this by reading values from a JsonValue into a stream or text writer.  For example, here's the code to access the FirstName value:

StringBuilder builder = new StringBuilder();
StringWriter writer = new StringWriter(builder);
jsonValue["FirstName"].Save(writer);
//+
String firstName = builder.ToString().Replace("\"", "");

Since you would be using this regularly, it's a good idea for us to place this in a method (or even in a "Reader" class):

//- $ReadJsonValue -//
private string ReadJsonValue(JsonValue jsonValue, String field)
{
    StringBuilder builder = new StringBuilder();
    jsonValue[field].Save(new StringWriter(builder));
    //+
    return builder.ToString().Replace("\"", "");
}

At this point, you have enough information to see how this WcfJsonClient class can be used.  Here's how we can use it:

WcfJsonClient client = new WcfJsonClient();
client.Complete += OnJsonServiceCallback;
client.PostHttpRequest("http://localhost:1003/Person.svc/json", "GetPersonData", @"{ ""personGuid"": ""F488D20B-FC27-4631-9FB9-83AF616AB5A6"" }");

This is, of course, not complete without the callback method:

//- $OnJsonServiceCallback -//
private void OnJsonServiceCallback(Object sender, WcfJsonClient.JsonValueEventArgs ea)
{
    Write(ReadJsonValue(ea.JsonValue, "State"));
}

As I've mentioned, we can work with arrays as well.  In .NET though, we really only talk about arrays for value types.  If we have a series of reference types, a collection feels much better.  Therefore, let's assume that we the following operation to our service:

//- GetPersonList -//
[OperationContract]
List<Person> GetPersonList( );

What's interesting about this is that System.Collections.Generic.List<T> likes to become an array when going over the wire.  When dealing with SOAP services, a List is an array over the wire.  The same goes for JSON as well.  This is where that JsonArray type comes in to play.  This object is incredibly easy to work with.  Essentially it's a series of JsonValue objects.  Not only that, but JsonArray has an indexer and it implements the IEnumerable<JsonValue> interface, thus allowing us to access it's elements via a foreach loop.  In our case, each of these elements will be of the type JsonObject, which we already know how to deal with.  Here's a complete example of interacting with the above service operation:

WcfJsonClient wcfJsonClient = new WcfJsonClient();
wcfJsonClient.Callback += delegate(Object sender, WcfJsonClient.JsonValueEventArgs ea)
{
    List<Person> personList = new List<Person>();
    JsonArray array = (JsonArray)ea.JsonValue;
    foreach (JsonValue jsonValue in array)
    {
        Person person = new Person
        {
            City = ReadJsonValue(jsonValue, "City"),
            FirstName = ReadJsonValue(jsonValue, "FirstName"),
            LastName = ReadJsonValue(jsonValue, "LastName"),
            PostalCode = ReadJsonValue(jsonValue, "PostalCode"),
            State = ReadJsonValue(jsonValue, "State"),
            Guid = ReadJsonValue(jsonValue, "Guid"),
        };
        personList.Add(person);
        //+
        Write(person.FirstName);
    }
    //+
    Write("Person count: " + personList.Count.ToString());
};
wcfJsonClient.PostHttpRequest("http://localhost:1003/Person.svc/json", "GetPersonList");

One aspect of this WcfJsonClient class that you may not have realized is that you could easily make it dual purpose with very few changes.  If you added a second callback for XML parsing and change the content type, your "WcfJsonClient" becomes "WcfXmlJsonClient".  This WebRequest technique itself can be used for just about anything.  You could load CVS data or even access SOAP services manually if you wanted, giving you the ability to interact with WsHttpBinding services.  If you know how to communicate with an HTTP service at the wire-level, then the WebRequest can probably make the connection happen.

The only other type of response you would ever really need to parse is a primitive, which is represented by the System.Json.JsonPrimitive, which also inherits from JsonValue.  You don't need to do anything special with these at all.  Just pull the value from them just as you would a value from JsonObject.  In our case, this means running it through the ReadJsonValue method.

Thread Waiting

As we have just seen with our JSON client, many times when working in the Async Pattern, you will have an async chain.  This is an effective way to manage the order or events in an application.  However, depending on what you're doing, this model may not be the entirely optimal.  Fortunately, we have another option: a thread wait.

Thread waiting has been in .NET since the beginning and is very effective in Silverlight to help us control the workflow of our applications.  To use a thread wait, you create an System.Threading.AutoResetEvent object and call it's WaitOne method.  This causes execution in the current thread to pause.  Execution will resume when the object's Set method is called.

So, you can call WaitOne immediately after a service call and have the service call's callback call Set to continue execution.  This allows you to keep a linear flow of your application instead of doing async chaining.  An important note about this, though, is that you don't want to call WaitOne on the UI thread.  This will basically lock up your web browser.  Instead, wrap your service calls and WaitOne call in a new thread.  This will cause that thread to pause, not the UI thread.  Here's the basic usage:

private AutoResetEvent wait = new AutoResetEvent(false);

//+
//- @OnButtonClick -//
public void OnButtonClick(Object sender, System.Windows.RoutedEventArgs ea)
{
    new Thread(new ThreadStart(delegate
    {
        //+ basicHttpBinding call
        ObjectClient<IPersonService> objectClient = new ObjectClient<IPersonService>("BasicHttpBinding_IPersonService");
        objectClient.Callback += OnServiceCallback;
        objectClient.Begin("GetPersonData", "F488D20B-FC27-4631-9FB9-83AF616AB5A6");
        wait.WaitOne();
        //+ webHttpBinding call
        WcfJsonClient wcfJsonClient = new WcfJsonClient();
        wcfJsonClient.Complete += OnJsonServiceCallback;
        wcfJsonClient.PostHttpRequest("http://localhost:1003/Person.svc/json", "GetPersonData", @"{ ""personGuid"": ""F488D20B-FC27-4631-9FB9-83AF616AB5A6"" }");
    })).Start();
}

In this example, a new thread will start and make an ObjectClient service call.  The thread will then be immediately pause.  It will remain paused until the following callback runs the wait.Set method, which will resume execution allowing the WcfJsonClient to then run.

//- $OnServiceCallback -//
private void OnServiceCallback(Object sender, ObjectClient<IPersonService>.ClientEventArgs ea)
{
    this.Dispatcher.BeginInvoke(delegate
    {
        //+ do stuff here
        wait.Set();
    });
}

Using DevServer

If you get seriously deep into HTTP-based service-development in either a Silverlight, AJAX, or general .NET context, there will definitely come a time your work when you need to know what messages are going over the wire, or if messages are going over the wire.  In a strictly Silverlight context, you might even want to make sure your Silverlight client is even looking for a ClientAccessPolicy.xml file.  Fortunately, there is a way to view all this information in a streamlined manner.

My NetFXHarmonics DevServer is a development web server which provides multi-instance web server hosting and the ability to look at the traffic in and out of each web server.  In addition, using DevServer profiles, you can load up entire sets of web servers to quickly setup and teardown different development environments.

To use it, just register your servers in the DevServer configuration file, setup a profile, and either set the startup profile or use a command line argument to specify what profile to load.  This will load up all your development web servers at once.  Here's a sample configuration:

<jampad.devServer>
  <startupProfiles activeProfile="Client">
    <profile name="Client">
      <server key="ClientWS" />
      <server key="ClientSVC" />
    </profile>
  </startupProfiles>
  <servers>
    <server key="ClientWS" name="ClientWS" port="1001"
                virtualPath="/" physicalPath="C:\Project\WCFService\WebSite">
    </server>
    <server key="ClientSVC" name="ClientSVC" port="1003"
                virtualPath="/" physicalPath="C:\Project\WCFService\Service">
    </server>
  </servers>
</jampad.devServer>

You can also change the binding of each server to allow remote or Virtual PC access for testing purposes.  For full documentation on DevServer see http://www.netfxharmonics.com/2008/04/NetFXHarmonics-DevServer-Released.

For now, though, just know that if you enable tracing as well as verbose tracing, you will see all requests that come into a particular web server, thus allowing you to see if your Silverlight application is even looking for the ClientAccessPolicy.xml file and allowing you to see service messages.  Sometimes you don't want to write a full UI to see what a service is sending and you don't feel like attaching a debugger to look at an object's content.  Using DevServer, you can just look at the raw data the server is sending.  DevServer will automatically format anything it thinks is JSON or XML, allowing you to view it in its pretty form (of course, there's also a raw data view as well).  Here's a screen shot of what I got when I ran the sample for this document:

DevServer

As you can see, this can be tremendously helpful when you need to know how to parse or deserialize the incoming data or even to see if a response is even coming back from the server.

Conclusion

As you can see, there's more to Silverlight connectivity in WCF than the naive "Add Service Reference" option.  By simply understanding the mechanics of what's going on, we are able to tailor a solution to our specific needs.  WCF requires nothing more than an address, a binding, and a contract. With this information we can create a channel to access our service.  Then, with a few changes here and there we can optimize our experience for both security and fault tolerance.  Or, in the case of JSON, we can use tools already provided to us to obtain the exact JSON fields we need.  Hopefully you understand the often hidden concepts of WCF for .NET and Silverlight much better than you did before.

As a quick closing note, if you like going into technology at this level of depth, but also like thorough explanations, you seriously need to check out Juval Lowy's book, Programming WCF (2nd Edition).

Links

kick it on DotNetKicks.com

Architectural Overview: Creating Streamlined, Simplified, yet Scalable WCF Connectivity

Contents

Introduction

One of the most awesome things about WCF is that the concepts scale extremely well.  If you understand the ABCs of WCF, then you can do anything from creating a simple Hello World to a complex sales processing service.  It's all based on having an address, a binding, and a contract.  All the other concepts like behaviors, validators, and service factories are simply supplemental to the core of the system.  When you understand the basics, you have the general essence of all of WCF.

Because of this fully-scalable ABC concept, I'm able to use the same pattern for WCF architecture and development for every solution.  This is really nice because it makes it so that I don't have to wait time designing a new setup every time a new problem comes along.  In this discussion, I would like to demonstrate how you can create your own extremely efficient WCF solution based on my template.  Along the way, you will also learn a few pieces of WCF internals to help you understand WCF better.

Before I begin the explanation though, keep in mind that most concepts mentioned here are demonstrated in my Minima Blog Engine 3.1.  This is my training software demonstrating an enormous world of modern technologies.  It's regularly refactored and often fully re-architected to be in line with newer technologies.  This blog engine relies heavily on WCF as it's a service-oriented blog engine.  Regardless of how many blogs you have (or any other series of "content entries"-- for example, the documentation section of the Themelia web site is Minima), you have a single set of services that your entire organization uses.  If you understand the WCF usage in Minima, you will understand WCF very well.

Now, onto the meat (or salad, for the vegetarians) of the discussion...

Service Structure

On any one of my solutions, you will find a X.Service project and a X.ServiceImpl project where X is the solution "code" (either the solution name or some other word that represents the essence of the solution).  The former is the public .NET project which contains service contracts, data contracts, service configuration, and service clients.  The latter is the private .NET project which contains the service implementations, behaviors, fault management, service hosts, validators, and other service-side-only, black-boxes portions of the service.  All projects have access to the former, only the service itself will ever even know about the latter.

This is a very simple setup based upon a public/private model, like in public key cryptography.  The idea is that everything private is protected with all your might and everything public is released for anyone, within the context of the solution, to see.

For example, below is the Minima.Service project for Minima Blog Engine 3.1.  Feel free to ignore the folder structure, no one cares about that.  Just because I make each folder a namespace with prefixed folder names for exclusions, doesn't mean anyone else in the world does.  I find it to be the most optimal way to manage namespaced and non-namespaced groups, but the point of this discussion is the separation of concerns in the projects.

MinimaService

For the time being, simply notice that data contracts and service contracts are considered public.  Everything else in the file is either meaningless to this discussion or will be discussed later.

Here is the Minima.ServiceImpl project for the same solution:

MinimaServiceImpl

Here you can see anything from the host factory to various behaviors to validators to fault management to LINQ-to-SQL capabilities.  Everything here is considered private.  The outside world doesn't need to know, therefore shouldn't know.

For the sake of a more simplified discussion, let's switch from the full-scale solution example of Minima to a smaller "Person" service example.  This "Person" service is part of the overall "Contact" solution.  Here's the Contact.Service for our Contact solution:

PersonService

As you can see, you have a standard data contract, a service contract, and a few other things, which will be discussed in a bit.

For this example, we don't need validators, fault management, or behaviors, or host factories, all we need is a simple service in our Contact.ServiceImpl project:

PersonServiceImpl

By utilizing this model separating the private from the public you can easily send the Contact.Service assembly to anyone you want without requiring them to create their own client proxy or use the painfully horrible code generated by "Add Service Reference", which ranks in my lists as one of the worst code generators right next to FrontPage 95 and Word 2000.

As a side note, I should mention that I have colleagues who actually take this a step further and make a X.Service.Client project which houses the WCF client classes.  They are basically following a Service/Client/Implementation model where as I'm following a Public/Private model.  Just use which ever model makes sense for you.

The last piece needed in this WCF setup is the host itself.  This is just a matter of creating a new folder for the web site root, adding a web.config, and adding a X.svc file.  Period.  This is the entire service web site.

In the Person service example, the service host has only two files: web.config and Person.svc.

Below is the web.config, which declares two endpoints for the same service.  One of the endpoints is a plain old fashioned ASMX style "basic profile" endpoint and the other is one to be used for JSON connectivity.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
    <behavior name="JsonEndpointBehavior">
      <enableWebScript />
    </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="Contact.Service.PersonService">
    <endpoint address="json" binding="webHttpBinding" contract="Contact.Service.IPersonService" behaviorConfiguration="JsonEndpointBehavior" />
    <endpoint address="" binding="basicHttpBinding" contract="Contact.Service.IPersonService" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

The Person.svc is even most basic:

<%@ ServiceHost Service="Person.Service.PersonService" %>

This type of solution scales to any level.  If you want to add a service, just add a new X.svc file and register as a new service.  If you want to add another endpoint, just add that line.  It's incredibly simple and scales to solutions of any size and even works well with non-HTTP services like netTcpBinding services.

Service MetaData

Now let's look at each of these files to see how they are optimized.  First, lets' look at the data contract, Person:

using System;
using System.Runtime.Serialization;
//+
namespace Contact.Service
{
    [DataContract(Namespace = Information.Namespace.Contact)]
    public class Person
    {
    //- @Guid -//
    [DataMember]
    public String Guid { get; set; }

    //- @FirstName -//
    [DataMember]
    public String FirstName { get; set; }

    //- @LastName -//
    [DataMember]
    public String LastName { get; set; }

    //- @City -//
    [DataMember]
    public String City { get; set; }

    //- @State -//
    [DataMember]
    public String State { get; set; }

    //- @PostalCode -//
    [DataMember]
    public String PostalCode { get; set; }
    }
}

Everything about this file should be self explanatory.  There's a data contract attribute on the class and data member attributes on each member.  Simple.  But what's with the data contract namespace?

Well, earlier this year, a co-architect of mine mentioned to me that you can centralize your namespaces in static locations.  Genius.  No more typing the same namespace on each and every data and service contract.  Thus, the following file is included in each of my projects:

using System;
//+
namespace Contact.Service
{
    public class Information
    {
    //- @NamespaceRoot -//
    public const String NamespaceRoot = "http://www.netfxharmonics.com/service/";

    //+
    //- @Namespace -//
    public class Namespace
    {
        public const String Contact = Information.NamespaceRoot + "Contact/2008/11/";
    }
    }
}

If there are multiple services in a project, and in 95%+ of the situations there will be, then you can simply add more services to the Namespace class and reference them from your data and service contracts.  Thus, you never, EVER have to update your service namespaces in more than one location.  You can see this in the service contract as well:

using System;
using System.ServiceModel;
//+
namespace Contact.Service
{
    [ServiceContract(Namespace = Information.Namespace.Contact)]
    public interface IPersonService
    {
    //- GetPersonData -//
    [OperationContract]
    Person GetPersonData(String personGuid);
    }
}

This service contract doesn't get much simpler.  There's no reason to discuss it any longer.

Service Implementation

For the sake of our discussion, I'm not going to talk very much at all about the service implementation.  If you want to see a hardcore implementation, go look at my Minima Blog Engine 3.1.  You will see validators, fault management, operation behaviors, message headers, and on and on.  You will seriously learn a lot from the Minima project.

For our discussion, here's our Person service:

using System;
//+
namespace Contact.Service
{
    public class PersonService : Contact.Service.IPersonService
    {
    //- @GetPersonData -//
    public Person GetPersonData(String personGuid)
    {
        return new Person
        {
        FirstName = "John",
        LastName = "Doe",
        City = "Unknown",
        Guid = personGuid,
        PostalCode = "66062",
        State = "KS"
        };
    }
    }
}

Not too excited, eh?  But as it is, this is all that's required to create a WCF service implementation.  Just create an every day ol' class and implement a service contract.

As I've mentioned, though, you could do a ton more in your private service implementation.  To give you a little idea, say you wanted to make absolutely sure that no one turned off metadata exchange for your service.  This is something that I do for various projects and it's incredibly straight-forward: just create a service host factory, which creates the service host and programmatically adds endpoints and modified behaviors. Given that WCF is an incredibly streamlined system, I'm able to add other endpoints or other behaviors in the exact same way.

Here's what I mean:

using System;
using System.ServiceModel;
using System.ServiceModel.Description;
//+
namespace Contact.Service.Activation
{
    public class PersonServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
    {
    //- @CreateServiceHost -//
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        ServiceHost host = new ServiceHost(typeof(PersonService), baseAddresses);
        //+ add metadata exchange
        ServiceMetadataBehavior serviceMetadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (serviceMetadataBehavior == null)
        {
        serviceMetadataBehavior = new ServiceMetadataBehavior();
        host.Description.Behaviors.Add(serviceMetadataBehavior);
        }
        serviceMetadataBehavior.HttpGetEnabled = true;
        ServiceEndpoint serviceEndpoint = host.Description.Endpoints.Find(typeof(IMetadataExchange));
        if (serviceEndpoint == null)
        {
        host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
        }
        //+
        return host;
    }
    }
}

Then, just modify your service host line:

<%@ ServiceHost Service="Person.Service.PersonService" Factory="Person.Service.PersonServiceFactory" %>

My point in mentioning that is to demonstrate how well your service will scale based upon a properly setup base infrastructure.  Each thing that you add will require a linear amount of work.  This isn't like WSE where you need three doctorates in order to modify the slightest thing.

Service Client without Magic

At this point, a few of my colleagues end their X.Service project and begin a X.Service.Client class.  That's fine.  Keeping the client away from the service metadata is nice, but its not required.  So, for the sake of this discussion, let's continue with the public/private model instead of the service/client/implementation model.

Thankfully, I have absolutely no colleagues who would ever hit "Add Service Reference".  I've actually never worked with a person who does this either.  This is good news because, as previously mentioned, the code generated by the add service reference is a complete disaster.  You also can't modify it directly without risking your changing being overwritten.  Even then, the code is SO bad, you wouldn't want to edit it.  There's no reason to have hundreds or THOUSANDS of lines of code to create a client to your service.

A much simpler and much more manageable solution is to keep your code centralized and DRY (don't repeat yourself).  To do this, you just need to realize that the publicly accessible X.Service project already contains the vast majority of everything needed to create a WCF client.  Because of this, you may access the service using WCF's built in mechanisms.  You don't need anything fancy, it's all built right in.

Remember, WCF simply requires the ABC: and address, binding, and contract.  On the client-side, WCF uses this information to create a channel.  This channel implements your service contract, thus allowing you to directly access your WCF service without any extra work required.  You already have the contract, so you just have to do is declare the address and binding.  Here's what I mean:

//+ address
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
//+ binding
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
//+ contract
IPersonService personService = ChannelFactory<IPersonService>.CreateChannel(basicHttpBinding, endpointAddress);
//+ just use it!
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
String firstName = person.FirstName;

No 3,000 line client generated code, no excess classes, no configuration.  Just direct access to your side.

Of course, if you want to use a configuration file, that's great too.  All you need to do in create a system.serviceModel section in your project or web site and declare your service endpoint.  What's really nice about this in WCF is that, since the concept for WCF are ABC on both the client and server, most of the configuration is already done for you.  You can just copy and paste the endpoint from the service configuration to your client configuration and add a name element.

<system.serviceModel>
  <client>
    <endpoint name="PersonServiceBasicHttpBinding" address="http://localhost:1003/Person.svc" binding="basicHttpBinding" contract="Simple.Service.IPersonService" />
  </client>
</system.serviceModel>

For the most part, you will also need to keep any bindings on the service side as well, though you wouldn't copy over validation information.

At this point you can just change the previously used WCF channel code to use an endpoint, but that's an architectural disaster.  You never want to compile configuration information into your system.  Instead of tying them directly, I like to create a custom configuration for my solution to allow the endpoint configuration to change.  For the sake of this discussion though, let's just use appSettings (do NOT rely on appSettings for everything!  That's a cop-out.  Create a custom configuration section!).  Here's our appSetting:

<appSettings>
  <add key="PersonServiceActiveEndpoint" value="PersonServiceBasicHttpBinding" />
</appSettings>

At this point, I can explain that Configuration class found in the public Contact.Service project:

using System;
//+
namespace Contact.Service
{
    public static class Configuration
    {
    //- @ActivePersonServiceEndpoint -//
    public static String ActivePersonServiceEndpoint
    {
        get
        {
        return System.Configuration.ConfigurationManager.AppSettings["PersonServiceActiveEndpoint"] ?? String.Empty;
        }
    }
    }
}

As you can see, this class just gives me strongly-typed access to my endpoint name.  Thus allowing me to access my WCF endpoint via a loosely connected configuration:

//+ configuration and contract
IPersonService personService = new ChannelFactory<IPersonService>(ServiceConfiguration.ActivePersonServiceEndpoint).CreateChannel();
//+ just use it!
Person person = personService.GetPersonData("F488D20B-FC27-4631-9FB9-83AF616AB5A6");
String firstName = person.FirstName;

When I feel like using a different endpoint, I don't modify the client endpoint, but just add another one with a new name and update the appSettings pointer (if you're info fancy names, this is essentially the bridge pattern).

Now, while this is a great way to directly access data by people who understand WCF architecture, it's probably not a good idea to allow your developers to have direct access to system internals.  Entry-level developers need to focus on the core competency of your company (i.e. sales, marketing, data management, etc), not ponder the awesomeness of system internals.  Thus, to allow other developers to work on a solution without having to remember WCF internals, I normally create two layers of abstraction on top of what I've already shown.

For the first layer, I create a concrete ClientBase class to hide the WCF channel mechanics.  This is the type of class that "Add Service Reference" would have created if your newbie developers accidentally used it.  However, the one we will create won't have meaningless attributes and virtually manageable excess code.

Below is our entire client class:

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
//+
namespace Contact.Service
{
    public class PersonClient : System.ServiceModel.ClientBase<IPersonService>, IPersonService
    {
    //- @Ctor-//
    public PersonClient(String endpointConfigurationName)
        : base(endpointConfigurationName) { }

    //+
    //- @GetPersonData -//
    public Person GetPersonData(String personGuid)
    {
        return Channel.GetPersonData(personGuid);
    }
    }
}

The pattern here is incredibly simple: create a class which inherits from System.ServiceModel.ClientBase<IServiceContractName> and implements your service contract.  When you implement the class, the only implementation you need to add is a call to the base channel.  In essence, all this class does is accept calls and pass them off to a pre-created channel.  When you add a new operation to your service contract, just implement the interface and add a single line of connecting code to wire up the client class.

The channel creation mechanics that I demonstrated earlier is now done provided automatically by the ClientBase class.  You can also modify this class a little by bridging up to a total of 10 different constructors provided by ClientBase.  For example, the following constructor call will allow developers to specify a specific binding and endpoint:

public PersonClient(Binding binding, EndpointAddress address)
    : base(binding, address) { }

At this point, we have something that protects developers from having to remember how to create a channel.  However, they still have to mess with configuration names and must remember to dispose this client object (there's an open channel, remember).  Therefore, I normally add another layer of abstraction.  This one will be directly accessibly for developer user.

This layer consists of a series of service agents.  Each service has its own agent and is essentially a series of static methods which provide the most efficient means of making a service call.  Here's what I mean:

using System;
//+
namespace Contact.Service
{
    public static class PersonAgent
    {
    //- @GetPersonData -//
    public static Person GetPersonData(String personGuid)
    {
        using (PersonClient client = new PersonClient(ServiceConfiguration.ActivePersonServiceEndpoint))
        {
        return client.GetPersonData(personGuid);
        }
    }
    }
}

As you can see, the pre-configured service endpoint is automatically used and the PersonClient is automatically disposed at the end of the call (ClientBase<T> implements IDisposable).  If you want to use a different service endpoint, then just change it in your appSettings configuration.

Conclusion

At this point, I've explained every class or each project in my WCF service project model.  It's up to you to decide how to best create and manage your data and service contracts as well as clients.  But, if you want a streamlined, efficient, model for all your service projects, you will want to create a publicly accessible project to house all your reusable elements.

Also, remember you don't need a full-on client class to access a service.  WCF communicates with channels and channel creation simply requires an address, binding, and contract.  If you have that information, just create your channel and make your call.  You can abstract the internals of this by using a ClientBase object, but this is entirely optional.  If the project you are working on requires hardcore WCF knowledge, there's no reason to pretty it up.  However, if non-WCF experts will be working with your system, abstractions are easy to create.

Links

Love Sudoku?  Love competition?  Try the new Sudokian.com experience today.

kick it on DotNetKicks.com

NetFXHarmonics DevServer Released

Two months ago started work on a project to help me in my AJAX and SOA development.  What I basically needed was a development web server that allowed me to start up multiple web servers at once, monitor server traffic, and bind to specific IP interfaces.  Thus, the creation of NetFXHarmonics DevServer.  I built it completely for myself, but others started to ask for it as well.  When the demand for it became stronger, I realized that I needed to release the project on the web.  Normally I would host it myself, but given the interest from the .NET community, I thought I would put it on CodePlex.  I've only cried twice seen I've put it on CodePlex, but I'll survive.

NetFXHarmonics DevServer is a web server hosting environment built on WPF and WCF technologies that allows multiple instances of Cassini-like web servers to run in parallel. DevServer also includes tracing capabilities for monitoring requests and responses, request filtering, automatic ViewState and ControlState parsing, visually enhanced HTTP status codes, IP binding modes for both local-only as well as remote access, and easy to use XML configuration.

Using this development server, I am able to simultaneously start multiple web sites to very quickly view everything that happens over the wire and therefore easily debug JSON and SOAP messages flying back and forth between client and server and between services.  This tool have been a tremendous help for me in the past few months to discover exactly why my services are tripping out without having to enable WCF tracing.  It's also been a tremendous help in managing my own web development server instances for all my projects, each having 3-5 web sites (or segregated service endpoints) each.

Let me give you a quick run down of the various features in NetFXHarmonics DevServer with a little discussion of each feature's usage:

XML Configuration

NetFXHarmonics DevServer has various projects (and therefore assemblies) with the primary being DevServer.Client, the client application which houses the application's configuration.

In the app.config of DevServer.Client, you have a structure that looks something like the following:

<jampad.devServer>
</jampad.devServer>

This is where all your configuration lives and the various parts of this will be explained in their appropriate contexts in the discussions that follow.

Multiple Web Site Hosting

In side of the jampad.devServer configuration section in the app.config file, there is a branch called <servers /> which allows you to declare the various web servers you would like to load.  This is all that's required to configure servers.  Each server requires a friendly name, a port, a virtual path, and the physical path.  Given this information, DevServer will know how to load your particular servers.

<servers>
  <server key="SampleWS1" name="Sample Website 1" port="2001"
          virtualPath="/" physicalPath="C:\Project\DevServer\SampleWebsite1">
  </server>
  <server key="SampleWS2" name="Sample Website 2" disabled="true" port="2003"
          virtualPath="/" physicalPath="C:\Project\DevServer\SampleWebsite2">
  </server>
</servers>

If you want to disable a specific server from loading, use the "disabled" attribute.  All disabled servers will be completely skipped in the loading process.  On the other hand, if you would like to load a single server, you can actually do this from the command line by setting a server key on the <server /> element and by accessing it via a command line argument:

DevServer.Client.exe -serverKey:SampleWS1

In most scenarios you will probably want to load various sets of servers at once.  This is especially true in properly architected service-oriented solutions.  Thus, DevServer includes a concept of startup profiles.  Each profile will include links to a number of keyed servers.  You configure these startup profiles in the <startupProfiles /> section.

<startupProfiles activeProfile="Sample">
  <profile name="Sample">
    <server key="SampleWS1" />
    <server key="SampleWS2" />
  </profile>
</startupProfiles>

This configuration block lives parallel to the <servers /> block and the inclusion of servers should be fairly self-explanatory.  When DevServer starts it will load the profile in the "activeProfile" attribute.  If the activeProfile block is missing, it will be ignored.  If the activeProfile states a profile that does not exist, DevServer will not load.  When using a startup profile, the "disabled" attribute on each server instance is ignored.  That attribute is only for non-startup profile usage.  An activeProfile may also be set via command line:

DevServer.Client.exe -activeProfile:Sample

This will override any setting in the activeProfile attribute of <startupProfiles/>.  In fact, the "serverKey" command line argument overrides the activeProfile <startupProfiles /> attribute as well.  Therefore, the order of priority is is as follows: command line argument override profile configuration and profile configuration overrides the "disabled" attribute.

Most developers don't work on one project and with only client.  Or, even if they do, they surely have their own projects as well.  Therefore, you may have even more servers in your configuration:

<server key="ABCCorpMainWS" name="Main Website" port="7001"
        virtualPath="/" physicalPath="C:\Project\ABCCorp\Website">
</server>
<server key="ABCCorpKBService" name="KB Service" port="7003"
        virtualPath="/" physicalPath="C:\Project\ABCCorp\KnowledgeBaseService">
</server>
<server key="ABCCorpProductService" name="Product Service" port="7005"
        virtualPath="/" physicalPath="C:\Project\ABCCorp\ProductService">
</server>

These would be grouped together in their own profile with the activeProfile set to that profile.

<startupProfiles activeProfile="ABCCorp">
  <profile name="ABCCorp">
    <server key="ABCCorpMainWS" />
    <server key="ABCCorpKBService" />
    <server key="ABCCorpProductService" />
  </profile>
  <profile name="Sample">
    <server key="SampleWS1" />
    <server key="SampleWS2" />
  </profile>
</startupProfiles>

What about loading servers from different profiles?  Well, think about it... that's a different profile:

<startupProfiles activeProfile="ABCCorpWithSampleWS1">
  <profile name="ABCCorpWithSampleWS1">
    <server key="SampleWS1" />
    <server key="ABCCorpMainWS" />
    <server key="ABCCorpKBService" />
    <server key="ABCCorpProductService" />
  </profile>
</startupProfiles>

One of the original purposes of DevServer was to allow remote non-IIS access to development web sites.  Therefore, in DevServer you can use the <binding /> configuration element to set either "loopback" (or "localhost") to only allow access to your machine, "any" to allow web access from all addresses, or you can specific a specific IP address to bind the web server to a single IP address so that only systems with access to that IP on that interface can access the web site.

In the following example the first web site is only accessible by the local machine and the second is accessible by others.  This comes in handy for both testing in a virtual machine as well as quickly doing demos.  If your evil project manager (forgive the redundancy) wants to see something, bring the web site up on all interface and he can poke around from his desk and then have all his complains and irrational demands ready when he comes to your desk (maybe you want to keep this feature secret).

<server key="SampleWS1" name="Sample Website 1" port="2001"
        virtualPath="/" physicalPath="C:\Project\DevServer\SampleWebsite1">
  <binding address="loopback" />
</server>
<server key="SampleWS2" name="Sample Website 2" port="2003"
        virtualPath="/" physicalPath="C:\Project\DevServer\SampleWebsite2">
  <binding address="any" />
</server>

Web Site Settings

In addition to server configuration, there is also a bit of general configuration that apply to all instances.  As you can see from the following example, you can add default documents to the existing defaults and you can also setup content type mappings.  A few content types already exist, but you can override as the example shows.  In this example, where ".js" is normally sent as text/javascript, you can override it to go to "application/x-javascript" or to something else.

<webServer>
  <defaultDocuments>
    <add name="index.jsx" />
  </defaultDocuments>
  <contentTypeMappings>
    <add extension=".jsx" type="application/x-javascript" />
    <add extension=".js" type="application/x-javascript" override="true" />
  </contentTypeMappings>
</webServer>

Request/Response Tracing

One of the core features of DevServer is the ability to do tracing on the traffic in each server.  Tracing is enabled by adding a <requestTracing /> configuration element to a server and setting the "enabled" attribute to true.

<server key="SampleWS1" name="Sample Website 1" port="2001"
        virtualPath="/" physicalPath="C:\Project\DevServer\SampleWebsite1">
  <binding address="loopback" />
  <requestTracing enabled="true" enableVerboseTypeTracing="false" enableFaviconTracing="true" />
</server>

This will have request/response messages show up in DevServer which will allow you to view status code, date/time, URL, POST data (if any), response data, request headers, response headers, as well as parsed ViewState and Control state for both the request and response.  In addition, each entry is color coded based on it's status code.  Different colors will show for 301/302, 500+, and 404.

image

When working with the web, you don't always want to see every little thing that happens all the time.  Therefore, by default, you only trace common text specific file like HTML, CSS, JavaScript, JSON, XAML, Text, and SOAP and their content.  If you want to trace images and other things going across, then set "enableVerboseTypeTracing" to true.  However, since there is no need to see the big blob image data, the data of binary types are not sent to the trace viewer even with enableVerboseTypeTracing.  You can also toggle both tracing as well as verbose type tracing on each server as each is running.

There's also the ability to view custom content types without seeing all the images and extra types.  This is the purpose of the <allowedConntetTypes /> configuration block under <requestTracing />, which is parallel to <servers />.

<requestTracing>
  <allowedContentTypes>
    <add value="application/x-custom-type" />
  </allowedContentTypes>
</requestTracing>

In this case, responses of content-type "application/x-custom-type" are also traced without needing to turn on verbose type tracing.

However, there is another way to control this information.  If you want to see all requests, but want the runtime ability to see various content types, then you can use a client-side filter in the request/response list.  In the box immediately above the request/response list, you can type something like the following:

verb:POST;statuscode:200;file:css;contentType:text/css

Filtering will occur as you type, allowing you to find the particular request you are looking for.  The filter is NOT case sensitive.  You can also clear the request/response list with the clear button.  There is also the ability to copy/paste the particular headers that you want from the headers list by using typical SHIFT (for range) and CTRL-clicking (for single choosing).

Request/Response monitoring actually goes a bit further by automatically parsing both ViewState and ControlState for both request (POST) and response data.  Thanks goes to Fritz Onion for granting me permission to use his ViewState parser class in DevServer.

As a Training Tool

When announce any major project I always provide an "as a training tool" section to explain how the project can be used for personal training.  NetFXHarmonics DevServer is built using .NET 3.5 and relies heavily on LINQ and WCF with a WPF interface.  It also uses extensive .NET custom configuration for all server configuration.  In terms of LINQ, you can find many examples of how to use both query expression syntax and extension method syntax.  When people first learn LINQ, they think that LINQ is an O/R mapper.  Well, it's not (and probably shouldn't be usef for that in enterprise applications! there is only one enterprise class O/R mapper: LLBLGen Pro).  LINQ allows Language INtegrated Query in both C# and VB.  So, in DevServer, you will see heavy reliance on LINQ to search List<T> objects and also to transform LINQ database entities to WCF DTOs.

DevServer also relies heavily on WCF for all inner-process communication via named-pipes.  The web servers are actually hosted inside of a WCF service, thus segregating the web server loader from the client application in a very SOA friendly manner.  The client application loads the service and then acts as a client to the service calling on it to start, stop, and kill server instances.  WCF is also used to communicate the HTTP requests inside the web server back to the client, which is itself a WCF service to which the HTTP request is a client.  Therefore, DevServer is an example of how you can use WCF to communicate between AppDomains.

The entire interface in DevServer is a WPF application that relies heavy on WPF binding for all visual information.  All status information is in a collection to which WPF binds.  Not only that all, but all request/response information is also in a collection.  WPF simply binds to the data.  Using WPF, no eventhandling was required to say "on a click event, obtain SelectedIndex, pull data, then text these TextBox instances".  In WPF, you simply have normal every day data and WPF controls bind directly to that data being automatically updated via special interfaces (i.e INotifyPropertyChanged and INotifyCollectionChanged) or the special generic ObservableCollection<T>.

Since the bindings are completely automated, there also needs to be ways to "transform" data.  For example, in the TabItem header I have a little green or red icon showing the status of that particular web server instance.  There was no need to handle this manually.  There is already a property on my web server instance that has a status.  All I need to do is bind the image to my status enumeration and set a TypeConverter which transforms the enumeration value to a specific icon.  When the enumeration is set to Started, the icon is green, when it says "Stopped", the icon is red.  No events are required and the only code required for this scenario is the quick creation of a TypeConverter.

Therefore, DevServer is an example of WPF databinding.  I've heard people say that they are more into architecture and WCF and therefore have no interested in learning WPF.  This statement makes no sense.  If you don't want to mess with UI stuff, you need to learn WPF.  Instead of handing events all over the place and manually setting data, you can do whatever it is you do and have WPF just bind to your data.  When it comes to creating quick client applications, WPF is a much more productive platform than Windows Forms... or even the web!

Links

1 2 3 4

Powered by
Python / Django / Elasticsearch / Azure / Nginx / CentOS 7

Mini-icons are part of the Silk Icons set of icons at famfamfam.com