Search This Blog

Sunday, April 3, 2011

Silverlight: How to Communicate with Desktop Application via HTTP

Summary: Simple example showing how to communicate between a Silverlight application and a standalone .NET application with using HTTP.


Introduction
This article is a free continuation of  How to Receive Messages from Desktop Application and How to Send Message to Desktop Application where the Silverlight application communicates with the standalone .NET application via TCP.
In this article I would like to show how to implement the communication via HTTP.

The example bellow implements a .NET application as a service and Silverlight application as a client. The service listens to text messages and responses their length.
The client then uses the service to get the length of the given text.

The implementation uses Eneter Messaging Framework.
(Full, not limited and for non-commercial usage free version of the framework can be downloaded from http://www.eneter.net/. The online help for developers can be found at http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html.)

Policy Server
Same as the TCP communication, also the HTTP communication requires the policy XML file. Silverlight automatically requests this file when the application wants to connect other than the site of origin. In case of the HTTP, Silverlight requests the policy file on the root of the HTTP request. I.e. if the Silverlight application requests http://127.0.0.1/MyHttpService/, then Silverlight asks for the policy server from the root: http://127.0.0.1/clientaccesspolicy.xml.
If the policy file is not available or its content does not allow the communication, the HTTP request is not performed.


Service Application
The service application provides the HTTP policy service for the communication with the Silverlight client. Then it implements the simple service calculating the length for the given text.
Please notice, to run the HTTP listening application, you must execute it under sufficient user rights. Otherwise you will get an exception.

The whole implemetation is very simple.

using System;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;

namespace LengthService
{
    class Program
    {
        // Receiver receiving messages of type string and responding int.
        static private IDuplexTypedMessageReceiver<int, string> myReceiver;

        static void Main(string[] args)
        {
            // Start Http Policy Server
            // Note: Http policy server must be initialized to the root.
            HttpPolicyServer aPolicyServer = new HttpPolicyServer("http://127.0.0.1:8034/");
            aPolicyServer.StartPolicyServer();

            Console.WriteLine("Http Policy Server is running.");

            // Create Http messaging.
            IMessagingSystemFactory aMessaging = new HttpMessagingSystemFactory();

            // Create the input channel that is able to
            // receive messages and send back response messages.
            IDuplexInputChannel anInputChannel = 
                aMessaging.CreateDuplexInputChannel("http://127.0.0.1:8034/MyService/");

            // Create message receiver - response sender.
            // It receives 'string' and responses 'int'.
            IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory();
            myReceiver = aSenderFactory.CreateDuplexTypedMessageReceiver<int, string>();
            myReceiver.MessageReceived += OnMessageReceived;

            Console.WriteLine("The service is listening to Http.");
            Console.WriteLine("Press Enter to stop the service.\n");

            // Attach the duplex input channel and start listening.
            myReceiver.AttachDuplexInputChannel(anInputChannel);

            Console.ReadLine();

            myReceiver.DetachDuplexInputChannel();
            aPolicyServer.StopPolicyServer();
        }

        static private void OnMessageReceived(object sender,
            TypedRequestReceivedEventArgs<string> e)
        {
            if (e.ReceivingError == null)
            {
                int aLength = e.RequestMessage.Length;

                Console.WriteLine("Received string: {0}; Responded length: {1}",
                    e.RequestMessage, aLength);

                // Response the length of the string.
                myReceiver.SendResponseMessage(e.ResponseReceiverId, aLength);
            }
        }
    }
}

Silverlight Client Application
The client application uses the service to get the length of the given text.
The client application uses the assembly built for Silverlight, Eneter.Messaging.Framework.Silverlight.dll.
The implementation is very simple.

using System.Windows;
using System.Windows.Controls;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;

namespace LengthClient
{
    public partial class MainPage : UserControl
    {
        // Sender sending messages of type string and
        // receiving responses of type int.
        private IDuplexTypedMessageSender<int, string> mySender;

        public MainPage()
        {
            InitializeComponent();

            OpenConnection();
        }

        private void OpenConnection()
        {
            // Create HTTP messaging with default parameters.
            // Note: The default constructor routes received response
            //       messages into the Silverlight thread.
            //       If it is not desired, then it can be changed.
            IMessagingSystemFactory aMessaging = new HttpMessagingSystemFactory();

            IDuplexOutputChannel anOutputChannel =
                aMessaging.CreateDuplexOutputChannel("http://127.0.0.1:8034/MyService/");

            // Create message sender - response receiver.
            IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory();
            mySender = aSenderFactory.CreateDuplexTypedMessageSender<int, string>();
            mySender.ResponseReceived += OnResponseReceived;

            // Attach duplex output channel and be able to send messages
            // and receive response messages.
            mySender.AttachDuplexOutputChannel(anOutputChannel);
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            mySender.DetachDuplexOutputChannel();
        }

        private void GetLengthButton_Click(object sender, RoutedEventArgs e)
        {
            // Send the user text to the service.
            // Service will response the length of the text.
            mySender.SendRequestMessage(UserText.Text);
        }

        private void OnResponseReceived(object sender, TypedResponseReceivedEventArgs<int> e)
        {
            if (e.ReceivingError == null)
            {
                int aResult = e.ResponseMessage;

                // Display the response message.
                // The response message is the length of the text.
                ReceivedLength.Text = aResult.ToString();
            }
        }
    }
}


And here are communicating applications.

I hope, you found the article useful.

2 comments:

  1. Does it support .NETCF 2.0?

    ReplyDelete
  2. The current verion does not support .Net Compact Framework.
    I am considering to support it in the next version.

    ReplyDelete