Introduction to Windows Communication Foundation for the .NET Compact Framework Messaging Stack


This BLOG continues my discussion into new features of .NET Compact Framework 3.5 by diving into Windows Communication Foundation for the .NET Compact Framework Messaging stack.  To start I suggest you read Romans WCF overview BLOG at http://blogs.msdn.com/romanbat/archive/2006/10/21/windows-communication-foundation-compact-edition-and-the-story-of-the-lunch-launcher.aspx

As with all features included in NETCF, the WCF implementation needed to be small to fit into device ROM’s.  Our original budget was 250kb and we tracked closely to this goal by cutting out the service layer and implementing a sub-set of the messaging stack.  Throughout our investigation a few critical end to end solutions required messaging level security, which was not orrginaly planned for.  To address these solutions, WCF for NETCF includes a subset of WS-Security.  This drove our size up to ~450kb.  The final implementation of WCF for NETCF includes the HTTP and email based transport, the text encoders and WS-Security.  Each of these features are extensible and  provides a flexible framework to allow each component to be swapped out or extended as needed. 

To introduce the messaging stack lets look at a hello world example using  HTTP or HTTPS request response.  There are distinct tasks which need to be completed for the client solution which includes; create the message, create the channel, open the channel, send the message then receive the response.   Server tasks follow similar steps; create the channel, open the channel and wait for response, parse and respond to the message.  To demonstrate this type of messaging channel I’ve added a simple code example below.  The client code will run on the PC so I if you do not have Orcas Beta1 or greater, which includes System.ServiceModel.dll, you can start your investigation PC them move to device when Orcas Beta2 is released.  Lets look at the specifics of a simple hello world example.

I’ve updated the code below to reflect the changes found in Orcas Beta2.

 Messaging Hello World Client Code:

The Hello World example below describes a simple use of the messaging stack in conjunction with the canned HTTP binding element.  

We need to implement infrastructure used by both the client and server.

First we need to add the needed references.

First add references to:

1. System.ServiceModel.dll

2. System.XML.dll

3 System.Runtime.Serialization.dll

Next we add the using statements.

using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.Xml; using System.Xml.Serialization; using System.Runtime.Serialization;

Next we need serializable class to contain our data. 

[System.SerializableAttribute()] [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://Microsoft.ServiceModel.Samples")] public class TransmittedObject { [System.Xml.Serialization.XmlElementAttribute(Order = 0)] public string str; [System.Xml.Serialization.XmlElementAttribute(Order = 1)] public int i; }

We next need to a helper class by extend the XMLSerilizer to be used in the context of WCF messages.

public sealed class XmlSerializerWrapper : XmlObjectSerializer { XmlSerializer serializer; string defaultNS; Type objectType; public XmlSerializerWrapper(Type type) : this(type, null, null) { } public XmlSerializerWrapper(Type type, string name, string ns) { this.objectType = type; if (!String.IsNullOrEmpty(ns)) { this.defaultNS = ns; this.serializer = new XmlSerializer(type, ns); } else { this.defaultNS = ""; this.serializer = new XmlSerializer(type); } } public override bool IsStartObject(XmlDictionaryReader reader) { throw new NotImplementedException(); } public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName) { throw new NotImplementedException(); } public override void WriteEndObject(XmlDictionaryWriter writer) { throw new NotImplementedException(); } public override void WriteObjectContent(XmlDictionaryWriter writer, object graph) { throw new NotImplementedException(); } public override void WriteStartObject(XmlDictionaryWriter writer, object graph) { throw new NotImplementedException(); } public override void WriteObject(XmlDictionaryWriter writer, object graph) { this.serializer.Serialize(writer, graph); } public override object ReadObject(XmlDictionaryReader reader) { string readersNS; readersNS = (String.IsNullOrEmpty(reader.NamespaceURI)) ? "" : reader.NamespaceURI; if (String.Compare(this.defaultNS, readersNS) != 0) { this.serializer = new XmlSerializer(this.objectType, readersNS); this.defaultNS = readersNS; } return (this.serializer.Deserialize(reader)); } }

We now have enough infrastructure to build the message.  It can look something like:

            TransmittedObject to = new TransmittedObject();
            to.str = "Hello";
            to.i = 5;

            XmlSerializerWrapper wrapper = 
                new XmlSerializerWrapper(typeof(TransmittedObject));

            Message m = Message.CreateMessage
                (MessageVersion.Soap11, "urn:test", to, wrapper);

Next up we need to create the channel using the BasicHttpBinding.

            BasicHttpBinding binding = new BasicHttpBinding();

            BindingParameterCollection parameters = 
                new BindingParameterCollection();

            IChannelFactory<IRequestChannel> channelFactory = 
                binding.BuildChannelFactory<IRequestChannel>(parameters);

            channelFactory.Open();

The channel then needs to be opened.  For PC to PC you can use LocalHost. If your using a device, you will need to setup an IIS server with an appropriate address which is reachable by the device

            IRequestChannel outChannel = 
                channelFactory.CreateChannel
                (new EndpointAddress(new Uri("http://<<ServerAddress>>:<<PortNumber>>")));

            outChannel.Open(TimeSpan.MaxValue);

It time to send the message and wait for the reply

            Message reply = outChannel.Request(m, TimeSpan.MaxValue);

Once the reply is received do Deserialize it and do something with the data.

            TransmittedObject to1 = 
                reply.GetBody<TransmittedObject>
                (new XmlSerializerWrapper(typeof(TransmittedObject)));

            MessageBox.Show(to1.str + " " + to1.i.ToString());

Lets clean up

            outChannel.Close();
            channelFactory.Close();

Messaging Hello World Server Code:

Now lets look at what the server code could look like.   

The server needs all the infrastructure described above including reference and using statements, TransmittedObject and XmlSerializerWrapper

Next the channel needs to be built.

            BasicHttpBinding binding = new BasicHttpBinding();

            BindingParameterCollection parameters = 
                new BindingParameterCollection();

            IChannelListener<IReplyChannel> listener = 
                binding.BuildChannelListener<IReplyChannel>
                (new Uri("http://<<ServerAddress>>:<<PortNumber>>"), parameters);

            listener.Open();

            XmlSerializerWrapper wrapper = 
                new XmlSerializerWrapper(typeof(TransmittedObject));

Next the channel needs to be opened.

            IReplyChannel channel = listener.AcceptChannel();
            channel.Open(TimeSpan.MaxValue);

Receiving the message

            RequestContext r = 
                channel.ReceiveRequest(TimeSpan.MaxValue);

            TransmittedObject to = 
                r.RequestMessage.GetBody<TransmittedObject>(wrapper);

Process the message

            to.str = to.str + " World";
            to.i = to.i + 1;

Finally we create the message and send the response.

            Message m = Message.CreateMessage
                (MessageVersion.Soap11, "urn:test", to, wrapper);

            r.Reply(m, TimeSpan.MaxValue);

Lets Clean up

channel.Close();

I hope this provides a brief description of using the WCF messaging stack as its implemented for the device using the .NET Compact Framework.


Comments (18)

  1. Mark Prentice of the .NET Compact Framework team has just posted an introduction on how you will be able

  2. Mark has a great post on the basics of WCF for the Compact Framework. Well worth the read! &lt;&lt;Check

  3. Byteabyte says:

    Siguiendo la línea que os comentaba en el post anterior donde se mostraba un ejemplo que nos contaron

  4. Ecco che se ne inizia a parlare anche nella pratica . Ottimo! Tra una settimana sarò con RoB a completare

  5. Qualcosa inizia a muoversi … ed era ora !!! Chissà che non riusciremo ad avere qualcosa per l’evento

  6. David Kline says:

    Yesterday, Mark Prentice posted an introduction to the Windows Communication Foundation for .NET Compact

  7. Paul Andrew says:

    Are you going to MEDC2007 in Las Vegas ? Marc Prentice is and he’s started blogging about the new WCF

  8. j.spraul says:

    Does this allow the Windows CE device to be the server part of the WCF equation? That would seem to be required for OEMs using Windows CE for custom platforms rather than the Windows Mobile application developers.

  9. While I was still an _MS MVP_ and a_MS RD_, one of the things I have always requested is to have _WCF_

  10. damir says:

    Could you please provide some information related to supported channel shapes, custom behaviors and custom channels? How much of these powerful feature are you going to provide for  CF?.

  11. Ben Kloosterman says:

    No mention of .. tcp/Binary Formatter. Why email transport and not a binary transport ? or MSMQ – this already exists and has store and forward ? ..

    I dont think anyone will use the email hooking ( there seem to be a few of these email hookings like the Exchange shutdown feature at the moment –  which i have yet to see anyone use. ) . Meanwhile they gimp debugging over wireless , which people were using. Yes store and retrieve/forward are needed but this is not a big deal.

    Small devices often run over older transports ie Packet radio (4800-9600 baud ) GPRS ( 30K if you are lucky) and these transports charge big $$ per MB.

    Hence you really want a binary protocol and even more a small service for callbacks so you can push instead of waste bandwidth for polling.

    If the only choice is HTTP will compression be supported ( like asmx web services on 3.5)

    Transport Security is often NOT an issue as you have WEP , WPA over wireless , over CDMA and KASUMI/A3/COMP128 over GSM .

    Authentication security is very usefull.

    Regards,

    Ben

  12. Ben Kloosterman says:

    btw WCF on CF would really help a number of our projects.

    One Question if end to end security is not required – can you not load the security dll?

    Regards,

    Ben

  13. Lets continue the discussion of the .NET Compact Framework new WCF features by discussing the new EMAIL

  14. Lets continue the discussion of the .NET Compact Framework new WCF features by discussing the new EMAIL

  15. Lately, I’ve been working on getting my WCF for NETCF hello world BLOG posts ( Intro to Messaging and

  16. Lately, I&#39;ve been working on getting my WCF for NETCF hello world BLOG posts ( Intro to Messaging

  17. An Introduction to WCF for Device Developers Chris Tacke OpenNETCF Consulting, LLC November, 2007 Download

  18. 黎波 says:

    MSDN文档

    WindowsCommunicationFoundation(WCF)Developmentandthe.NETCompactFramework

    http://ms