MSDN Magazine Launch Issue - February 15, 2008 - (Page 40) Figure 7 Starting the Mail Transport Binding public Window1() { InitializeComponent(); ExchangeWebServiceMailBinding binding = new ExchangeWebServiceMailBinding(exchangeUrl, null); ((ExchangeWebServiceMailTransport) binding.Transport).ServerQueryInterval = 2000; messaging = new Messaging ( binding, Messaging .DesktopToDeviceChannel, Messaging .DeviceToDesktopChannel, incomingMessage); Start by adding the following two fields to the Window1.xaml.cs codebehind file. Change the Exchange server to your own Microsoft Outlook® Web Access URL: Messaging messaging; readonly Uri exchangeUrl = new Uri(“https://mail.wingtiptoys.com”); Just like in the device app, create the message receiving method so you can pass it in as a callback to the Messaging constructor: void incomingMessage(string message) { } } Add several reference assemblies to the desktop project, similar to the way you did with your device project. The assemblies you need to reference are: • System.ServiceModel.dll • System.Runtime.Serialization.dll • Microsoft.ServiceModel.Channels.Mail.dll • Microsoft.ServiceModel.Chan nels.Mail.ExchangeWeb Service.dll Next, link the MessageSerializer.cs and Messaging.cs files that you created in your device project into your desktop project. Rightclick on DesktopMessagingApp in Solution Explorer, then click Add | Existing Item. Navigate to your device application directory. Select both MessageSerializer.cs and Messaging.cs, but don’t click the Add button just yet. Instead, click the down arrow that is on the right edge of the button and select Add As Link. This allows you to share source files between the two projects. The only catch here is that since you created the source files in the device project, the namespace around the shared classes matches the device project’s namespace. If this bothers you too much, you can simply change the namespace for these classes to something more common. Additionally, you could put these two source files in a shared library project (being careful to not reference either the ExchangeWebService.dll or the WindowsMobile.dll assemblies). Construction and teardown of the mail channel for the desktop app will be similar to the device application, except you will instantiate ExchangeWebServiceMailBinding instead of WindowsMobileMailBinding. Also worth noting is that while WindowsMobileMailBinding just used the mailbox on the device (or emulator), ExchangeWebServiceMailBinding needs network credentials. Assuming that the credentials are the same as your network login credentials, you can just pass null into the ExchangeWebServiceMailBinding constructor, and Exchange will authenticate using Windows Integrated Security. You can keep this pattern (which is more secure), or you can hardcode the user name and password, or you can prompt the user for credentials at run time before constructing the Messaging instance. One other difference between the two mail-binding classes: WindowsMobileMailBinding is notified immediately when ActiveSync brings down a new message, but ExchangeWebSer viceMailBinding has to periodically call WebMethods to query for new messages, so you can either accept the default period of 30 seconds or set it yourself. 40 msdnmagazine Mobile WCF You can instantiate a Messaging class in the Window1 constructor, passing it the Exchange mail binding (see Figure 7). This next step is very important: swap the order of the channel names from their order in the device app. By swapping the order, you allow the desktop to receive messages from the device and the device to receive messages from the desktop. If you fail to swap the channels, you have both sides speaking on the same channel and both listening on another channel—no messages would ever be received. And just so you do not have to wait half a minute to see any results, in this sample I force polling the Exchange server every two seconds. Be warned: setting the query interval to two seconds in a production app would probably introduce a scalability problem. To close the channel, you will need to wire up a method to respond to the Window.Closed event. Open the XAML code in the Window1.xaml file and add the Closed=“Window_Closed” attribute to your opening tag. It should look something like this: Add a Window_Closed method to your Window1.xaml.cs codebehind file and then call the Close method on your Messaging object, as shown here: void Window_Closed(object sender, EventArgs e) { messaging.Close(); } Once again, all you need to do is send and respond to messages. Add a handler for the Send menu button by double-clicking it in the designer. Call SendMessage and clear the textbox where the user typed her message so she can see that the message was sent: void sendButton_Click(object sender, RoutedEventArgs e) { messaging.SendMessage(toBox.Text, messageBox.Text); messageBox.Clear(); } To implement the incomingMessage method, once again keep in mind that it will be called from a background thread and you need to invoke it on the UI thread. The WPF way of doing this is slightly different than with Windows Forms. Instead of the InvokeRequired property, you call CheckAccess, and instead of calling Invoke on the control you call it on the control’s Dispatcher object. Lastly, WPF has some handy methods on the TextBox control that do exactly what we want to do, so take advantage of them: void incomingMessage(string message) { if (historyBox.CheckAccess()) { historyBox.AppendText(message + Environment.NewLine); historyBox.ScrollToEnd();
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.