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 https://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 = "https://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("https://<<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("https://<<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

  • Anonymous
    March 26, 2007
    Mark Prentice of the .NET Compact Framework team has just posted an introduction on how you will be able

  • Anonymous
    March 26, 2007
    Mark has a great post on the basics of WCF for the Compact Framework. Well worth the read! &lt;&lt;Check

  • Anonymous
    March 26, 2007
    Siguiendo la línea que os comentaba en el post anterior donde se mostraba un ejemplo que nos contaron

  • Anonymous
    March 27, 2007
    Ecco che se ne inizia a parlare anche nella pratica . Ottimo! Tra una settimana sarò con RoB a completare

  • Anonymous
    March 27, 2007
    Qualcosa inizia a muoversi ... ed era ora !!! Chissà che non riusciremo ad avere qualcosa per l'evento

  • Anonymous
    March 27, 2007
    Yesterday, Mark Prentice posted an introduction to the Windows Communication Foundation for .NET Compact

  • Anonymous
    March 27, 2007
    Are you going to MEDC2007 in Las Vegas ? Marc Prentice is and he's started blogging about the new WCF

  • Anonymous
    April 03, 2007
    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.

  • Anonymous
    April 05, 2007
    While I was still an MS MVP and a_MS RD_, one of the things I have always requested is to have WCF

  • Anonymous
    April 11, 2007
    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?.

  • Anonymous
    April 14, 2007
    The comment has been removed

  • Anonymous
    April 14, 2007
    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

  • Anonymous
    April 25, 2007
    Lets continue the discussion of the .NET Compact Framework new WCF features by discussing the new EMAIL

  • Anonymous
    August 11, 2007
    Lets continue the discussion of the .NET Compact Framework new WCF features by discussing the new EMAIL

  • Anonymous
    September 07, 2007
    Lately, I've been working on getting my WCF for NETCF hello world BLOG posts ( Intro to Messaging and

  • Anonymous
    September 07, 2007
    Lately, I&#39;ve been working on getting my WCF for NETCF hello world BLOG posts ( Intro to Messaging

  • Anonymous
    November 29, 2007
    An Introduction to WCF for Device Developers Chris Tacke OpenNETCF Consulting, LLC November, 2007 Download

  • Anonymous
    March 20, 2009
    MSDN文档 WindowsCommunicationFoundation(WCF)Developmentandthe.NETCompactFramework http://ms...