Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Building WCF Services for Deployment in Transiently Connected Networks : Page 4

Users increasingly rely on their applications to work both on site and on the go, so they can remain productive anywhere and at any time—regardless of how they connect to the network.


advertisement
Exploring the LibroLogic Test Harness
I am a big fan of using lightweight test harnesses to demonstrate service functionality. Test harnesses are useful for communicating functionality and demonstrating progress for services that are inherently abstract to the typical business user. I typically build them using Windows Forms because I can easily build some visually appealing bells and whistles into the interface to impress customers. In addition, getting into the habit of creating lightweight test harnesses for your services means that you have a smoke tester for exercising your services. Having test harnesses available for each service that support a business process can be a godsend when troubleshooting a problem within a business process that is distributed across multiple services behind a service boundary. If your business process is made up of half a dozen services and you want to know where the problem lies, you can exercise each service using its respective test harness, isolate the point of failure, and begin a very focused and effective debugging and troubleshooting session (or, better yet, prove that your service is working!).

 
Figure 7: The search tab on the test harness provides the ability to exercise search operations on the service when the network is online.
The user interface for working with the service is very basic, as it is takes a minimalist approach to showing the high-level functionality that the service provides. This said, if there are any WPF gurus out there that want to do a mashup, shoot me an email.

In exploring the test harness, Figure 7 shows the application with the "Search" tab selected. The search feature allows the user to enter either a unique identifier for the book (commonly a UPC code or ISBN number, however in this case I will use the ID used by the Pubs database) or a title keyword. Also notice in Figure 7 the status bar that indicates the status of the test harness. Certainly, there are several additional features that you could add to the application, but the sole purpose of this client is to demonstrate the core functionality that addresses the features previously discussed.

The "Purchase" tab allows a user to enter an ID for a given book and select a payment method. Again, this is a minimalist approach to demonstrating the core functionality of the service. Therefore, this form consists of a text box for the ID and a few check boxes to indicate the payment method. You will notice that I've labeled one of the check boxes "Flag." This check box allows the user to indicate that the book has not been sold, but is being flagged to indicate that the book has left the store despite not (yet) being sold. Figure 8 demonstrates the "Purchase" screen.

 
Figure 8: The purchase tab provides the ability to exercise one-way calls on the service, regardless of the user's location or network status.
 
Figure 9: The status of the network connection and whether the application is running locally or remotely is displayed to the user using a status bar.
One other important point of interest is the status bar shown in Figure 9. This control is visible regardless of the tab that is active. Tts sole purpose is to indicate whether a network connection is available, and if so, whether the application is running on site or off site.

Detecting the Status of the Network at Run Time
 
Figure 10: The endpoint will be determined at run time based on the state of the network and the location of the user.
There are a number of decisions that need to be made before you call the WCF proxy. Figure 10 presents a matrix for determining which endpoint you should use given a network and location condition. For instance, if the network is online and the application is running on site, you should use the InventoryTCP endpoint to service search requests. However, if the application is running off site and a network connection is present—assuming the user can access the Internet—you should use the InventoryHTTP endpoint to service the same search requests.

So, the first thing you must do before servicing a search request is figure out if a network connection is present. There are a number of ways to go about this, but it turns out that the .NET Framework 2.0 introduces a new namespace called System.Net.NetworkInformation that includes a class called NetworkInterface that provides just this kind of information. In fact, if you want to query whether the primary network interface is available, you can simply call a method called GetIsNetworkAvailable as shown below:

NetworkInterface.GetIsNetworkAvailable();

The GetIsNetworkAvailable method returns a Boolean value to indicate whether the network interface is online and functional. If you have more than one network connection, you can simply call the GetAllNetworkInterfaces method, which will return an array of NetworkInterface objects that can be further interrogated as needed. To do so, simply call the GetIPProperties method on the NetworkInterface class. The GetIPProperties method will return an object that implements IPInterfaceProperties. This interface provides nifty information such as IP, DNS, and Gateway addresses—exactly the information you would need to determine if the application is being run on site or remotely.

And just when you thought you could take no more, the System.Net.NetworkInformation namespace also provides a class called NetworkChange, which supplies an event called NetworkAvailabilityChanged that fires whenever the state of the network changes (i.e., a network connection is lost). NetworkChange also provides an event called NetworkAddressChanged that fires when an IP address changes. With either event, the runtime checks a list of subscribers and notifies the configured delegate—just as with any .NET event. In this case, your test harness will use delegates to intelligently act upon this information as it happens.

I was so impressed when my mentor and friend, Juval Lowy, showed me this technique that ever since I've been resolved to write about it. As you (hopefully) are starting to see, at your fingertips lies a tremendously powerful API that, when combined with WCF, allows you to develop applications with intelligence that just a few years ago would have been significantly more complex to implement.

Listing 7 shows the code for the test harness. One of the first things you will notice is two properties, Online and OnSite, both of which are thread-safe. The reason for this is that the NetworkAvailabilityChanged and NetworkAddressChanged events will call their corresponding delegates using threads from the thread pool. As such, support for multithreaded access is a must.

The Online property simply returns true or false to indicate whether the application has a network connection:

public bool Online { get { lock (this) { return m_Online; } } set { lock (this) { m_Online = value; } } }

The OnSite property works the same way, signaling if the location of the user is other than the configured location that is considered on site:



public bool OnSite { get { lock (this) { return m_Onsite; } } set { lock (this) { m_Onsite = value; } } }

Within the constructor of the LibroLogicClient Windows Forms class, note the following code that sets the value of the Online and OnSite properties, subscribes to the events of interest, and provides and initializes the status bar using the appropriate methods:

public LibroLogicClient() { InitializeComponent(); NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged; NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged; bool online = false; bool onsite = false; online = NetworkInterface.GetIsNetworkAvailable(); onsite = QueryLocation(); UpdateNetworkAvailableStatus(online); UpdateNetworkLocationStatus(onsite); }

The UpdateNetworkAvailableStatus method simply sets the Online property and subsequently calls a method called UpdateStatusBar:

void UpdateNetworkAvailableStatus(bool online) { Online = online; UpdateStatusBar(); }

The UpdateStatusBar method updates the text on the m_StatusBar control (which is rendered at the bottom of the LibroLogic UI as shown in Figure 7 and Figure 8). You must synchronize this update with the UI thread because the events fire from the thread pool. The MethodInvoker method handles the synchronization and updates the status bar with the respective string value:

private void UpdateStatusBar() { if (m_StatusBar.InvokeRequired) { m_StatusBar.Invoke(new MethodInvoker( UpdateStatusBar)); } else { m_StatusBar.Text = "Test"; string status = Online ? "Current Status: Online" : "Current Status: Offline"; string locStatus = OnSite ? "Onsite" : " | Offsite"; m_StatusBar.Text = status + locStatus; } }

Recall that in order to support the ability to detect intermittent network status at runtime, you must subscribe to the NetworkAvailabilityChanged and NetworkLocationChanged events. I have named the handlers for these events OnNetworkAvailabilityChanged and OnNetworkAddressChanged respectively.

The OnNetworkAvailabilityChanged method is of the NetworkAvailabilityChangedEventHandler delegate type and calls the UpdateNetworkAvailableStatus method just discussed:

void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs args) { UpdateNetworkAvailableStatus( args.IsAvailable); }

The OnNetworkAddressChanged method is of the delegate type NetworkAddressChangedEventHandler. Any time you call this handler, it will simply query the IP information using the QueryLocation method and update the status bar in much the same way as the UpdateNetworkAvailableStatus method. You can see all this code in Listing 7:

void OnNetworkAddressChanged(object sendes, EventArgs args) { UpdateNetworkLocationStatus( QueryLocation()); }



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap
Thanks for your registration, follow us on our social networks to keep up-to-date