Download Article
Download Developing Enterprise Windows* Store Apps using RESTful Web Services [PDF 596KB]
Abstract
This article discusses a way to create Enterprise Windows* Store apps that are connected to RESTful web services. It also includes a case study on implementing a network healthcare-themed application in C# that consumes a RESTful web service.
Overview
Since the World Wide Web (WWW) was invented at CERN in 1989, it has quickly become the real distributed computing platform that scientists and engineers have dreamed about for decades. This platform acts as a powerful and scalable storage and transportation tool for data. By mimicking John Gage’s famous phrase “the network is the computer,” we have seen “the Web is the computer” gradually become a reality in both the consumer and the business computing spaces. In 2000, Roy Fielding introduced the Representational State Transfer (REST) software architecture in his PhD dissertation. Since then, RESTful web services have become the mainstream design principle in implementing connected apps. In this article, we will use a healthcare line of business application case study to discuss how to implement Windows Store applications that consume RESTful web services.
RESTful Web Services
In traditional computer programming paradigms, we use CRUD to represent the basic operations when dealing with data in persistent storages, such as databases. By definition, the CRUD operations are Create, Read, Update, and Delete. For decades, Structured Query Language (SQL) has been the programming language used to interact with data in a database. The basic SQL queries easily map to the CRUD operations:
Table 1. CRUD operations in SQL
Operation | SQL query |
---|---|
Create | Insert |
Read | Select |
Update | Update |
Delete | Delete |
HTTP (HyperText Transfer Protocol), the foundation of the World Wide Web, serves as the interface between human, computer, and the Web. We can also see how the basic HTTP methods map to the CRUD operations:
Table 2. CRUD operations in HTTP Methods
Operation | HTTP Method |
---|---|
Create | POST |
Read | GET |
Update | PUT / PATCH |
Delete | Delete |
The same way SQL is used to interact with items stored in databases, such as the tables and the individual data items, HTTP is used to interact with items flowing in the Web. The items are called “resources.” HTTP uses URIs (Uniform Resource Identifiers) to reference resources in the Web. We often use “urls” (or “web addresses,” or “web links”) to refer to a web resource, for example, http://software.intel.com. A URL is technically a type of URI.
In Chapter 5 of his dissertation, Roy Fielding defines the REST-style software architecture by adding several constraints to the Web: Client-Server, Stateless, Cache, Uniform Interface, Layered System, and Code-On-Demand. A web service is called RESTful if it satisfies these architectural style constraints.
In this article, we will use a case study to show how to use Visual Studio* 2012 to create a Windows Store app that consumes RESTful web services.
A Healthcare Enterprise Windows Store App
Like we did in several other articles in this forum, we will build the case study around a healthcare Windows Store enterprise application. Some of the previous articles include:
- Porting App Life Cycle, Settings and Search Features from iOS* to Windows* 8
- Porting the User Interface from an iOS* Basic App to Windows* 8
- Porting Advanced User Interface from iOS* to Windows* 8
- Porting iOS* Custom Charts and Graphs to Windows* 8 UI
We will extend the same application to access a RESTful web service.
The application allows the user to login to the system, view the list of patients (Figure 1), and access patient medical records, such as profiles, doctor’s notes, lab test results, vital graphs, etc.
By extending the app to consume web services instead of using a local database, we enable the app to share data between the devices connected to the Web. Figure 1 is a screenshot of the Healthcare cloud-enabled application that this article is based on.
Figure 1: The Patients view displays the list of all patients. Selecting an individual patient provides a new view with further medical record details.
Porting an existing iOS* Web Service App
For developers with an iOS background, the APIs you probably used to create web service applications included Cocoa Touch* framework’s NSURLConnection or NSRLRequest to directly interact with web resources. A similar URL connection approach will be used in this case study, specifically the C# HttpClient class.
By working through the case study in this article, you should see similarities between the APIs and get a sense of how HTTP requests are done in a Windows Store app.
Constructing a RESTful Web Service Windows Store App
In the following sections we will walk through the code involved to connect to the web service, retrieve data, and then present the information in a healthcare-themed Windows Store app.
A RESTful Web Service
There are many different options for creating and deploying a web service that integrates with this type of cloud-based application. If you are porting a cloud-based application to a Windows Store app, you probably already have a web service solution up and running.
For the sample application outlined in the following sections, a simple RESTful ASP.Net MVC Web Application project was created for testing. It uses a local SQLite DB as the source of data and can be created easily with the Visual Studio* project templates. This runs using the Visual Studio integrated version of IIS and can be deployed to a service that supports IIS such as Windows Azure*.
Another possible solution would be to use a Python script to serve up a SQLite DB. Additional resources on possible web service options include the following:
- http://bottlepy.org/docs/dev/
- http://www.windowsazure.com/en-us/develop/net/tutorials/rest-service-using-web-api/
- http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
Further details on how to implement and deploy the web service is outside the scope of this article.
Set up the Project
First we need to set up a project. In Visual Studio 2012, one straightforward way to display a collection of information is to use the GridView control. So we will set up a new project and start with a blank template and then add to it a GridView control. The Grid App project could also be used and includes additional logic and views for navigation between screens.
Figure 2: The Add New Project dialog of the connected healthcare Windows* Store app project in Visual Studio* 2012
Choose an Item Page
Next, add a new item to the project and choose an Item Page. This step will add several dependent files to the project in addition to the new grid layout page that contains the GridView control we will use.
Figure 3: The Add New Item dialog of the connected healthcare Windows* Store app project in Visual Studio* 2012
Add a View Model Class
To get started writing code, we need to add a new class named PatientViewModel. We will follow the MVVM design pattern, which you can read about in detail here. This view model class is responsible for a couple of things. It exposes the collection of patients to the GridView control. It also contains the definition and data for a single Patient object pulled from our web service data source. For the sake of brevity, it also contains the definition of the data model. In our example this data source is a RESTful web service that makes an HTTP Get request to retrieve the patient information. The code in Sample Code 1 provides all of class definitions that we will use in the remainder of the view model. The class patient_main holds the data for a single patient that we show how to pull from the web service. The class ArrayOfPatient lets us easily move the entire collection of patients into our data structure. PatientViewModel exposes only three fields, Title, Subtitle, and Description, that we will eventually bind to the XAML view.
namespace PatientApp { // Data Model for patient public class patient_main { public int id { get; set; } public string lastname { get; set; } public string firstname { get; set; } public string gender { get; set; } public string dob { get; set; } public string ssn { get; set; } public string status { get; set; } public string lastvisit { get; set; } public string insurance { get; set; } } // There are some extra attributes needed to deal with the namespace correctly [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = “http://schemas.datacontract.org/2004/07/PRCloudServiceMVC”)] [System.Xml.Serialization.XmlRootAttribute(Namespace = “http://schemas.datacontract.org/2004/07/PRCloudServiceMVC”, IsNullable = false)] public class ArrayOfPatient { [System.Xml.Serialization.XmlElementAttribute(“Patient”)] public patient_main[] Items; } class PatientViewModel : BindableBase { private string title = string.Empty; public string Title { get { return title; } set { this.SetProperty(ref title, value); } } private string subtitle = string.Empty; public string Subtitle { get { return subtitle; } set { this.SetProperty(ref subtitle, value); } } private string description = string.Empty; public string Description { get { return description; } set { this.SetProperty(ref description, value); } } }
Sample Code 1**
Retrieving Data from the View Model
The following source in Sample Code 2 contains the method that the view will use to retrieve the list of patients from the view model. The bindable patient data is stored in an ObservableCollection and allows the loading of patient data to continue in the background while this method returns immediately to the UI.
private static ObservableCollection<PatientViewModel> _patients = null; // Retrieve the collection of patients public static ObservableCollection<PatientViewModel> GetPatients() { // create a new collection to hold our patients _patients = new ObservableCollection<PatientViewModel>(); // start the task of retrieving patients from the service LoadPatientDataFromService(_patients); // return the collection that will be continue to be filled asynchronously return _patients; }
Sample Code 2**
LoadPatientDataFromService is where the actual work is done, and this work is done asynchronously. The function itself does not return any data, but instead adds patient objects to the collection. When a new patient is added to the collection, the XAML View that is bound to the collection is automatically notified and updates the view accordingly. LoadPatientDataFromService uses the async keyword to indicate that this method is allowed to return to the calling function while it waits for work to be completed inside.
Sample Code 3 shows the contents of this method and starts the process of making and responding to the HTTP request.
async private static void LoadPatientDataFromService(ObservableCollection<PatientViewModel> patients) { // The serializer to deserialize XML into an array of data objects XmlSerializer ser = new XmlSerializer(typeof(ArrayOfPatient)); // make the call to the webservice to retrieve a stream of XML Stream rawXml = await GetPatientsRawXmlDataFromWebServiceAsyns(); // Create an xml reader to feed to the desrializer XmlReaderSettings readerSettings = new XmlReaderSettings() { Async = true, CloseInput = true }; using (XmlReader reader = XmlReader.Create(rawXml, readerSettings)) { // Deserialize the xml stream into an array of patient data var patientarray = ser.Deserialize(reader) as ArrayOfPatient; // Create our collection of view model patient objects foreach (var patientdata in patientarray.Items) { // Use some of the data elements to populate the view model var p = new PatientViewModel() { Title = patientdata.firstname + "" + patientdata.lastname, Subtitle = "Last Visit: " + patientdata.lastvisit, Description = "Date of Birth: " + patientdata.dob + " Gender: "+ patientdata.gender }; patients.Add(p); // add this to the collection - view will automatically get notified } } }
Sample Code 3**
For our example we ask the web service for XML as the response data format and, with the response, deserialize the data into an array of patient data. The serializer object does this for us once we have set up the types correctly with the correct namespace. See the definition of ArrayOfPatient for the attributes needed for this example to work with the namespace correctly.
GetPatientsRawXmlDataFromWebServiceAsyns performs the next critical task and is given below in Sample Code 4. Here, we are using localhost and port 52358 as our URI since we are locally hosting the web service in a separate Visual Studio project. 52358 just happens to be the default port for this project.
// Makes the HTTP GET request and returns a stream of XML response data async private static Task<Stream> GetPatientsRawXmlDataFromWebServiceAsync() { // construct URI from our session setting UriBuilder uriBuilder = new UriBuilder(“http://localhost:52358/”); uriBuilder.Path = “api/Patients”; // construct an HttpClient object to make the request. Use a custom client handler // to request XML instead of txt HttpMessageHandler handler = new WebProcessingHandler(new HttpClientHandler()); HttpClient client = new HttpClient(handler); // Make the GET request HttpResponseMessage response = await client.GetAsync(uriBuilder.Uri); if (response.IsSuccessStatusCode) { // read the result return await response.Content.ReadAsStreamAsync(); } return null; }
Sample Code 1**
The .Net class WebRequest is not available to Windows 8 Store apps, instead we must use an HttpClient object. The custom message handler is shown in Sample Code 5. The only purpose of using the custom handler is so that “application/xml” can be put in the request header. If this isn’t done, JSON-formatted text would be the result from the request instead of XML. JSON deserialization is just as easy as using XML and the DataContractJsonSerializer class handles the deserialization. Two asynchronous calls, GetAsync and ReadStreamAsync, are invoked to perform the work for making the request and reading the response.
// Custom Request Message handler private class WebProcessingHandler : MessageProcessingHandler { public WebProcessingHandler(HttpMessageHandler innerhandler) : base(innerhandler) { } protected override HttpRequestMessage ProcessRequest( HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { if (request.Method == HttpMethod.Get) { // Request XML instead of txt if this is an Http GET request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml")); } return request; } protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, System.Threading.CancellationToken cancellationToken) { return response; } }
Sample Code 2**
That’s it, GetPatients is all set to make a call to the cloud and asynchronously retrieve our patient data.
Binding the data in the View Model to the View
Next, we will take a look at how the data in the view model is bound to the view with only having to write one more line of C# code. Sample code 6 below contains the definition of the GridView
control in the XAML layout page. These values are all default except for changing the item template to Standard500x130ItemTemplate
. These templates are all defined in StandardStyles.xaml and using this predefined item template allows it to automatically bind to the properties Title, Subtitle, and Description within the ViewModel
class. In addition to the GridView
control, the CollectionViewSource
definition for itemsViewSource
is shown and is the object we will eventually bind the Patient collection to. The GridView control sets the itemsViewSource as the source of data with the XAML line ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
.
<!--Collection of items displayed by this page --> <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Items}"/> <GridView x:Name="itemGridView" AutomationProperties.AutomationId="ItemsGridView" AutomationProperties.Name="Items" TabIndex="1" Grid.RowSpan="2" Padding="116,136,116,46" ItemsSource="{Binding Source={StaticResource itemsViewSource}}" ItemTemplate="{StaticResource Standard500x130ItemTemplate}" SelectionMode="None" IsSwipeEnabled="false"/>
Sample Code 6**
Here is what the Standard500x130ItemTemplate
item template definition looks like. Notice the three text blocks with the Binding
keyword.
<!-- Grid-appropriate 500 by 130 pixel item template as seen in the GroupDetailPage --> <DataTemplate x:Key="Standard500x130ItemTemplate"> <Grid Height="110" Width="480" Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Border Background="{StaticResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110"> <Image Source="{Binding Image}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/> </Border> <StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0"> <TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding Subtitle}" Style="{StaticResource CaptionTextStyle}" TextWrapping="NoWrap"/> <TextBlock Text="{Binding Description}" Style="{StaticResource BodyTextStyle}" MaxHeight="60"/> </StackPanel> </Grid> </DataTemplate>
Sample Code 7**
To make the association that the list of Patients we retrieve should be used in this view, we just need a single line. The source below goes in the code behind C# file for the XAML view and makes the call to our previously described GetPatients()
method.
Protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { this.DefaultViewModel["Items"] = PatientViewModel.GetPatients(); }
Sample Code 8**
One of the greatest advantages of this binding is that no additional code is needed to handle events for when a Patient is added or removed from the collection. This is automatically taken care of for you by the ObservableCollection
and the XAML View.
After this data binding step is done, we will see a grid view of mock patient data as shown in Figure 4.
Figure 4: Screenshot of the sample code app with mock patient data and default styling
With additional styling, a professional look can be easily achieved, see Figure 1 at the start of this article.
Summary
We have discussed the RESTful software architecture and how to apply the development principles in Windows* Store Enterprise applications. From our case study we see the Windows 8 Runtime provides a good foundation for creating web service-based applications.
About the Authors
Nathan Totura is an application engineer in the Intel Software and Services Group. Currently working on the Intel® Atom™ processor-enabling team, he helps connect software developers with Intel technology and resources. Primarily these technologies include tablets and handsets on the Android*, Windows 8, and iOS platforms. Connect with Nathan on Google+ | |
Miao Wei is a software engineer in the Intel Software and Services Group. He is currently working on the Intel® Atom™ processor scale enabling projects. |
Copyright © 2013 Intel Corporation. All rights reserved.
*Other names and brands may be claimed as the property of others.
**This sample source code is released under the Intel OBL Sample Source Code License (MS-LPL Compatible), Microsoft Limited Public License, and Visual Studio 2012 License.