Windows Phone – Phone PC Connector through WCF service

Windows Phone OS is being developed and I do not know which protocol Microsoft use to allow users and developers to transfer data between PC and phone, may be USB, Wifi, Bluetooth, etc … Within these protocols I prefer using protocol based on IP therefore today I would like to write a small demonstration which lets me download/upload file from PC to phone/from phone to PC.
The Demo source code consists of 2 projects :
- The sever is a WPF application running on PC. When the server starts to run, a WCF service will be automatically executed and listens on specific port to request and gives response back to phone client.

- The client is a Silverlight application running on Windows Phone Emulator. The client requires information of the IP and opened port of server for building the connection and accessing the WCF service. These settings are stored in InsolatedStorageFile within AppSettings.xml file and can be edited by client.

Before I start to discuss a little about my demo, there are some requirements we should do so that it runs smoothly
- If you are running a firewall, you must register the server so that the firewall allows inbound and outbound traffic of server. This registration can be done with programming but I still don’t integrate it into program.


Server side

As I said above, the server will host a WCF service inside it and starts the service at the same time. This service will open an available port (which requires administrator right and access through firewall) and binds the service to that port.

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
	try
	{
		lblServer.Content = TCPClass.GetIPV4();
		CustomConfiguration.Port = TCPClass.GetAvailablePort();
		txtPort.Content = CustomConfiguration.Port.ToString();
		txtServiceUri.Text = "http://" + TCPClass.GetIPV4() + ":" + CustomConfiguration.Port + CustomConfiguration.ServiceName;
		txtTargetFolder.Text = Directory.GetCurrentDirectory();
		m_wcfsFileTransfer = new WCFService();
		m_wcfsFileTransfer.CreateService();
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

ServiceHost uses BasicHttpBinding with TransferMode set on Streamed. “Setting the transfer mode to Streamed enables streaming communication in both directions. Streamed transfers can improve the scalability of a service by eliminating the need for large memory buffers. Whether changing the transfer mode actually improves scalability in practice depends on the size of the messages being transferred. Improvements in scalability should be most evident when large messages use streamed instead of buffered transfers.“. I already set the buffer size very large (64 MB) for sending large file.

public void CreateService()
{
	try
	{
		Uri uriTcpAddress = new Uri("http://" + TCPClass.GetIPV4() + ":" + CustomConfiguration.Port + CustomConfiguration.ServiceName);
		Uri[] uriBaseAddress = { uriTcpAddress };

		m_shHost = new ServiceHost(typeof(FileStreamingService), uriBaseAddress);

		BasicHttpBinding ntbBind = new BasicHttpBinding(BasicHttpSecurityMode.None);
		ntbBind.MaxBufferPoolSize = (int)67108864;
		ntbBind.MaxBufferSize = (int)67108864;
		ntbBind.MaxReceivedMessageSize = (int)67108864;
		ntbBind.SendTimeout = TimeSpan.FromSeconds(15);
		ntbBind.MaxReceivedMessageSize = 67108864;
		ntbBind.ReaderQuotas.MaxArrayLength = 67108864;
		ntbBind.ReaderQuotas.MaxStringContentLength = 67108864;
		ntbBind.TransferMode = TransferMode.Streamed;

		m_shHost.AddServiceEndpoint(typeof(IFileStreaming), ntbBind, "");

		ServiceMetadataBehavior smbBehavior = m_shHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
		if (smbBehavior == null)
		{
			smbBehavior = new ServiceMetadataBehavior();
			smbBehavior.HttpGetEnabled = true;

			m_shHost.Description.Behaviors.Add(smbBehavior);
		}

		m_shHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "http://localhost:" + (CustomConfiguration.Port - 1).ToString() + CustomConfiguration.ServiceName + "/mex");
		m_shHost.Open();
	}
	catch (Exception ex)
	{
		throw ex;
	}
}

After creating service, we can defines some operation contract so that the client can access and transfer data.
- GetStream : download file from PC to phone.
- UploadStream : upload file from phone (IsolatedStorageFile) to PC.
- GetStartUpFolder : get the folder where the server program locates.
- GetFolderInfo : get list of files and sub-folders of a specific folder.

[ServiceContract]
public interface IFileStreaming
{
	[OperationContract]
	System.IO.Stream GetStream(string data);
	[OperationContract]
	bool UploadStream(FileUpload stream);
	[OperationContract]
	string GetStartUpFolder();
	[OperationContract]
	List<ObjectInfo> GetFolderInfo(string Folder);
}

Client side
The mission of client is pretty simple. It just calls the service with appropriate data and receives data back. The operations of WCF services will be parsed in class ViewModel and used in client to browse, upload, download file in PC and phone.

void Explorer_Loaded(object sender, RoutedEventArgs e)
{
	string strType = "";
	NavigationContext.QueryString.TryGetValue("Type", out strType);
	if (strType == "PCExplorer")
	{
		btnUp.Visibility = System.Windows.Visibility.Visible;
		tbCurrentFolder.Visibility = System.Windows.Visibility.Visible;
		m_bUpload = false;
		vm.ReadConfiguration();
		vm.StartPCExplorer();
	}
	else
	{
		btnUp.Visibility = System.Windows.Visibility.Collapsed;
		tbCurrentFolder.Visibility = System.Windows.Visibility.Collapsed;
		m_bUpload = true;
		vm.ReadConfiguration();
		vm.StartPhoneExplorer();
	}
}

What we should make a concern about is that the operations should be called asynchronously and the stream type will be therefore automatically converted to byte array.

public void StartPCExplorer()
{
	try
	{
		fscClient.GetStartUpFolderCompleted += new EventHandler<GetStartUpFolderCompletedEventArgs>(fscClient_GetStartUpFolderCompleted);
		fscClient.GetStartUpFolderAsync();
	}
	catch (Exception ex)
	{
		throw ex;
	}
}

I am installing VS 2010 on my desktop and therefore I can not develop Windows Phone Application on my desktop. I must use my laptop to develop client. Hence the project contains 2 separated solutions. The complete source code you can download here “Windows Phone PC Connector“.

4 thoughts on “Windows Phone – Phone PC Connector through WCF service”

  1. Hi, thank you for your post.
    I tried to run your code but I’m getting this error:

    There was no endpoint listening at http://192.168.1.2:1024/WindowsPhoneServer/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.\n
    Can you help me solve this please !?

  2. great article! i have not been able to open the zip file for the attached source code. says it corrupt???

  3. Very useful article! I wanted to try out your solution. The WPF Windows Phone Server works (at least it compiles and starts…) but with the Windows Phone PC Connector solution there are some problems (references no more valid; namespaces changed; and mainly: “Manifest validation fails: Error code: ValidationSchemaValidation”). Maybe you can look into it and do an update :-) Would be awesome! Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>