Search This Blog

Wednesday, July 29, 2015

RPC from Windows Phone 8.1 client to .NET service

Simple example showing how to call remote methods exposed by a .NET service application from Windows Phone 8.1 (Silverlight).

The source code from this example can be found here.

Introduction

The example bellow demonstrates how to implement the client-service communication using RPC (Remote Procedure Call) between a Windows Phone 8.1 (Silverlight) and a .NET applications.
It implements a simple calculator where Windows Phone is the client application which calls remote methods exposed by the .NET service application to calculate two numbers.

To Run Example

  1. Download Eneter.Messaging.Framework for .NET platforms.
  2. Download the example project.
  3. Open the solution in Visual Studio and update references to:
    Eneter.Messaging.Framework.dll - for .NET 4.5 CalculatorService project.
    Eneter.Messaging.Framework.WindowsPhone.dll - for CalculatorClientWindowsPhoneSilverlight project.
  4. Figure out the IP address your computer within your network and update the IP address in the client as well ass in the service source code.
  5. Run the CalculatorService application.
  6. Deploy the client application to Windows Phone device and run it.
  7. When client application is running press connect button and then you can start to try calculate numbers.

RPC from Windows Phone Silverlight

RPC functionality in Windows Phone Silverlight is not so elegant like in a classic .NET application. The reason is Windows Phone Silverlight does not support emitting of metadata and MSIL (Microsoft Intermediate Language). Therefore it is not possible to create the proxy for the given service interface in runtime. It means the RPC client in Eneter cannot provide the proxy (like in .NET) allowing to call service methods as if they are local methods.
To overcome this issue Eneter provides a possibility to call methods explicitly by name and list of parameters. E.g.:

// Call remote method in the service.
int aResult = (int) myRpcClient.CallRemoteMethod("Calculate", a, b);

Windows Phone Client Application

Windows Phone Client is a simple application which provides buttons to connect and disconnect from the service and a simple UI to insert two numbers and the button Calculate which triggers the remote call to the service.

The whole implementation is very simple:

using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using Microsoft.Phone.Controls;
using System.Windows;

namespace CalculatorClientWindowsPhoneSilverlight
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Service interface.
        public interface ICalculator
        {
            int Calculate(int a, int b);
        }

        private IRpcClient<ICalculator> myRpcClient;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            // Sample code to localize the ApplicationBar
            //BuildLocalizedApplicationBar();
        }

        private void OnConnectBtnClick(object sender, RoutedEventArgs e)
        {
            OpenConnection();
        }

        private void OnDisconnectBtnClick(object sender, RoutedEventArgs e)
        {
            CloseConnection();
        }

        private void OpenConnection()
        {
            // Create RPC client.
            IRpcFactory anRpcFactory = new RpcFactory();
            myRpcClient = anRpcFactory.CreateClient<ICalculator>();

            // Use TCP messaging.
            // Note: provide IP address of your service computer.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
            IDuplexOutputChannel anOutputChannel
               = aMessaging.CreateDuplexOutputChannel("tcp://192.168.178.31:8099/");

            // Attach output channel and be able to call remote methods.
            myRpcClient.AttachDuplexOutputChannel(anOutputChannel);
        }

        private void CloseConnection()
        {
            myRpcClient.DetachDuplexOutputChannel();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            int a = int.Parse(Number1TextBox.Text);
            int b = int.Parse(Number2TextBox.Text);

            // Call remote method in the service.
            int aResult = (int) myRpcClient.CallRemoteMethod("Calculate", a, b);

            // Display the result.
            ResultTextBox.Text = aResult.ToString();
        }
    }
}

.NET Service Application

The service is a simple console application which exposes methods of ICalculatorService interface for remote procedure calls. When the client calls the remote method the Eneter framework forwards the call to the service and then when it returns the value it sends it back to the service.

using Eneter.Messaging.EndPoints.Rpc;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
using System;

namespace CalculatorService
{
    // Service interface.
    public interface ICalculator
    {
        int Calculate(int a, int b);
    }

    // SErvice implementation.
    public class Calculator : ICalculator
    {
        public int Calculate(int a, int b)
        {
            return a + b;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //EneterTrace.DetailLevel = EneterTrace.EDetailLevel.Debug;
            //EneterTrace.TraceLog = new StreamWriter("d:/tracefile.txt");

            // Instantiate class which implements the application logic of the service.
            ICalculator aCalculator = new Calculator();

            // Create RPC service.
            IRpcFactory anRpcFactory = new RpcFactory();
            IRpcService<ICalculator> anRpcService
               = anRpcFactory.CreateSingleInstanceService<ICalculator>(aCalculator);

            // Use TCP for the communication.
            // Note: provide IP address of your service computer.
            IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
            IDuplexInputChannel anInputChannel
               = aMessaging.CreateDuplexInputChannel("tcp://192.168.178.31:8099/");

            // Attach input channel to the service and start listening.
            anRpcService.AttachDuplexInputChannel(anInputChannel);

            Console.WriteLine("The calculator service is running. Press ENTER to stop.");
            Console.ReadLine();

            // Detach the input channel to stop listening.
            anRpcService.DetachDuplexInputChannel();
        }
    }
}


No comments:

Post a Comment