Kurt Claeys

DEVITECT.NET

  Home  |   Contact  |   Syndication    |   Login
  100 Posts | 42 Stories | 61 Comments | 14 Trackbacks

News

I'm a .NET architect / developer from Belgium an also trainer in .NET topics.

Kurt CLAEYS

 


 

View Kurt CLAEYS's profile on LinkedIn


Being ...





 


Working ...


and



Reading ...



Riding ...

Article Categories

Archives

Links

Wednesday, October 01, 2008 #

mvplogo Today I received the MVP Connected System Developer award. Thank you Microsoft and all of you who supported me.
I'll continue my focus on WCF/WF and Biztalk and keep evangelizing and training this technology to the community.
Stay tuned....

 

 

.


Wednesday, September 24, 2008 #

When using untyped messages on WCF operations we can take a more generic approach in creating services. The idea behind untyped messages is to create operations which take a parameter of which the type (and datastructure) is not known in the signature of the operation. This parameter is not a class you created and attributed with the DataContract attribute but it is the Message class found in the System.ServiceModel.Channels namespace.


using
System.ServiceModel.Channels; public interface IServiceInterface { Message TransactionAdd(Message msg); }


When using a parameter of type Message there can be only 1 parameter and the returntype of the operation has to be void or must be also of type Message.

It is a good practice to attribute this operation with a Name an Action and to set IsOneWay when needed. The action has to be specified by the client when sending a message to this operation.


[OperationContract(Name = "TransactionAdd", Action = "AddTransaction")] Message TransactionAdd(Message msg); [OperationContract(IsOneWay = true, Name = "TransactionAdd", Action = "AddTransaction")] void TransactionAdd(Message msg);


The client can put whatever data he likes into that operation as the structure is not strictly defined. The operation in the proxy expects a parameter from the Message class. A message can be created by calling the static method CreateMessage on the Message class. This method has an overload that takes 3 parameters : an indication which soapversion to be used, a string with the actionname (as specified in the operationcontract) and an instance of an object. That object could be a WCF DataContract, which means it’s just a class with the DataContract attribute in which the fields have the DataMember attribute.

MyDataContracts.Scenario1 myObject;

myObject = new MyDataContracts.Scenario1();

Message request;
request = Message.CreateMessage(MessageVersion.Soap12WSAddressing10,"AddTransaction",myObject);

Where the definition of MyDataContracts.Scenario1 is :

[DataContract]
public class Scenario1 
{
    [DataMember]
    public string AField;

    // more fields …
   
}


The CreateMessage() method serializes the object into the message and it can be given to the operation.

clientProxy.TransactionAdd(request);

On the service side, in the implementation we can use the incoming message as a raw XML stream by using the GetReaderAtBodyContents() method on the Message class. This results in an XMLDictionaryReader which allows having a look in all the elements and/or attributes in the XML.


This code results in the RAW xml :

XmlDictionaryReader reader;
reader = msg.GetReaderAtBodyContents();
string xml;
xml = reader.ReadOuterXml();


Or you can query the XML by xpath using an XmlDocument and the SelectSingleNode() method. To make this work you have to use a NameSpaceManager.

XmlDictionaryReader reader;
reader = msg.GetReaderAtBodyContents();

XmlDocument doc;
doc = new XmlDocument();
doc.Load(reader);

XmlNamespaceManager xmlNamespaceManager;
xmlNamespaceManager = new XmlNamespaceManager(doc.NameTable);
xmlNamespaceManager.AddNamespace("ns", "http://schemas.datacontract.org/2004/07/DataContracts");

Console.WriteLine(doc.SelectSingleNode("//ns:AField",xmlNamespaceManager).InnerText);


It also possible to recreate the object in memory from this XML and use as we’re used to. The generic GetBody<T>() method does the deserialization for us based on the specified type.

DataContracts.Scenario1 myObject;
myObject = msg.GetBody<DataContracts.Scenario1>();


The CreateMessage() and GetBody<T>() method use the DataContractSerializer behind the scenes but have versions where the serializer can be specified.

In this approach where the client serializes the data according the datacontract and the service deserializes this data again, without the datacontract being part of the signature of the operation, it’s obvious that the datacontracts should be kept in a separate library which is referenced by both the client and the serviceimplementation. Because no operation has specified the datacontract type in it’s signature it’s not known by the WSDL and thus not created in the proxy.


If the datacontracts cannot be shared to the client (because the client is not WCF, but a SOAP stack on another platform) you can specify that the servicecontracts do know the type by the ServiceKnownType attribute. This results in the datacontracts being part of the WSDL and will appear on the client as .xsd files. Then it’s up to the clientplatform to generate the classes in their language.

[ServiceContract]
[ServiceKnownType(typeof(DataContracts.Scenario1))]
public interface IServiceInterface
{
}


One thing you have to remember when consuming the messages in the implementation is that the XML data is read of the wire by using either GetReaderAtBodyContents() or GetBody<T>(). Once it’s consumed by one of the methods it cannot be consumed again by the other method. Using the two methods in sequence is a typical solution to be very generic. The GetReaderAtBodyContents () could look into the XML to decide what the type is we want to deserialize it to by GetBody<T>(). To solve this you have to use a MessageBuffer to create copies of the message and work with these copies.

Message msgCopy1;
Message msgCopy2;

MessageBuffer buffer;
buffer = msg.CreateBufferedCopy(int.MaxValue);
msgCopy1 = buffer.CreateMessage();
msgCopy2 = buffer.CreateMessage();

Monday, September 22, 2008 #

I'm looking forward to attend both PDC (26/10 - 30/10 Los Angeles) and TechEd Developers EMEA (10/11 - 14/11 Barcelona). Happy to go to Barca again, this time as MCT proctor.

Some more announcements on the conferences :

Countdown to PDC2008 by Amitabh Srivastava on Channel9 : http://channel9.msdn.com/posts/Dan/Countdown-to-PDC2008-Amitabh-Srivastava-Corporate-Vice-President-of-Cloud-Infrastructure--Services-H/

Interview with Hans Verbeek (with info on TechEd TV) on TechEd EMEA 2008 by Katrien De Graeve : http://www.microsoft.com/belux/msdn/nl/chopsticks/default.aspx?id=581

 


A unattended setup of MSMQ on W2003 can be done by the commandline utility sysocmgr.exe referencing the sysoc.inf file and providing it an answerfile (in .ini format) with the components you want to install.

c:\windows\system32\sysocmgr.exe /i:c:\windows\inf\sysoc.inf /u:c:\answerfile.ini /q /w

The simplest content for this answer file (answerfile.ini) is :

[Components]
msmq_Core = ON
Msmq_Common = ON
msmq_LocalStorage = ON

 


Wednesday, September 17, 2008 #

Last week I delivered a 5 day course on WCF/WF and Bizalk (http://www.ordina.be/SOA)

About 25 students where introduced to the world of SOA with Microsoft technologies.
Thanks to all of them, I had a great time ! Hope you enjoyed it.

Many asked me for links to resources on WCF. Here's a compilation of the best :

Dasblonde Webcast series :
http://www.dasblonde.net/2007/06/24/WCFWebcastSeries.aspx

Microsoft Nuggets by Mike Taulty :
http://www.microsoft.com/uk/msdn/screencasts/search-results.aspx?q=wcf

The most imporant MSDN pages :
http://msdn.microsoft.com/en-us/netframework/aa663324.aspx

http://msdn.microsoft.com/en-us/library/ms735119.aspx

http://msdn.microsoft.com/en-us/library/cc512374.aspx

http://msdn.microsoft.com/en-us/magazine/cc163447.aspx
http://msdn.microsoft.com/en-us/library/bb332338.aspx

WCF Security Guidance :
http://www.codeplex.com/WCFSecurity

Downloadable WCF Examples :
http://www.microsoft.com/downloads/details.aspx?familyid=2611A6FF-FD2D-4F5B-A672-C002F1C09CCD&displaylang=en

WikiPedia :
http://en.wikipedia.org/wiki/Windows_Communication_Foundation

The WCF forum :
http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=118&SiteID=1



I created a little screencast on WCF Impersonation :
(you will need to press the play button)

 

 

keywords : .NET, 3.0, 3.5, Window Communication Foundation, WCF, Tutorial, Demo, Screencast, Impersonation, Security, serviceAuthorization, impersonateCallerForAllOperations, AllowedImpersonationLevel, Principal, TokenImpersonationLevel, Impersonation, ClientCredentials 


Tuesday, September 02, 2008 #

See www.visug.be


ALT.NET Overview on Thursday, September 11, 2008 18:30 Compuware Zaventem
by Yves Goeleven

For the past year the alt.net movement has been stirring up the Microsoft community around the globe. Now it's getting hold of the Belgian community as well.
In this session I would like to present to you what the core values of the alt.net movement are, what principles, concepts and tools we hope to promote and to booth I would like to introduce the brand new 'Dutch alt.net user group'.

ASP.NET 3.5 SP1 special Part 1: MVC Framework on Tuesday, October 14, 2008 18:30 Cap Gemini Brussels
by Maarten Balliauw

This session provides an introduction to the ASP.NET MVC framework. Starting with a short intro to the model-view-controller pattern and Microsoft's driving goals for this alternative to classic ASP.NET, toover some of the key differences between classic ASP.NET and ASP.NET MVC like routing, extensibility, testing, ...

ASP.NET 3.5 SP1 special Part 2: ASP.NET Dynamic Data, ADO.NET Data Services and AJAX on Tuesday, October 21, 2008 18:30 AE
By Gill Cleeren

ASP.NET Dynamic Data: ASP.NET Dynamic Data helps you quickly build a fully customizable, data-driven application without writing code. Dynamic Data provides a rich scaffolding framework that is easily extensible by using the traditional ASP.NET programming model.
ADO.NET Data Services: ADO.NET Data Services provide new services that find, manipulate and deliver data over the web using simple URIs. Benefits include an easy and flexible way to access data over the web, while enabling the separation of presentation and data access code.
ASP.NET AJAX History: We’ll how to take advantage of the new AJAX History feature to enhance the user experience of a web application.
ASP.NET Routing: The final stop is ASP.NET Routing. We’ll explain the ASP.NET Routing engine and how it can provide better control over your web application's URLs. It discusses the pipeline of a request as seen by the routing engine, and how it can be extended to work with any type of web resource.

What's new in Visual Studio Team System Code Name "Rosario" on Thursday, November 27, 2008 18:30
by Pieter Gheysens 

Microsoft Visual Studio Team System code name "Rosario" is the version of Team System that follows Visual Studio Team System 2008. It is an integrated Application Life-cycle Management (ALM) solution comprising tools, processes, and guidance. Team System "Rosario" can be seen as a major release and will bring lots of new features in the areas of Project Management, Architecture, Version Control, Build, ... Come and enjoy a sneak preview of what will be shipped in the next version of Visiual Studio Team System.


Monday, September 01, 2008 #

WCF Durable services are WCF services in which the operations can remember the values of private variables (=the state of the service) inbetween restarts of the serivcehost and/or client. This is new in .NET 3.5 and the concept goes beyond the idea of .NET 3.0 WCF sessions. In WCF sessions the service keeps the content in a session environment which is not persisted by default, this means that the service can only remember the data as long as it is running. When the service is down, the data is lost. Also when the client is restarted the session is not accessible anymore because the client creates a new session by instantiating the proxy.

With durable services all state in the service is persisted to a database store. This database has a predefined structure. The instance of the service is serialized, a new GUID is generated, the serialized XML is inserted into a table with this GUID as key and the client gets the GUID. The client is supposed to send this GUID back to the service when it wants to be talking to the same instance. This guid is the instancId. The instanceID allows the service to recognize the client so it can reload the XML from the database and deserialize this XML to a running instance so the operation can work with the private state again.

With this concept both client and service can be restarted, as long as the client knows the instanceID and can send it back to the service, the service can recreate its state. So the service is realy durable.

In a durable scenario we typically have :

- an operation to start the durable session (PowerOn). This operation creates the record in the database.

- an operation that sends some data that the service has to remember (SendDataToTheService).

- an operation that receives this data back from the service (GetDataFromService).

- an operation that stops the session (PowerOff). This operation deletes the records from the database.

For this a normal WCF ServiceContract is used :

[ServiceContract]
public interface IServiceInterface
{
    [OperationContract]
    void PowerOn();

    [OperationContract]
    void SendDataToTheService(int data);

    [OperationContract]
    int GetDataFromService();

    [OperationContract]
    void PowerOff();
}


The implementation of the service needs some attributes.

1. The class has to be marked as [Serializable] and as [DurableService]

[Serializable]
[DurableService]
public class ServiceImplementation : ServiceInterfaces.IServiceInterface
 

2. The implementation of the operations have to be marked as [DurableOperation]. This attribute has two boolean flags.

CanCreateInstance = true : calling this operation results in creating the serialization and inserting it into the database.

CompletesInstance = true : calling this operation results in deleting the persited instance from the database.

int someDataToRemember = default(int);

[DurableOperation(CanCreateInstance = true)]
public void PowerOn()
{

    Console.WriteLine("PowerOn");
    Console.WriteLine("-" + System.ServiceModel.Dispatcher.DurableOperationContext.InstanceId);
}

[DurableOperation()]
public void SendDataToTheService(int data)
{
    
    Console.WriteLine("Got " + data);
    someDataToRemember = data;
}

[DurableOperation()]
public int GetDataFromService()
{
    Console.WriteLine("Returning " + someDataToRemember);
    return someDataToRemember;
}

[DurableOperation(CompletesInstance = true)]
public void PowerOff()
{
    Console.WriteLine("PowerOff");
}

wsHttpContextBinding : To allow durable services and the exchange of the instanceId the wsHttpContextBinding has to used on both service and client.

<services>
  <service behaviorConfiguration="ServiceBehavior" 
           name="ServiceImplementations.ServiceImplementation">
    <endpoint address="ContextOverHttp" 
              binding="wsHttpContextBinding"
              contract="ServiceInterfaces.IServiceInterface" />
  </service>
</services>

The service needs a behavior which has a persistenceProvidor element.

<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceBehavior"  >
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceCredentials>
        <windowsAuthentication allowAnonymousLogons="false" includeWindowsGroups="true" />
      </serviceCredentials>
      <persistenceProvider 
        type="System.ServiceModel.Persistence.SqlPersistenceProviderFactory, System.WorkflowServices, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
       connectionStringName="DurableServiceStore"
       persistenceOperationTimeout="00:00:10"
       lockTimeout="00:01:00"
       serializeAsText="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

This behavior element refers to a connectionstring to the database with the tables.

<connectionStrings>
  <add name="DurableServiceStore" connectionString="Data Source=KUCLXPX\SQLEXPRESS;Initial Catalog=DurableServicesPersistenceDB;Integrated Security=True"/>
</connectionStrings>

This database has to have the schema and stored procedure as defined SqlPersistenceProviderSchema.sql and SqlPersistenceProviderLogic.sql found in C:\WINDOWS\Microsoft.NET\Framework\v3.5\SQL\EN. Simply create a SQL Database and run the two scripts on it.

 

When the operation with the CanCreateInstance flag is true is called a record will be inserted into the table InstanceData;


pic4


... and the generated instanceId is send as part of the SOAP header to the client.

 

pic1


If you also want to make the client durable you have to manually add the instanceId to the context. This is done by getting a contextmanager from the InnerChannel of the proxy and asking this contextmanager for a reference to a dictionary of name/value pairs. One of the items in this dictionary has the name instanceID (watch it : case sensitive!!!). Give this item the value of the GUID. You can also obtain this GUID in this way.

System.ServiceModel.Channels.IContextManager contextManager;
contextManager = ((System.ServiceModel.IContextChannel)client.InnerChannel).GetProperty<System.ServiceModel.Channels.IContextManager>();
IDictionary<string, string> context = contextManager.GetContext();

if (!context.ContainsKey("instanceId"))
{

    context.Add("instanceId", "<the instanceID goes here>");
    contextManager.SetContext(context);
}

Now the calls the other operations receive this instanceId. A signal for WCF to reload the state before executing the call.


pic2


Nice to now : You can look into the tables to see the serialized state.

pic3


Thursday, August 28, 2008 #

Recently I was asked to describe what is understood by Software + Services. To make a big story short, I hereby summarize the key facts about this concept. Not a deep dive article for the hard core developers amongst us, but more a short, kind of elevator-story, summary on the executive level.
 
Software + Services is the combination of running software at the enterprise (also called on-premises software) and using services (with functionality or for data-storage) that are published on the internet (also called cloud services).
 
The on-premises software includes desktop software and server software and usually uses a local database. Cloud services is software (application and services) that is hosted by a service provider where data is also stored at the service provider.
 
The idea of Software + Services means the realization of a mix of these two worlds.
 
S+S = software on-premises + cloud services.
 
Three different types of architecture are recognized:
 
SaaS :
Software as a Service. Applications that run at service providers which are visualized by using the browser. SaaS is also known by the term finished services.

An example of this type of applications is Microsoft Dynamics CRM Online which can be used by the browser. It’s the online version of the popular Dynamic CRM application.
 
Attached Services
An application runs locally as an installed client and has its dedicated value and behavior. But additional functionality for the application is present as services in the cloud. The services in the cloud are meaningless without the client, but the client has its value even without the services. The services are considered as nice-to-have functions but are not essential for the local application.
 
Perfect example here is Microsoft Exchange. Exchange runs on premises but can use add-on services for additional functionality (like email filtering).
 
Cloud platforms (or Building Block Services)
Is a platform targeted to developers to support other applications in general, either in the cloud or running locally. This support is more than hosting only, it is an infrastructure to allow applications to communicate with each other or to create combinations (mash-ups) of multiple applications and third party services.
 
Windows Live Platform is the example here. It exposes services from the cloud that are meant to be used by local applications. Things like exposing Virtual Earth Maps and the Live Search API.
 
How does S+S compare to SOA? They are not the same although they overlap. SOA is a developer only area while S+S plays in the end users world. The cloud platform is where the overlap is situated.
 
Living in this S+S world is a bit more complex as the logic moves to the cloud. It has pros and cons that developers and decision makers have to understand.
 
Benefits are lower costs and a reduced risk in investments. SaaS applications don’t have the notion of licenses that have to be bought, because the price is based on the usage of the software or service (on a monthly base for instance). Most often the software can be tried before it’s bought so the chance to invest in software that does not fulfill the required needs is lower.
 
The biggest benefit is the faster deployment and the ease of upgrading. It’s simply a mather to create a login online and use the application through the browser. New versions are automatically available.
 
Combining the SaaS application with additional other services on a cloud platform is an ideal situation to evolve in the use of a broad set of functionalities for your company.
 
On the other hand we have to face the drawbacks which concern trust. Can we trust the provider and how safe is the data kept.
 
The biggest technology challenge (and thus an interesting future for developers) is the integration of the different parts of the SaaS application with other services and existing parts on-premises, the support for security and identity management and providing monitoring facilities for the use of the application. Again that’s where the cloud platforms fits it. The cloud platform has the needed infrastructure for these requirements.
 
There are basically two kinds of SaaS applications. The ones use by consumers, most often free of charge and possibly less reliable. The investment is paid by advertisements. Business applications are the other kind; they are paid for and have a service-level agreement.
 
As for now these are distinct kinds but in the future we will see combination of these.
 
Microsoft distinguishes these into two families of brands. The Live brand targets consumers, while the Online brand is for business users.
 
Since the last years we are already familiarized more or less with the first two types of architectures. ASP web applications are the SaaS applications avant-la-lettre. The use of attached services is also something we have seen before (I'm sure you browsed the iTunesStore while copying a CD to your ipod).
 
New is the notion of the cloud platform. Microsoft has launched Popfly, a platform capable of creating mash-ups in a visual way, ready for the public. Another effort, more on the integration level is Biztalk Services. This platform (which is not really related to the Biztalk product) supports integration, communication and security between on-premises applications running in different enterprises.
 
More in the SOA development, we will see the Oslo initiative.
 
I think were heading towards a very interesting future for developers as well for end users.
 

Wednesday, May 14, 2008 #

Today the MCT 2008 Welcome Pack arrived. I'll be certified trainer again, for the 4th year now. Last 12 months i've been busy with WCF and WF and I succeeded in both .NET 3.5 exams on these topics (TS: Microsoft .NET Framework 3.5 – Windows Communication Foundation and TS: Microsoft .NET Framework 3.5 – Windows Workflow Foundation). Looking forward to teach the new MOC's.

At the end of the month I'm off to TechEd 08 Orlando as Technical Learning Guide. Technical Learning Guide is a volunteer role as MCT to assist at TechEd. I'll be helping in the Hands-on-Labs. Beside this I will be presenting there the Instructor Led Lab "Workflow Services using the Windows Communication Foundation" (yeah, a training with both names of these great technologies in the title, that's my game) at TechEd. Hope to see someone from Belgium there.


Friday, May 02, 2008 #

WCF uses by default the DataContractSerializer found in System.Runtime.Serialization namespace to serialize an object to XML and back to an object. This is needed to transfer the data in the object through the communication channel as part of the SOAP packet.

The DataContractSerializer supports version tolerance which can be very helpful when versions of WCF Clients are not aligned with the versions of their needed WCF Services. It’s not always possible to upgrade all the clients at once when you deploy a new version of the service. Or maybe an already upgraded client must be able to talk to a previous version of the service and expect data back from it (roundtripping).

You can also use this DataContractSerializer yourself without needing WCF as the infrastructure around it. Based on this idea I started to do some research on how this versioning tolerance works and how it can be implemented.

First I created two generic methods which will do the serialization and deserialization. Very usefull methods I include as helperclasses in every WCF project I do.

* SerializeToString takes an object from a generic type as input and returns the XML containing the data as a string.

static public string SerializeToString(T o)
{
    DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof(T));

    StringWriter stringWriter = new StringWriter();

    XmlWriter xmlWriter = XmlWriter.Create(stringWriter);

    dataContractSerializer.WriteObject(xmlWriter, o);
    xmlWriter.Close();

    return (stringWriter.ToString());
}

* DeserializeFromString takes the XML string with the serialized data en creates an object out of this data.

static public T DeserializeFromString(string Xml)
{
    DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof(T));

    StringReader stringReader = new StringReader(Xml);
    XmlReader xmlReader = XmlReader.Create(stringReader);

    T obj = (T)dataContractSerializer.ReadObject(xmlReader);

    return obj;
}

Now ... Let’s consider some scenarios where we need version tolerance.

1. A second version of a class adds another field to it. When the object is serialized from XML created by the first version of the class, like in the case of the client being an older version compared to the service, we want to have a default injected in the missing field.

I’m using a very simple class called PersonClassV1 here.

[DataContract(Name = "Person", Namespace = "PersonNamespace")]
public class PersonClassV1 
{
    [DataMember]
    public string Name;
}

Version 2 adds a country field and also has a method which is attributed with the OnDeserializing attribute. This method will be executed when the DataContractSerializer deserializes the given XML. So it’s easy to check if the country field is not present and give it a default. The operation receiving this object would not see the difference as the country field is given this value before the data enters the operation.

[DataContract(Name = "Person", Namespace = "PersonNamespace")]
public class PersonClassV2 
{
    [DataMember]
    public string Name;

    [DataMember]
    public System.String Country;

    [OnDeserializing()]
    internal void OnDeserializing(StreamingContext context)
    {
        if (Country == null)
        {
            Country = "BE";
        }
    }
}

Notice also that both classes have been given the same name and namespace to simulate how you would work when updating a single datacontract of existing services.

In this drawing the arrow represent the serialization and deserialization.

image

The code for testing this :

PersonClassV1 p1;
p1 = new PersonClassV1();
p1.Name = "Kurt";         

string asXMLv1;
asXMLv1 = GenericDataContractSerializer<PersonClassV1>.SerializeToString(p1);
textBox1.Text = asXMLv1;

PersonClassV2 p2;
p2 = GenericDataContractSerializer<PersonClassV2>.DeserializeFromString(asXMLv1);
//Deserialize the XML from version 1 to an object if version 2
MessageBox.Show(p2.Name + " " + p2.Country);

This shows my name and the countrycode BE which is the given default in the messagebox.

As you can see there is no breaking change in the datacontracts here. Older clients can still send their data to services expecting a newer version. The new version of the datacontract on the service is responsible for defining the defaults.

 

2. A second version of the datacontract is on the client, but the service still uses the first version. The service gets some data in the serialized stream that it doesn’t know and cannot use. Of course the service does not know what it does not know so there’s no logic to use this extra field. WCF also supports version tolerance here, no breaking change. Not really a problem.

But what about roundtrips ? Suppose the operation returns this class again. When returning this class to the client the DataContractSerializer is used to serialize the class to XML. But as it doesn’t know the countryfield this field will be lost and be empty at the client altough the class at the client knows the field.

How can we work this out so that this extra field is not lost during this roundtripping ? The solution to this is to implement the IExtensibleDataObject interface. By implementing this interface a field called ExtensionData which is of type System.Runtime.Serialization.ExtensionDataObject is needed. This field is acting as a bag for the extra XML that is present in the data. This data becomes part of the datacontract although it not there to be used because the lower version of the service will not have logic for the additional data given by the second version of the dataContract. This ExtensionData object is there for roundtripping. When deserializing/serializing this class against the datactontract that has this extra field, the field is filled up with the data from the extensiondata field. The extensiondata field simply holds the XML data (at the service) that it cannot deserialize so it's there again when the data is serialized again at the client.

Code :

[DataContract(Name = "Person", Namespace = "PersonNamespace")]
public class PersonClassV1 : IExtensibleDataObject
{
    [DataMember]
    public string Name;

    #region IExtensibleDataObject Members

    private ExtensionDataObject extensionData;

    public ExtensionDataObject ExtensionData
    {
        get
        {
            return extensionData;
        }
        set
        {
            extensionData = value;
        }
    }

    #endregion
}

 

In this schema you see the serialization from version 2, deserializing this XML into version 1, serializing this again to XML and deserializing this XML again to an object of version 2.

image

Code to test this scenario :

PersonClassV2 p2;
p2 = new PersonClassV2();
p2.Name = "Kurt";       
p2.Country = "US";

string asXMLv2;
asXMLv2 = GenericDataContractSerializer<PersonClassV2>.SerializeToString(p2);

PersonClassV1 p1;
p1 = GenericDataContractSerializer<PersonClassV1>.DeserializeFromString(asXMLv2);

string asXMLv1;
asXMLv1 = GenericDataContractSerializer<PersonClassV1>.SerializeToString(p1);

PersonClassV2 p2bis;
p2bis = GenericDataContractSerializer<PersonClassV2>.DeserializeFromString(asXMLv1);

MessageBox.Show(p2bis.Country);

This shows me "US", the value of the country field given to the first instantiation of version 2.

Conclusion : Version 1 does not know the country field but can remember it in the extensionData field to spit it out when serialized so it's there when deserialized into the second version again.

You could say that it's a good practice in WCF development to always implement IExtensibleDataObject on your datacontracts.


Wednesday, April 23, 2008 #

A great tool every WCF developer could benefit from is SvcTraceViewer.exe. More info here. This tool is an UI to interprete the logfiles WCF can produce and show them in a nice graphical way. It even supports correlation of the activities in the client logfiles with the activities in the service logfile. So you can see when the messages are transported from client to server.

But this tool is kind of hidden gem. It doesn't come with Visual Studio and not with the Visual Studio extensions for WCF. You can not download it anywhere as a standalone executable.

No, the only way (as far that I know of) to have it, is to install the .NET SDK. The latest version of this SDK is 6.1 and is called 'Windows SDK for Windows Server 2008 and .NET Framework 3.5'.

This is a huge install. First you have to download a 1,29 GB .ISO on
http://www.microsoft.com/downloads/details.aspx?FamilyID=e6e1c3df-a74f-4207-8586-711ebe331cdc&DisplayLang=en. After burning it to DVD or mounting it with a ISO mounting tool (like http://www.slysoft.com/en/virtual-clonedrive.html) you can start the setup. Uncheck all the unneeded parts in the install options. To have SvcTraceViewer.exe you only need to select Developer Tools \ .NET Development Tools.

This setup will create the SDK directory which is C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin

SvcTraceViewer.exe is in this directory.

Here is some configuration code to setup you WCF host (and client) to produce the logfiles. I marked the place to configure the path to the logfiles in red.


<system.diagnostics>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose,ActivityTracing"
      propagateActivity="true">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" name="Default">
          <filter type="" />
        </add>
        <add name="ServiceModelTraceListener">
          <filter type="" />
        </add>
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose,ActivityTracing">
      <listeners>
        <add type="System.Diagnostics.DefaultTraceListener" name="Default">
          <filter type="" />
        </add>
        <add name="ServiceModelMessageLoggingListener">
          <filter type="" />
        </add>
      </listeners>
    </source>
  </sources>
  <sharedListeners>
    <add initializeData="C:\Temp\Logs\App_tracelog.svclog"
      type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
      <filter type="" />
    </add>
    <add initializeData="C:\Temp\Logs\App_messages.svclog"
      type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
      name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
      <filter type="" />
    </add>
  </sharedListeners>
  <trace autoflush="true" />
</system.diagnostics>


Tuesday, April 22, 2008 #

The first thing developers starting to implement Windows Communication Foundation (WCF) should know is the difference between the BasicHttpBinding and the WSHttpBinding.

This is very important as the BasicHttpBinding has some major drawbacks compared to the WSHttpBinding. From the functional view it makes no difference, it's just a client invoking an operation on a service, but there is a world of difference concerning the low level exchange of SOAP packets to achieve this.

BasicHttpBinding is there only to support the old .ASMX style of working (based on WS-BasicProfile 1.1) and aimed for clients which do not have .NET 3.0 installed. As lots of Windows 2000, which cannot run .NET 3.0, are still out there this is the only way to work with WCF. So the BasicHttpBinding it's there mainly for compatibility reasons.

But you have to be familiar with the idea that this basic profile binding is out-of-date and that the protocol does not have enough quality on board to support the requirements of enterprise oriented services, which can have a high SLA.

ASMX does not support secure messaging (I mean by default, without the WS enhancements). When a client calls an operation on a service, all data in the payload is send as a plain XML, human readable, SOAP packet. Scary? Isn’t? It also does not support reliability and ordered delivery. When a call is lost somewhere, the client is not informed and just waits for a timeout and can not know for sure if the call has arrived at the server and if the logic behind it got executed. Also lacking in the basic profile is ordered delivery. This means when a client fires multiple calls to the service it's not guaranteed that they arrive in the same order. Maybe somewhere a router could drop a packet allowing the second call to arrive earlier than the retransmission of the first. This can lead to disasters, which cannot be allowed in enterprise solutions.

In a sentence: do not use basicHttpBinding binding.

The WSHttpBinding fully supports these requirements on security, reliability and ordered delivery. Some of them as default, others have to be configured. But remember this tuning does not influence the functional development; it's all done under the covers!

So there is no excuse to not use the WSHttpBinding.

WSHttpBinding uses (as the name implies) the WS-* protocols. This results in having some additional handshake messaging and other ping-pong exercises (you got it, I got it, you got it, I got it ... as Juval Lowy would say this) to accomplish this. This means that not only SOAP requests are sent for the operation calls but also to have the client and service agree on some context and to inform each other on the success of the calls.

To fully understand when these extra messages are send and what they are carrying, we can have a closer look at the SOAP messages by using a tool like HTTP Analyzer. This great tool allows you to capture the HTTP traffic and dive into the SOAP packets on the wire.

You can download a demo version of HTTP Analyzer at http://www.ieinspector.com/httpanalyzer/index.html

To experiment on these issues I created an application, which has some scenarios to demonstrate the differences on these bindings. You can download this VS2005 solution here.

I created 3 proxy-service scenarios, all of them exposing the same ServiceOperation and using the same really simple implementation.

[ServiceContract]
interface ITestServiceContract
{
    [OperationContract]
    int DoSomethingInTheService(int aNumber, string aString);

    [OperationContract]
    string DoAnotherThingInTheService(int aNumber, string aString);
}

class TheService : ITestServiceContract
{
    public int DoSomethingInTheService(int aNumber, string aString)
    {
        return aNumber * 10;
    }

    public string DoAnotherThingInTheService(int aNumber, string aString)
    {
        return string.Format("I got {0}", aString);
    }
} 

1. Using BasicHttpBinding (the ASMX style)

Code to start the service (I’m not using any config here, the service is running self hosted in a executable and configuration of binding and endpoint is done programmatically).


* The ServiceHost

ServiceHostBasic = new ServiceHost(typeof(TheService));
BasicHttpBinding binding;
binding = new BasicHttpBinding();
ServiceHostBasic.AddServiceEndpoint(typeof(ITestServiceContract), binding, "http://localhost:9000/ServiceHostBasic");

* The client creates a proxy

EndpointAddress endpointAddress;
endpointAddress = new EndpointAddress(new Uri("http://localhost:9000/ServiceHostBasic"));
BasicHttpBinding binding;
binding = new BasicHttpBinding();

ProxyBasic = new TheProxy(binding,endpointAddress);

* The client calls the operations

int a;
a = ProxyBasic.DoSomethingInTheService(100, "test");
string s;
s = ProxyBasic.DoAnotherThingInTheService(100, "test");

* The client closes the proxy.

ProxyBasic.Close();

Lets examine this scenario in detail. Doing all of this results in 2 messages traveling over the wire. One for the first call (DoSomethingInTheService) another for the second one (DoAnotherThingInTheService).

ss1

Both messages transport the call and the needed data to the service.

Content of the request for the second message (as an example, this is comparable to the first message) :

ss2

Content of the response for the second message:

ss3

Hmm, no security, not encrypted. The client cannot know whether the call arrived at the service, as this is a kind of fire and forget situation. No acknowledgement of the arrival of the call back to the client.


2. Using default WSHttpBinding.

* The ServiceHost
ServiceHostWS = new ServiceHost(typeof(TheService));
WSHttpBinding binding;
binding = new WSHttpBinding();
ServiceHostWS.AddServiceEndpoint(typeof(ITestServiceContract), binding, "http://localhost:9000/ServiceHostWS");

ServiceHostWS.Open();

* The client creates a proxy

EndpointAddress endpointAddress;
endpointAddress = new EndpointAddress(new Uri("http://localhost:9000/ServiceHostWS"));
WSHttpBinding binding;
binding = new WSHttpBinding();

ProxyWS = new TheProxy(binding, endpointAddress);

The rest of the code is the same. What has gone over the wire now? This results in 6 messages and their answers.

ss4

Message 1,2 and 3 is a handshake sequence to establish the security context. This handshake is using the Web Service Secure Conversation Languages build on the WS-Security and WS-Trust protocols.

In this part of a message 1 you can see the client asks for a security token.

 ss5b

The answer for this is a RequestSecurityTokenResponse.

ss6

The 2 following SOAP messages (message 2 en 3) complete this handshake.

Message 4 and 5 are the operation calls, but the data is now encrypted in a way the service infrastructure (=WCF) can decrypt this before sending it in the operation.

 cypherdata

Message 6 is again related to the securitycontext. But important to notice that message 6 is sent when closing the proxy. So the service can release the securitycontext.

As said, this behavior comes for free by using WCF, the developer does not have to know how this is done. Compared the ASMX this is a huge step forward. It would be hard to develop this yourself without WCF and if you would succeed in this is, it would be influencing the functional code.

This is the default behavior of the WSHttpBinding. But what about the reliability and ordered delivery?

3. Using default WSHttpBinding with the reliableSessionEnabled flag on.

When instantiating the WSHttpBinding you can set the reliableSessionEnabled flag to true. This instructs the WCF client to have the messages sent in a reliable session. This means that the client gets informed when the message arrives so there is no doubt whether the serviceoperation has done it’s job.

ss8

* The ServiceHost

ServiceHostWSReliable = new ServiceHost(typeof(TheService));
WSHttpBinding binding;
binding = new WSHttpBinding(SecurityMode.Message, true);
ServiceHostWSReliable.AddServiceEndpoint(typeof(ITestServiceContract), binding, "http://localhost:9000/ServiceHostWSReliable");

ServiceHostWSReliable.Open();

* The client creates a proxy

EndpointAddress endpointAddress;
endpointAddress = new EndpointAddress(new Uri("http://localhost:9000/ServiceHostWSReliable"));
WSHttpBinding binding;
binding = new WSHttpBinding(SecurityMode.Message, true);

ProxyWSReliabable = new TheProxy(binding, endpointAddress);

The only difference is this code compared to scenario 2 is in providing the parameters to the constructor of the binding. This at the client side and the service side.

This results in 9 messages and their answers, of which only 2 messages are the actual calls to the operations.

ss9

Message 1 to 3: Again this is the security context handshake like in the previous scenario.

Message 4: This message asks the service to create the sequence, so it knows it can expect multiple messages that are part of the same sequence.

createsequence

And the answer on this:

createsequenceresponse

Message 5 and 6 are again the encrypted calls to the operations. But notice that each message is carrying a sequence number.

The first operation:

ss10

The second operation:

ss11

Message 7 is the client asking to the service to acknowledge the 2 messages it just has send it.

This message (and the subsequent messages) is send when the proxy is closed. So remember its necessary to close your proxy always!

ss12

On which the service reacts by sending its acknowledgement:

ss13

Message 8 is again the client telling to the service it got its confirmation so both part can be sure the messages are delivered. This is what reliability is about.

Message 9 is as in the previous scenario to release the securitycontext at the service.


Summary (considering 2 calls to an ServiceOperation)

1. BasicHttpBinding (2 messages)

sum1

2. Default WSHttpBinding (6 messages)

sum2

3. Default WSHttpBinding with Reliable Session Enabled (9 messages)

sum3

Some remark: Although you can set the securityMode when creating the BasicHttpBinding for the service, you cannot use this without having either SSL on the IIS to implement for transort level security or implement the WS-enhancement stack on the client yourself. So out-of-the box ASMX services have this basic non-secure behavior. With WCF this comes all for free with the WSHttpBinding.

 

cu (happy coding)


Saturday, April 19, 2008 #

A litle late, busy month, been on holiday to Lissabon with wife and kids and attended the Architect's Master Class (by Juval Lowy). 2 great experiences !

The links that hit my eye the last month are :

About ASP.NET MVC, great screencasts by Scott Hanselman
http://www.hanselman.com/blog/ASPNET35ExtensionsPlusMVCHowToScreencast.aspx
http://www.asp.net/learn/3.5-extensions-videos/default.aspx#mvc

About Workflow Services in .NET 3.5 on Channel9
http://channel9.msdn.com/Showpost.aspx?postid=398586
http://channel9.msdn.com/Showpost.aspx?postid=362199
http://channel9.msdn.com/ShowPost.aspx?postid=338720

Or by Mike Taulty (Building WCF Services Using Workflow Foundation)
http://www.microsoft.com/uk/msdn/screencasts/screencast/285/WF-V35-Building-WCF-Services-Using-Workflow-Foundation.aspx

More on Workflow Services : Building Workflow Services (WF+WCF) with Visual Studio 2008 by Marc Schweigert
http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?culture=en-US&EventID=1032366133&CountryCode=US

Free books on WCF
http://codeidol.com/csharp/wcf/
http://books.google.be/books?id=-AUyj6S7etwC</