What the new App Hub in Windows Phone Mango means for the Enterprise

Windows Phone 8 Tiles

If you attended MIX 11 or watched it on Channel 9, you might have seen Todd Brix’s session titled “Making Money with your Applications on Windows Phone.”

In this session, Todd talked about all the great things Windows Phone users and developers can expect with the new Marketplace and App Hub in the Mango timeframe.  I just want to focus on two items that will be of great significance to companies and organizations that are looking to build, and privately distribute Windows Phone apps to their employees, partners and customers.

Mango-Sizes

The Beta Distribution Service allows developers to distribute pre-certified apps to an access-controlled set of beta users.  How does it work?

  • The developer selects a list of up to 100 testers.  This number is subject to change based on feedback we get.
  • Developer sends an email to the designated testers that includes a private deeplink that points to the app in the Marketplace.  This allows only the testers to access and download the content since the app is not discoverable in the Marketplace via Search.
  • Only testers selected in the App Hub based on their Windows Live ID can test the app and provide feedback for 90 days.  Yes, the app will “time bomb” after 90 days.
  • The beta cannot be updated.  If you have multiple updates based on testing feedback, you must resubmit them like the first beta and send updated deeplinks to testers.
  • Testers won’t have to unlock their phone in order to beta test the apps.
  • Since there’s no certification requirement, there’s no latency between when you publish a beta app and when your private list of testers can access and download your content.
  • The cost of the beta app must be free.

Takeaway: No matter who you’re building apps and games for, the Beta Distribution Service will allow you to create higher quality content since you can now include beta testing in your development cycle.

The Private Distribution Service allows developers to privately distribute certified apps to a targeted group of users.  How does it work?

  • The app must be certified by Microsoft before distributing.
  • Developer sends an email to the targeted group of users that includes a private deeplink that points to the app in the Marketplace.  Keep in mind that the app is not discoverable in the Marketplace via Search by the general public.
  • A private app can be updated and pushed to the targeted group of users.
  • There are no limits on the number of users or the duration of time that those users can use the app.  This works just like the public Marketplace rules we have today.
  • There is no access enforcement based list of targeted users.  In other words, if an employee at a company shares the deeplink with a fellow coworker, that new person can download the content.  By including appropriate authentication and authorization mechanisms in published apps, you can prevent unwanted users from being able to do anything with the app.
  • Private apps can be free or paid
  • These private apps can be published to the public Marketplace at any time.

Takeaway: This enables the private distribution of released apps to a small or large community of users.  You could use this as an extension of your application beta testing cycle if you want to send out a release candidate to a broader group of testers than the 100 allowed via the Beta Distribution Service.  It’s also a great way to privately send your app to magazines, blogs, and other media channels to be publicly reviewed.

What does this mean for the enterprise?  Those of you who have worked with or administered enterprise software distribution systems, will quickly recognize that the Private Distribution Service doesn’t allow an administrator to push out and restrict software usage to specific organizational groups or roles.  It also doesn’t allow an administrator to uninstall specific apps  from the phones of specific users or groups either.  Lastly, it doesn’t map to an enterprise LDAP service like Active Directory.  You’re probably thinking System Center and this is definitely not that.

That being said, the Private Distribution Service overcomes the single-biggest blocker that company executives have expressed to me as a reason why they might not create and publish apps for Windows Phone.  They don’t want their private corporate apps publicly viewable and/or accessible by the broad general public searching for apps in the public Marketplace.  When they build B2C apps to reach their own customers, this is no problem, but when they build line-of-business apps meant just for their employees or partners, they don’t want these apps to be discoverable.

This means IT departments will be able to build undiscoverable Windows Phone apps for private internal use by the users they designate.  Some of the administrative issues around software distribution can be alleviated by having a corporate IT authority publish Beta and Private apps via a single Windows Live ID.  That publishing administrator can then map users, groups or roles to existing or new Windows Live IDs of employees that need to use the app.  That administrator will be able maintain the application lifecycle through beta testing, publishing, updating and decommissioning.  As I alluded to earlier in the post, once a designated employee has access to the app, her ability to run and access data and various parts of the app can be controlled by on-premise or cloud-based authentication and authorization mechanisms.  This includes things like passing Domain credentials or using claims-based auth.  Your data-in-transit is protected by SSL and your data-at-rest in Isolated Storage is protected by AES encryption.

We’ll be seeing a new Windows Phone, App Hub, and Marketplace before the end of 2011.  Its line-of-business credentials include encryption, private software distribution, server auth mechanisms, the ability to call SOAP and REST web services, socket support, multitasking, background agents, and a local SQL database just to name a few.

You’ll soon be looking at the most enterprise-ready smartphone on the market.

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Confronting the Consumerization of IT with Microsoft MEAP

Microsoft MEAP

CIOs are asking for help in confronting the tidal wave of mobile devices entering the enterprise and IT departments have raised the white flag as attempts to block consumer-focused smartphones and tablets have failed.

The Consumerization of IT has been a growing trend fueled by cloud-delivered services and compelling mobile devices with wireless capabilities.  This trend snowballs more and more each year, meaning it’s time to embrace it rather than put your head in the sand.  Microsoft MEAP is the answer.  I’ve been talking to you about how Microsoft aligns with Gartner’s Mobile Enterprise Application Platform (MEAP) for years now, and I wanted to update you on how we’ve evolved with respect to Gartner’s Critical Capabilities.  As a refresher, MEAP is Software + Services that allow IT orgs to extend corporate apps to mobile employees and business partners.  This platform must support:

  1. Multiple mobile applications
  2. Multiple mobile operating systems
  3. Multiple backend systems maximizing ROI vs. tactical solutions

It’s already a $1 Billion business and 95% of orgs will choose MEAP over point solutions by 2012.   The picture below represents some of our familiar cloud and on-premise servers on top and a wide spectrum of mobile devices from Microsoft and other manufacturers on the bottom:

Microsoft MEAP

Let’s do a quick rundown of Gartner’s Critical Capability list so you can see how we rise to their challenge:

  1. Integrated Development Environment for composing server and client-side logic: Microsoft Visual Studio supports on-premise and cloud server development and targets clients such as Windows, Windows Phone 7, Windows Mobile, the Web, Nokia S60, and the Macintosh.
  2. Application Client Runtime: Various flavors of Microsoft .NET (Silverlight, .NET, Compact Framework) run on Azure, Windows Server, Windows, the Mac, Windows Phone 7, Windows Mobile, and Nokia S60.  Guess what, you can use MonoTouch to take your .NET skills to the iPhone, iPad and iPod Touch.  MonoDroid is in the preview stage and will bring .NET to Android phones and tablets in the future.
  3. Enterprise Application Integration Tools: Connecting mobile devices to a variety of backend packages like Dynamics or SAP is critical.  Microsoft supports this integration in the cloud via Windows Azure AppFabric and on-premise though SQL Server Integration Services and dozens of adapters.  Tools like our Business Intelligence Dev Studio make EAI a repeatable, drag and drop exercise.
  4. Packaged Mobile Apps: Microsoft delivers the Office suite across Windows, Windows Phone 7, Windows Mobile, the Web and the Mac.  Office will be coming to Nokia in the future and One Note just arrived on iOS.
  5. Multichannel Servers: Windows Server + SQL Server on-premise and Windows Azure + SQL Azure in the cloud represents Microsoft’s mobile middleware platforms.  Windows Communication Foundation (WCF) delivers cross-platform SOAP & REST Web Services and cross-platform wire protocols like XML, JSON and OData.
  6. Software Distribution: Microsoft System Center Configuration Manager supports pushing software out to Windows and Windows Mobile.  Windows Phone 7 has Marketplace for this function.
  7. Security: Data-in-transit is secured by SSL across all platforms.  Data-at-Rest security for apps is facilitated on Windows by BitLocker, Windows Mobile through encryption policies and Windows Phone 7 through AESManaged in Silverlight.  Cross-platform auth is facilitated by Microsoft Windows Identity Foundation so devices can access resources via a Windows Live ID, Facebook, Google, Yahoo, ADFS and others.
  8. Hosting: It goes without saying the Microsoft knocks the hosting requirement out of the park with Azure.

So what do I want you to take away from all this?

Microsoft has a great MEAP stack comprised of servers and skillsets you probably already have at your company.  You get maximum reuse on our servers and in our cloud which means you save money when it’s time to build and deploy your second, third and fourth mobile app without new training, new servers, and different technologies each time.  I hope you’re pleasantly surprised to see that our .NET application runtime lives on so many mobile platforms.  Again, this means that your existing .NET skills can be reused on Microsoft devices, the Web, Mac, Nokia and even the iPad.  Who knew?  I’m looking forward to bring Android into the .NET camp as well.

It’s a brave new world of disparate devices connected to the cloud.  Companies have no choice but to target most all of them when constructing B2C apps to sell products or bring in new customers.  They’ve also found that this is the case in supporting their own employees and business partners with B2E and B2B apps.  No single company has so many different skillsets and competencies to pull this off.

There is one thing that most companies do have though.  A Microsoft infrastructure in their data center or the cloud, Windows on desktops, laptops and tablets, plus teams of .NET developers.  As I’ve just shown you, these .NET developers armed with Visual Studio or MonoTouch can be unleashed to allow you to reach almost every mobile platform.  This dramatically reduces the amount of extra Java and Eclipse skills that you’ll consider bringing in-house or outsourcing in order to target platforms like Android or the Blackberry.  Through the magic of WCF, all these platforms can connect to your critical Microsoft back-end resources and beyond.  You save money on training, use the servers you already have, resuse business logic and get to market faster.  No matter what platform you need to target, Microsoft and its partners want to help you reach your goals.

Looks like you’re already ahead of the game in taking on the Consumerization of IT.

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Improving the In-Memory Database

Phone 7

About a month ago, I wrote an article intended to help you fill some of the gaps left by the missing SQL Server Compact database.

Since your Windows Phone 7 Silverlight app is consuming an ObservableCollection of objects streaming down from Windows Azure and SQL Azure, it makes sense to organize those objects in a database-like format that’s easy to work with.  If you’ve ever worked with Remote Data Access (RDA) in the past, the notion of pre-fetching multiple tables to work with locally should look familiar.

In this case, each ObservableCollection represents a table, each object represents a row, and each object property represents a column.  I had you create a Singleton class to hold all these objects in memory to serve as the database.  The fact that Silverlight supports Language Integrated Query (LINQ) means that you can use SQL-like statements to work with the multiple, ObservableCollections of objects.

If you’re wondering why I have you cache everything in memory in a Singleton, there’s a few reasons.  For starters, it makes it easy to query everything with LINQ with the fastest performance possible for single and multi-table JOINs.  Secondly, I don’t represent a Microsoft product group and therefore wouldn’t engineer an unsupported provider that can query subsets of serialized data from files residing in Isolated Storage.  Finally, I don’t want you to accidentally find yourself with multiple instances of the same ObservableCollection when pulling data down from Azure or loading it from Isolated Storage.  Forcing everything into a Singleton prevents you wasting memory or updating objects in the wrong instance of an ObservableCollection.  An inconsistent database is not a good thing.  Don’t worry, you can control which tables are loaded into memory.

So what is this article all about and what are the “improvements” I’m talking about?

This time around, I’m going to focus on saving, loading and deleting the serialized ObservableCollections from Isolated Storage.  In that last article, I showed you how to serialize/de-serialize the ObservableCollections to and from Isolated Storage using the XmlSerializer.  This made it easy for you to save each table to its own XML file which sounds pretty cool.

So what’s wrong with this?

Saving anything as XML means that you’re using the largest, most verbose form of serialization.  After hearing me preach about the virtues of doing SOA with WCF REST + JSON, using the XmlSerializer probably seems out of place.  Luckily, the DataContractJsonSerializer supported by Silverlight on Windows Phone 7 gives you the most efficient wire protocol for data-in-transit can also be used to save those same .NET objects to Isolated Storage.  So the first improvement in this article comes from shrinking the size of the tables and improving the efficiency of the serialization/de-serializing operations to Isolated Storage using out-of-the-box functionality.

While going from XML to JSON for your serializing might be good enough, there’s another improvement in the way you write the code that will make this much easier to implement for your own projects.  A look back to the previous article reveals a tight coupling between the tables that needed to be saved/loaded and the code needed to make that happen.  This meant that you would have to create a SaveTable and LoadTable method for each table that you wanted to retrieve from Azure.  The new code you’re about to see is generic and allows you to use a single SaveTable and LoadTable method even if you decide to download 100 tables.

Enough talk already, let’s see some code.  Launch your ContosoCloud solution in Visual Studio and open Database.cs.  I want you to overwrite the existing code with the code shown below:

using System;
using System.Net;
using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization.Json;

namespace ContosoPhone
{
sealed class Database
{
//Declare Instance
private static readonly Database instance = new Database();

        //Private Constructor
private Database() { }

        //The entry point into this Database
public static Database Instance
{
get
{
return instance;
}
}

        //Serialize ObservableCollection to JSON in Isolated Storage
public void SaveTable<T>(T tableToSave, string tableName)
{
if (tableToSave != null)
{
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = store.CreateFile(tableName + “.txt”))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
serializer.WriteObject(stream, tableToSave);
}
}
}
else
{
throw new Exception(“Table is empty”);
}
}

        //Deserialize ObservableCollection from JSON in Isolated Storage
public T LoadTable<T>(T tableToLoad, string tableName)
{
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(tableName + “.txt”))
{
using (IsolatedStorageFileStream stream = store.OpenFile(tableName + “.txt”, System.IO.FileMode.Open))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
}
}
else
{
throw new Exception(“Table not found”);
}
}
}

        //Delete ObservableCollection from Isolated Storage
public void DropTable(string tableName)
{
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(tableName + “.txt”))
{
store.DeleteFile(tableName + “.txt”);
}
else
{
throw new Exception(“Table not found”);
}
}
}


//Declare Private Table Variables
private ObservableCollection<Customer> customerTable = null;

        //Customer Table
public ObservableCollection<Customer> Customers
{
get { return customerTable; }
set { customerTable = value; }
}
}
}

 

Looking from top to bottom, the first change you’ll notice is the new SaveTable method where you pass in the desired ObservableCollection and table name in order to serialize it as JSON using the DataContractJsonSerializer.  The next method down the list is LoadTable where you pass in the same parameters as SaveTable but you get back a de-serialized ObservableCollection.  The last new method in the Database Singleton is DropTable which simply deletes the serialized table from Isolated Storage if you don’t need it anymore.

So how do you call this code?

Bring up MainPage.xaml.cs, and find the click event for Save button.  Delete the existing XmlSerializer code and replace it with the following:

try
{
Database.Instance.SaveTable<ObservableCollection<Customer>>(Database.Instance.Customers, “Customers”);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

The code above shows you how to call the SaveTable method in the Singleton with the appropriate syntax to pass in the ObservableCollection type as well as actual ObservableCollection value and name.

Now find the click event for the Load button, delete the existing code and paste in the following:

try
{
Database.Instance.Customers = Database.Instance.LoadTable<ObservableCollection<Customer>>(Database.Instance.Customers, “Customers”);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

This code looks pretty much the same as the SaveTable code except that you set Database.Instance.Customers equal to the return value from the method.  For completeness sake, drop another button on MainPage.xaml and call it Drop.  In its click event, paste in the following code:

try
{
Database.Instance.DropTable(“Customers”);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

For this code, just pass in the name of the table you want to delete from Isolated Storage and it’s gone.

It’s time to hit F5 so you can see how things behave.

phone7

When your app comes to life in the emulator, I want you to exercise the system by Getting, Adding, Updating and Deleting Customers.  In between, I want you to tap the Save button, close the app, reload the app and tap the Load button and then View Customers to ensure you’re seeing the list of Customers you expect.  Keep in mind that when you Save, you overwrite the previously saved table.  Likewise, when you Load, you overwrite the current in-memory ObservableCollection.  Additionally, Saving, Loading, and Dropping tables that don’t exist should throw an appropriate error message.

So what’s the big takeaway for these tweaks I’ve made to the in-memory database?

While switching serialization from XML to JSON is a great improvement in size and efficiency, I truly believe that making the SaveTable and LoadTable methods generic and reusable will boost developer productivity.  The new ease with which you can Save and Load 1, 10 or even 1,000 tables makes this more attractive to mobile developers that need to work with local data.

So where do we go from here?

You now have some of the basic elements of a database on Windows Phone 7.  You don’t have ACID support, indexes, stored procedures or triggers but you have a foundation to build on.  So what should be built next?

To help ensure database consistency, I would add an AutoFlush feature next.  SQL Server Compact flushes its data to disk every 10 seconds and there’s nothing to prevent you from using the SaveTable method to do the same.  A timer set to fire at a user-specified interval that iterates through all the ObservableCollections and saves them will help keep your data safe from battery loss and unforeseen system failures.  The fact that your app can be tombstoned at any moment when a user taps the Back button makes an AutoFlush feature even more important.

Anything else?

At the beginning of this article I mentioned RDA which is a simple form of data synchronization.  It’s simple because it only tracks changes on the client but not the server.  To find out what’s new or changed on the server, RDA requires local tables on the device to be dropped and then re-downloaded from SQL Server.  With the system I’ve built and described throughout this series of articles, we already have this brute force functionality.  So what’s missing is client-side change tracking.  To do this, I would need to add code that fires during INSERTS, UPDATES, and DELETES and then writes the appropriate information to local tracking tables.  To push those changes back to SQL Azure, appropriate code would need to call WCF REST + JSON Services that execute DML code on Windows Azure.

I hope with the improvements I’ve made to the in-memory database in this article, you’ll feel even more empowered to build occasionally-connected Windows Phone 7 solutions for consumers and the enterprise.

Keep coding!

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Network Awareness

Phone 6

By now, you’ve heard me talk a lot about the role wireless data networks play when it comes to the success of your mobile application.

They are unreliable, intermittent, highly latent and often slower than they should be due to overtaxed cellular towers and congested backhaul networks.  Hopefully, you’ve built an app that tackles those challenges head-on using efficient WCF REST + JSON Services coupled with an offline data store.

So what is the user of your new application going to think when a Web Service call fails because the network is unavailable?

An end-user of your app probably won’t be too thrilled when they’re staring at an unintelligible error message.  Or maybe your app will just silently fail when the Web Service call doesn’t succeed.  The user might not know there’s a problem until they can’t view a list of relevant data on their phone.

This is no way to treat your prospective user-base because mobile apps should never diminish the user experience by trying to send or receive data in the absence of network connectivity.

Luckily, Silverlight on Windows Phone 7 provides you with a way to determine network connectivity.

Launch Visual Studio 2010 and load the ContosoCloud solution that we’ve been working with over the last four Windows Phone 7 Line of Business App Dev articles.  First, I want you to drag an Ellipse from the Toolbox and drop it on MainPage.xaml.  Name that control ellipseNet.  Next, I want you to drag a TextBlock control over and drop it beneath the Ellipse.  Name this control textBlockNet.  Now open MainPage.xaml.cs so we can write some code.

Above the ContosoPhone namespace I want you to add:

using Microsoft.Phone.Net.NetworkInformation;

This allows you to tap into the NetworkInterface class.  The next line of code I want you to add may seem a little confusing since it’s similar, yet different from Microsoft.Phone.Net.NetworkInformation.  Inside the MainPage() constructor, beneath InitializeComponent();, add the following code to create an event handler:

System.Net.NetworkInformation.NetworkChange.NetworkAddressChanged += new System.Net.NetworkInformation.NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);

This is the standard, cross-platform Silverlight way to create an event handler that tells you when your network address has changed.  I wrote it out the long-way because it collides with the phone-specific NetworkInformation class.  Don’t ask.

Underneath the line of code above, add the following:

NetworkStateMachine();

This is going to call a method you haven’t created yet.

Inside your MainPage class, the event handler your just created will appear:

void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
NetworkStateMachine();
}

As you can see, I want you to add the NetworkStateMachine(); line of code inside the event handler to execute this mysterious function.  By now you’re probably saying, “Enough of the suspense already!”  Below the event handler, paste in the following code:

private void NetworkStateMachine()
{
try
{
switch (NetworkInterface.NetworkInterfaceType)
{
//No Network
case NetworkInterfaceType.None:
ellipseNet.Fill = new SolidColorBrush(Colors.Red);
textBlockNet.Text = “No Network”;
break;
//CDMA Network
case NetworkInterfaceType.MobileBroadbandCdma:
ellipseNet.Fill = new SolidColorBrush(Colors.Blue);
textBlockNet.Text = “CDMA”;
break;
//GSM Network
case NetworkInterfaceType.MobileBroadbandGsm:
ellipseNet.Fill = new SolidColorBrush(Colors.Blue);
textBlockNet.Text = “GSM”;
break;
//Wi-Fi Network
case NetworkInterfaceType.Wireless80211:
ellipseNet.Fill = new SolidColorBrush(Colors.Green);
textBlockNet.Text = “Wi-Fi”;
break;
//Ethernet Network
case NetworkInterfaceType.Ethernet:
ellipseNet.Fill = new SolidColorBrush(Colors.Green);
textBlockNet.Text = “Ethernet”;
break;
//No Network
default:
ellipseNet.Fill = new SolidColorBrush(Colors.Red);
textBlockNet.Text = “No Network”;
break;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

The switch statement above creates a state machine for your mobile application that lets it know what type of network connection you have at any given moment.  Remember for this example, the sample code is running on the UI thread.  Since the code is synchronous and blocking, you may want to run it on a background thread.

As you can see, the following network types are returned:

  • Wireless80211  (Wi-Fi)
  • Ethernet  (Docked/LAN)
  • MobileBroadbandGSM  (GPRS/EDGE/UMTS/HSDPA/HSPA)
  • MobileBroadbandCDMA  (1xRTT/EV-DO)
  • None

As you’re probably thinking, the primary value in this is to know if you have any kind of network or not.  Obviously, a return value of None means you shouldn’t make any kind of Web Service call.

Hit F5 in Visual Studio and let’s see what you get in the emulator:

phone6

As you can see, the ContosoCloud app detected my laptop’s Wi-Fi connection in the switch statement and therefore gave me a Green Ellipse and a TextBlock that says “Wi-Fi.”  Keep in mind that the emulator doesn’t behave the same way as an actual phone so changing my laptop’s networking while the mobile app is running won’t trigger the NetworkChange_NetworkAddressChanged event handler.  If you close the app, turn off Wi-Fi on your laptop and then restart the app, it will correctly report that no network is available.

So why would you want to know about all the other network return types?

In working with customers all around the world who use Pocket PCs, Windows Mobile devices and Windows Phones, it has become evident that there is always a “cost” in doing anything over the network.  Not everyone has unlimited, “all-you-can-eat” data plans for their employees.  Some companies have very low monthly data usage limits for each employee that has been negotiated with one or more mobile operators.  For these organizations, it’s not enough to know if the network is present or not.  They need to know what kind of network is available so their mobile application can make intelligent decisions.

If I need to download a large amount of data in the morning to allow me to drive my delivery truck route, I probably should only perform this operation over docked Ethernet or Wi-Fi.  This gives me the network speed I need to move a lot of data and I don’t incur any costs with my mobile operator.

If I’ve captured small amounts of data in the field that I need to send back to HQ in near real-time, then a return value of MobileBroadbandGSM  or MobileBroadbandCDMA is perfect.  This would also be appropriate if my app is making lightweight remote method calls via Web Services as well.  The use of WCF REST + JSON is probably making a lot of sense now.

If I’ve captured large amounts of data in the field or I’m batching up several data captures throughout the day, it would make more sense to use Ethernet or Wi-Fi when I returned to the warehouse or distribution center.  On the other hand, if I have a high enough data usage limit or no limit at all, the MobileBroadbandGSM/CDMA would be fine.

Keep in mind that this guidance is just as valuable for B2C and Consumer apps as well.  If you’re building a connected mobile app of any kind, the information I’ve discussed in this article will ensure that you’re always providing a great user experience.

Delighting the end-user is what it’s all about!

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Working with an In-Memory Database

Phone3

In my last article of this series, you finally got to consume wireless-friendly WCF REST + JSON Services from both Windows Server and Windows Azure with data coming from SQL Server/SQL Azure.

You now have an ObservableCollection of Customer objects residing in a Singleton on your Windows Phone 7 device.  This Singleton looks similar to an in-memory database and the Customers property works like a table.

So now what?

If you’re like me, you probably want to display the list of Customers in the UI.  You might also want to perform other local operations against this data store.  You could add a new Customer and update or even delete an existing one.

I’m going to apologize in advance for not doing the MVVM thing that everyone seems to be into these days and get right to the point. Drag a button on to MainPage.xaml and call it View Customers.  While you’re at it, drag a listbox below the button and name it listBoxCustomers.  Double-click on this Button and add the following code to the click event:

try
{
if (Database.Instance.Customers != null)
{
listBoxCustomers.DisplayMemberPath = “Name”;
listBoxCustomers.ItemsSource = Database.Instance.Customers;
}
else
{
MessageBox.Show(“The Customer Table is Empty”);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

In the simple code above, you set the listbox’s ItemsSource equal to the Customer collection in the Database Singleton and set the DisplayMemberPath property equal to the Name property of the Customer objects.

Hit F5 to start debugging this Windows Phone 7 + Azure solution.  As usual, a web page and the emulator will launch.  Tap the Get Customers button to pull the Customer data back from the WCF REST service.  Next, tap on the View Customers button to display the list of Customers from the in-memory database as shown in the picture below:

phone1

Now it’s time to add a new Customer so drop a button underneath the listbox and call it Add Customer.  Creating a new Customer object requires setting values for 8 properties.  Instead of having you add 8 textboxes to type in the info, I’ll keep in simple and let you add it in code.  In the click event of the button, paste in the code you see below:

try
{
if (Database.Instance.Customers != null)
{
Customer customer = new Customer();
customer.CustomerId = 5;
customer.DistributionCenterId = 1;
customer.RouteId = 1;
customer.Name = “ABC Corp”;
customer.StreetAddress = “555 Market Street”;
customer.City = “Seattle”;
customer.StateProvince = “WA”;
customer.PostalCode = “98987”;
Database.Instance.Customers.Add(customer);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

After setting all the properties (Columns), you add the Customer object (Row) to the Customers property (Table), in the Singleton Database.  Hit F5, tap the Get Customers button, tap the View Customers button and then tap the Add Customer button.  Through the magic of simple data-binding, you should see the new “ABC Corp” show up in the listbox as shown below:

phone2

Now that you’ve added a new Customer, it’s time to update it because the president of the company decided to change the name.  Drag a new button and drop it underneath the Add Customer button.  Call it Update Customer and in it’s click event, paste in the following code:

try
{
if (Database.Instance.Customers != null)
{
foreach (Customer c in Database.Instance.Customers)
{
if (c.Equals((Customer)listBoxCustomers.SelectedItem))
{
c.Name = “XYZ Inc”;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

The code above loops through the Customers ObservableCollection until it finds a match for the item that’s been selected in the listbox.  When it finds that match, it updates the Name property to “XYZ Inc” which will automatically update what the user views in the listbox.

Hit F5, tap the Get Customers button, tap the View Customers button and then tap the Add Customer button.  Now tap on “ABC Corp” in the listbox to highlight it.  Clicking the Update Customer button will change it before your eyes.

phone3

It turns out that “XYZ Inc” went out of business because the president was an idiot so you need to delete it.  Guess what, you need yet another button beneath the Update Customer button.  Call it Delete Customer and in it’s click event, paste in the following code:

try
{
if (Database.Instance.Customers != null)
{
Database.Instance.Customers.Remove((Customer)listBoxCustomers.SelectedItem);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

In the code above, the Customer object that matches the item selected in the listbox is removed from the Customers ObservableCollection.  Pretty simple stuff in this case.

To find out for sure, hit F5, tap the Get Customers button, tap the View Customers button and then tap the Add Customer button.  Now tap on “ABC Corp” in the listbox to highlight it.  Clicking the Update Customer button will change it to “XYZ Inc.”  Highlighting “XYZ Inc” and clicking the Delete Customer button will cause this defunct company to disappear as shown below:

phone4

Now suppose you only want to display the Customers from Seattle and not the Eastside.  A little LINQ will do the trick here.  Drag and drop a new button called Seattle next to the Test Uri button and paste the following code in the click event:

if (Database.Instance.Customers != null)
{
IEnumerable<Customer> customers = from customer in Database.Instance.Customers
where customer.DistributionCenterId == 1
select customer;
listBoxCustomers.DisplayMemberPath = “Name”;
listBoxCustomers.ItemsSource = customers;
}
else
{
MessageBox.Show(“The Driver Table is Empty”);
}

In the code above, I set an IEnumerable<Customer> variable equal to the Customers table where the DistributionCenterId is equal to 1.  Since the DistributionCenter #1 serves the Seattle area, I know the listbox will be filled with just Adventure Works LLC and City Power & Light.  Start debugging and test it for yourself.

The last thing you need to do with local data is store it offline since you can’t always count on the network being there.  Luckily we’ve got Isolated Storage to serialize stuff.  In order to work with Isolated Storage, I need you to add using System.IO.IsolatedStorage; at the top of the class.  Since in this example I’ll demonstrate XML Serialization of the Customers ObservableCollection, I’ll need you to add a reference to System.Xml.Serialization and then add using System.Xml.Serialization; at the top of the class.  With that plumbing in place, let’s write some actual code.

Drag and drop another button called Save next to the Get Customers button and paste the following code in the click event:

if (Database.Instance.Customers != null)
{
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = store.CreateFile(“Customers.xml”))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Customer>));
serializer.Serialize(stream, Database.Instance.Customers);

        }
}
}

In the code above, you use the combination of IsolatedStorageFile and IsolatedStorageFileStream to write data to Isolated Storage.  In this case, you’re going to create an XML file to save the Customers ObservableCollection of Customer objects.  Remember back in the 80’s when databases used to save each table as an individual file?  I’m thinking of DBase III+, FoxPro, and Paradox at the moment.  Anyway, this is exactly what happens here using the power of the XmlSerializer.  Feel free to debug and step through the code to ensure that it executes without error.

To complete the picture, you need to be able to retrieve the Customers ObservableCollection from Isolated Storage and work with the data without ever having to call the WCF REST services.  Drag and drop one last button called Load next to the View Customers button and paste the following code in the click event:

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(“Customers.xml”))
{
using (IsolatedStorageFileStream stream = store.OpenFile(“Customers.xml”, System.IO.FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(ObservableCollection<Customer>));
Database.Instance.Customers = (ObservableCollection<Customer>)serializer.Deserialize(stream);
}
}
}

The code above does the reverse of the previous Save code by opening the Customers.xml and re-hydrating those objects back into the Customers table using the XmlSerializer.  This is pretty cool stuff.

To make it all real, hit F5 to start debugging this completed mobile project.  When the app loads, tap the Get Customers button to retrieve the data and then tap View Customers to verify that you can see the data.  Now I want you to tap the Save button to serialize the Customers to an XML file in Isolated Storage.  Lastly, I want you to tap on the Back button to close the application.

Hit F5 again to fire up the application.  This time, I don’t want you to retrieve the data from Azure.  Instead, I want you to tap the Load button to de-serialize the Customer objects from XML.  Now for the moment of truth.  Tap the View Customers button to see if you’re actually working with an offline database.  Hopefully, your app will look like the picture below:

phone5

Congratulations!  You’ve made it to the end of this series of articles on building an occasionally-connected Windows Phone 7 application that works with WCF REST + JSON Services in Windows Azure.  Furthermore, you’re now pulling data down from SQL Azure and you’re working with it locally using a simple in-memory database that you built yourself.  I’m hoping that you’ll now feel empowered to go build industrial-strength mobile solutions for your own company or your customers.

Keep coding!

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Consuming an Azure WCF REST + JSON Service

Windows Phone 7.5

In my last two articles, I showed you how to build WCF REST services using Visual Studio 2010 that can reside on-premise in Windows Server 2008 or in the Cloud in Windows Azure.  Furthermore, I demonstrated pulling data from a table in SQL Server/SQL Azure.  I serialized .NET Objects using lightweight JSON to speed data transfers over even the slowest wireless data networks.  Now it’s time to call that REST service from Windows Phone 7.

Launch VS2010 and open the solution you created to build the WCF Service Web Role in Azure last time.  Right-click on the solution and add a Windows Phone Application project.  Change the name to ContosoPhone.

WP71

Part of the magic of making all this work is to have both the Azure Development Fabric and the Windows Phone 7 project start when it comes time to debug.  Most developers are accustomed to only having a single startup project so let’s make sure you have everything we need running when you hit F5.  Right-click on the solution and select Properties.  Select Startup Project and then click on the Multiple startup projects radio button.  Set both the AzureRestService and ContosoPhone projects Action value to Start and click OK as shown below:

WP72

With the startup configuration complete, the next thing I want you to do is copy Customer.cs from the AzureRestService project to the new ContosoPhone project since you’ll need it to create local Customer objects when you retrieve the data from the WCF call.  In this new Customer class you’ll need to change the Namespace to ContosoPhone and remove using System.Web; at the top of the class.  In order to support the DataContract() and DataMember() attributes, you’ll need to add a reference to System.Runtime.Serialization in order to get it to compile.

Drag a Button on to your MainPage.xaml and call it Test.  Double-click on this Button and add the following WebClient code to the click event:

try
{
WebClient webClient = new WebClient();
Uri uri = new Uri(“
http://127.0.0.1:48632/service1.svc/getdata?number=8″);
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedTest);
webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

As you can see above, I create a WebClient and a Uri object that points to the local Url presented by the Azure Development Fabric.  The port number my be different on your machine so double-check.  This is the test REST service from the last article used to prove that you’re calls are making it through.  You’ve made this call with your web browser and Windows Phone 7 will call it the same way.  Since all calls are asynchronous and the WebClient above created an event handler, copy the following code into the MainPage class and make sure to add using System.IO; at the top:

void OpenReadCompletedTest(object sender, OpenReadCompletedEventArgs e)
{
try
{
StreamReader reader = new System.IO.StreamReader(e.Result);
MessageBox.Show(reader.ReadToEnd().ToString());
reader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

In the event handler above, I use the StreamReader to grab the entire XML return value.  The fact that I’m using WebClient means that callbacks are run on the UI thread thus relieving you of the need to use the dispatcher to update the UI.  This allows you to display the following XML string in the MessageBox:

<string xmlns=”http://schemas.microsoft.com/2003/10/Serialization/”>You entered: 8</string>

It’s time to try this thing out so hit F5.  If it compiles and everything executes properly, you should see both a web browser pointing to the root of your Azure services as well as your emulator and you can test your services with both.  Click the simple Test Button on your Silverlight MainPage and the MessageBox should pop up after the XML result is returned from Azure displaying the answer:

WP73

Click the Back button on the Emulator to close your app and close the web browser window to shut down Azure.

Now it’s time to do something a little more ambitious like return the JSON-encoded list of Customers from SQL Azure.  Unlike most books and articles on Silverlight and RIA Services that you may have read, I’m not going to return this data and immediately data-bind it to a control.  As a long-time mobile and wireless guy that understands intermittent connectivity and the importance of an offline data store, I’m going to have you put this data in a local database first.  Since SQL Server Compact is nowhere to be found and I don’t want you going off and using a 3rd party or open source embedded database, I’m going to show you how to create a simple one of your own.

Right-click on your ContosoPhone project and select Add | Class.  Name this new class Database.

WP74

You’re going to turn this class into a Singleton to create an in-memory database which will ensure that only instance is available.  For simplicity’s sake, just copy the code below into the new Database class:

using System;
using System.Net;
using System.Windows;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace ContosoPhone
{
sealed class Database
{
//Declare Instance
private static readonly Database instance = new Database();

        //Private Constructor
private Database() { }

        //The entry point into this Database
public static Database Instance
{
get
{
return instance;
}
}

        //Declare Private Variables
private ObservableCollection<Customer> customerTable = null;

        //Customer Table
public ObservableCollection<Customer> Customers
{
get { return customerTable; }
set { customerTable = value; }
}
}
}

As you can see above, I’ve had you create a sealed class with a private, static, readonly constructor as an entry point following a popular .NET method of implementing a Singleton.  The big thing here is the Customers property of type ObservableCollection<Customer>.  Since each Customer object is a Row with properties that are Columns, then it’s easy to think of this ObservableCollection of these Customer objects as a Table.  You now have the beginnings of a simple, in-memory database with which to store all the Customer objects when they arrive from the Cloud.

Start out by dragging another button on to MainPage.xaml and calling it Get Customers.  Double-click on this Button and add the following WebClient code to the click event:

try
{
WebClient webClient = new WebClient();
Uri uri = new Uri(“
http://127.0.0.1:48632/service1.svc/customers”);
    webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenReadCompletedCustomers);
webClient.OpenReadAsync(uri);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

You’ll notice that it looks almost identical to the previous WebClient call except this time you’re just adding /customers to the end of service1.svc.  The beauty of the UriTemplate is that Microsoft makes it just that easy to call a REST service from WCF.  Since the above code created an event handler, paste this following code into the MainPage class to handle the callback:

void OpenReadCompletedCustomers(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;

    try
{
ser = new DataContractJsonSerializer(typeof(ObservableCollection<Customer>));
Database.Instance.Customers = ser.ReadObject(e.Result) as ObservableCollection<Customer>;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

You’ll immediately see a bunch of squiggly lines telling you something is missing.  Add a reference to System.Servicemodel.Web and then add using System.Runtime.Serialization.Json; at the top in order to fix the problems with DataContractJsonSerializer.  Next add using System.Collections.ObjectModel; at the top to fix the ObservableCollection squigglies.  Give your solution a quick Rebuild to ensure that everything compiles.

In analyzing the new code I just had you add, you’ll notice the use of DataContractJsonSerializer which in this case is used to de-serialize JSON-encoded Customer objects that are downloading over the air.  It does this by casting them as ObservableCollection<Customer> which works because I had you copy that class from the AzureRestService project.  In a world of right-clicking to add a Service/Web Reference to consume SOAP web services, you never had to know what was going on under the covers to create an easy to use proxy.  You also never saw Visual Studio create hidden classes that looked just like the ones found on the server side so your client would have something to work with and so that intellisense worked.

The last important line of code you see is setting the Customers table of your in-memory database equal to the de-serialization of the OpenReadCompletedEventArgs.  I think we’re ready to try out this code.  If all goes well, you’ll have a bunch of downloaded Customer data stored in an in-memory database on Windows Phone 7.

Set a breakpoint at the declaration of the DataContractJsonSerializer, hit F5, and click the Get Customers button!

WP75

Success looks like the picture above!  I hovered my mouse over Database.Instance.Customers and revealed that I was now storing Customers with Cities, CustomerId’s, PostalCodes, RouteId’s and StateProvinces for all to see in Visual Studio’s amazing debugger.

You are now consuming wireless-friendly WCF REST + JSON Services from both Windows Server and Windows Azure with data coming from SQL Server/SQL Azure.  Windows Phone 7 is connected to tiny, fast, efficient services designed to thrive in unreliable/slow wireless coverage.  You now know how to serialize/de-serialize .NET objects as JSON and you’ve also created your own in-memory database.

So what’s next?  In my next article, I’ll show you how to query this new in-memory database using LINQ and I’ll show you how to save the data in your local tables to Isolated Storage so you can keep using your apps even when the network has disappeared.

Keep coding and I’ll see everyone at Tech Ed in Berlin!

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Ray Ozzie sees the Dawn of a New Day for Microsoft

Ray Ozzie

Five years after Ray Ozzie penned The Internet Services Disruption, he reflects on Microsoft’s move to the cloud.

While he’s most proud of Windows Azure and SQL Azure, he also gives our competitors their due by mentioning that they have out-executed us when it comes to mobile experiences.  He harps on the subject of how complexity kills and then challenges us to close our eyes and form a realistic picture of what a post-PC world might actually look like.

rayozzie

Ray goes on to state that those who can envision a plausible future that’s brighter than today will earn the opportunity to lead.  His ultimate dream is to move us toward a world of :

  • Cloud-based continuous services that connect us all and do our bidding.  These are websites and cloud-based agents that we can rely on for more and more of what we do.  On the back end, they possess attributes enabled by our newfound world of cloud computing: They’re always-available and are capable of unbounded scale.
  • Appliance-like connected devices enabling us to interact with those cloud-based services.  This goes beyond the PC and will increasingly come in a breathtaking number of shapes and sizes, tuned for a broad variety of communications, creation & consumption tasks.  Each individual will interact with a fairly good number of these connected devices on a daily basis – their phone / internet companion; their car; a shared public display in the conference room, living room, or hallway wall.

As a Mobility Architect at Microsoft, I’m excited that my commitments align with this vision in connecting the Peanut Butter of the Cloud with the Chocolate of devices.  Wireless data networks, bandwidth, latency and signal coverage are the wildcards when it comes to making this vision a reality.  That’s why you’ll always see my concern for this Wireless wildcard reveal itself in all the Cloud-connected mobile architectures I design.

Check out the rest of Ray’s new memo at http://ozzie.net/docs/dawn-of-a-new-day/.

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Moving your WCF REST + JSON Service to Windows Azure

Azure2

Ever since my last blog post where I demonstrated how to create lightweight WCF REST + JSON services for consumption by Windows Phone 7, I’ve received many requests from folks wanting to know how to do the same thing from Windows Azure.  Using Visual Studio 2010, the Azure Development Fabric and SQL Server, I will show you how to move this code to the cloud.

Fire up VS2010 and create a new cloud project (you’ll be prompted to download all the Azure bits if you haven’t done so already).

Azure1

Select WCF Service Web Role and move it over to your Cloud Service Solution.  Rename it to AzureRestService and click OK.

Azure2

You’ll then be presented with the default Service1.svc.cs SOAP web service that implements the IService1.cs Interface.  Needless to say, you’ll need to makes some modifications to these two files as well as Web.config if you want to be a true RESTafarian.

Azure3

In Service1.svc.cs, delete the GetDataUsingDataContract method but leave the GetData method since you’ll use it to perform an initial test.

Next, open IService1.cs and delete the GetDataUsingDataContract [OperationContract] as well as the CompositeType [DataContract].  You should be left with the simple GetData [OperationContract].

Open Web.config.  You’ll notice that it’s already pretty full of configuration items.  After the closing </serviceBehaviors> tag, tap on your Enter key a few times to give you some room to insert some new stuff.  Insert the following just below the closing </serviceBehaviors> tag and just above the closing </behaviors> tag as shown:

         <endpointBehaviors>
<behavior name=”REST”>
<webHttp />
</behavior>
</endpointBehaviors>

This provides you with the all-important webHttp behavior that enables lean REST calls using HTTP Verbs.

Below the closing </behaviors> tag and above <serviceHostingEnvironment multipleSiteBindingsEnabled=”true” />, insert the following as shown:

<services>
<service name=”AzureRestService.Service1″>
<endpoint address=”” behaviorConfiguration=”REST” binding=”webHttpBinding” contract=”AzureRestService.IService1″ />
</service>
</services>

Here is where we define our service name and contract.  It’s also where we point our behaviorConfiguration at the webHttp behavior you named “REST” and set the binding to webHttpBinding.

Now it’s time to decorate your interface’s [OperationContract] with a WebGet attribute and utilize a UriTemplate to give the Windows Phone 7 caller a web-friendly Uri to call.  So beneath [OperationContract] and above string GetData(int value);, squeeze in the following:

[WebGet(UriTemplate = “/getdata?number={value}”, BodyStyle = WebMessageBodyStyle.Bare)]

Since we want to call the GetData method via a GET request, we use WebGet and then we set our UriTemplate to something that anyone could access via their browser.  Lastly, we strip out all unnecessary junk by setting WebMessageBodyStyle.Bare.

It’s convenient that I mentioned using a browser to access this new REST service because that’s exactly how we’re going to test it.  Hit F5 in Visual Studio to fire up the Azure Development Fabric and start your Web Role.  Internet Explorer will come up and you’ll probably see an Error page because it points to the Root of your Role Site.  This is expected behavior.  In order to test the service, type the following in the IE address bar:

http://127.0.0.1:81/service1.svc/getdata?number=5

This points to a loopback address on your computer with a port number of 81.  If your environment uses a different port, then just change what you pasted in as appropriate.  After the port number and “/”, you type in the name of the service you created which is service1.svc.  After the next “/”, you type the format you described in the UriTemplate.  You can type any Integer you wish and if everything works, the browser will display the following result:

    <string xmlns=”http://schemas.microsoft.com/2003/10/Serialization/”>You entered: 5</string>

With your test REST service working from your local Azure Development Fabric, it’s time to bring over the business logic from my last blog post where I showed you how to return Customer information from an on-premise WCF Service connected to SQL Server.  I don’t necessarily expect you to have a SQL Azure account so you’ll add a connection string to Web.config that points to a local SQL Server Express instance.  Don’t worry, you can swap this connection string out later to point to our awesome cloud database.  Beneath the closing </system.web> tag and above the <system.serviceModel> tag, insert the following:

<connectionStrings>
<add name=”ContosoBottlingConnectionString” connectionString=”Data Source=RTIFFANY2\SQLEXPRESS;Initial Catalog=ContosoBottling;Integrated Security=True” providerName=”System.Data.SqlClient” />
</connectionStrings>

This is the same connection string from the last blog post and you’ll definitely need to modify it to work with both your local SQL Server instance and SQL Azure when you’re ready to deploy.  Bear with me as the rest of this blog post will be a large Copy and Paste effort.

Open IService1.cs and add the following:

using System.Collections.ObjectModel;

and

[OperationContract]
[WebGet(UriTemplate = “/Customers”, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
ObservableCollection<Customer> GetCustomers();

Open Service1.svc.cs and add the following:

using System.Web.Configuration;
using System.Collections.ObjectModel;
using System.Data.SqlClient;

 

and

//Get the Database Connection string
private string _connectionString = WebConfigurationManager.ConnectionStrings[“ContosoBottlingConnectionString”].ConnectionString;

and

public ObservableCollection<Customer> GetCustomers()
{
SqlConnection _cn = new SqlConnection(_connectionString);
SqlCommand _cmd = new SqlCommand();
_cmd.CommandText = “SELECT CustomerId, DistributionCenterId, RouteId, Name, StreetAddress, City, StateProvince, PostalCode FROM Customer”;

    try
{
_cn.Open();
_cmd.Connection = _cn;

        ObservableCollection<Customer> _customerList = new ObservableCollection<Customer>();

        SqlDataReader _dr = _cmd.ExecuteReader();
while (_dr.Read())
{
Customer _customer = new Customer();
_customer.CustomerId = Convert.ToInt32(_dr[“CustomerId”]);
_customer.DistributionCenterId = Convert.ToInt32(_dr[“DistributionCenterId”]);
_customer.RouteId = Convert.ToInt32(_dr[“RouteId”]);
_customer.Name = Convert.ToString(_dr[“Name”]);
_customer.StreetAddress = Convert.ToString(_dr[“StreetAddress”]);
_customer.City = Convert.ToString(_dr[“City”]);
_customer.StateProvince = Convert.ToString(_dr[“StateProvince”]);
_customer.PostalCode = Convert.ToString(_dr[“PostalCode”]);

            //Add to List
_customerList.Add(_customer);
}
return _customerList;
}
finally
{
_cmd.Dispose();
_cn.Close();
}
}

As you can see, the only remaining error squigglies refer to the lack of the Customer class I discussed in the on-premise WCF project from the last blog post.  To add it, I want you to right-click on your AzureRestService project and select Add | Class and name the class Customer.

Azure4

Now I want you to paste the code below into this new class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace AzureRestService
{
[DataContract()]
public class Customer : INotifyPropertyChanged
{
public Customer() { }

        private int customerId;
private int distributionCenterId;
private int routeId;
private string name;
private string streetAddress;
private string city;
private string stateProvince;
private string postalCode;

        [DataMember()]
public int CustomerId
{
get { return customerId; }
set
{
customerId = value;
NotifyPropertyChanged(“CustomerId”);
}
}

        [DataMember()]
public int DistributionCenterId
{
get { return distributionCenterId; }
set
{
distributionCenterId = value;
NotifyPropertyChanged(“DistributionCenterId”);
}
}

        [DataMember()]
public int RouteId
{
get { return routeId; }
set
{
routeId = value;
NotifyPropertyChanged(“RouteId”);
}
}

        [DataMember()]
public string Name
{
get { return name; }
set
{
name = value;
NotifyPropertyChanged(“Name”);
}
}

        [DataMember()]
public string StreetAddress
{
get { return streetAddress; }
set
{
streetAddress = value;
NotifyPropertyChanged(“StreetAddress”);
}
}

        [DataMember()]
public string City
{
get { return city; }
set
{
city = value;
NotifyPropertyChanged(“City”);
}
}

        [DataMember()]
public string StateProvince
{
get { return stateProvince; }
set
{
stateProvince = value;
NotifyPropertyChanged(“StateProvince”);
}
}

        [DataMember()]
public string PostalCode
{
get { return postalCode; }
set
{
postalCode = value;
NotifyPropertyChanged(“PostalCode”);
}
}

        public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

    }
}

As I mentioned in the last article, this class is a little overkill since it inherits from INotifyPropertyChanged and adds all the code associated with firing NotifyPropertyChanged events.  I only do this because you will use this same class in your Windows Phone 7 project to support two-way data binding.

The Customer table you’ll be pulling data from is shown in SQL Server Management Studio below:

Azure5

We’re now ready to roll so hit F5 in Visual Studio to debug this new cloud solution in the Azure Development Fabric.  When Internet Explorer comes up, type the following in the IE address bar:

            http://127.0.0.1:81/service1.svc/customers

You might be surprised to see the following dialog pop up instead of XML rendered in the browser:

Azure6

The reason you see this is because you’re returning the data objects in wireless-friendly JSON format.  Notice that the dialog say the Unknown file type is only 671 bytes.  This is a good thing.  Click the Save button and save this file to your desktop.

Now find the customer file on your desktop and rename it to customer.txt so you can view it in Notepad.  Double-click on this text box to reveal the tiny, JSON-encoded data in Notepad that you just looked at in the previous SQL Server Management Studio picture.

Azure7

Conclusion

If you followed me through this example and all the code executed properly, you now know how to build Windows Azure REST + JSON services designed to conquer those slow, unreliable, and highly-latent wireless data networks we all deal with all over the world.  When combined with my last article, both your on-premise and Windows Azure bases are covered with WCF.  The only thing left to do is sign up for an Windows Azure Platform account and move this Web Role and SQL Azure database to cloud.  In my next article, I’ll show you how to use the WebClient object from Silverlight in Windows Phone 7 to call these services.

Keep coding,

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Windows Phone 7 Line of Business App Dev :: Building a WCF REST + JSON Service

Visual Studio

Let’s start at the server and work our way to the phone.  Anyone who knows me is probably aware that I come from a wireless background so I’m always obsessed with things like coverage, bandwidth and latency when it comes to building mobile systems.  The only thing I assume in mobile development is frequent network dropouts and 28.8 kb/s modem speeds.  Think Compuserve.  For device apps to be successful, they must pre-fetch the data they need and cache it offline so a user can keep working when the network is not around.  This is not typical SOA, calling Web Services on-demand to help drive your application.  If your connectivity is that perfect, then build a mobile web site.  Additionally, they must first save captured data locally and only try to upload it to the server when network connectivity is available.  Never get caught in the trap of assuming ubiquitous network availability.

Networking + Wire Protocols

If you’ve looked at the Networking in Silverlight for Windows Phone 7 documentation on MSDN, you might have noticed that a number of things are missing:

  • WCF RIA Services
  • WCF Data Services (OData)
  • Duplex Communication over HTTP
  • Sockets
  • UDP Multicast Client
  • NTLM Auth
  • RSS/ATOM Feeds
  • Custom Bindings
  • JSON Serialization

I decided to focus on the networking capabilities that did work out of the box so that I could continue to build large-scale mobile/wireless solutions for our customers.  We’ve got SOAP and REST + Basic Authentication.  That’s right, you can add a Service Reference to an ASMX or WCF Web Service and you can pass your credentials to IIS with Basic Auth as long as you remember to wrap that clear text with SSL.  What I’m truly interested in is using the smallest, most efficient wire protocol possible to traverse all those unreliable wireless networks.  I’ve looked at various ways to do something simple like return a short list of Customers to a Windows Phone 7 device.  Some wire protocols are more efficient than others.  For instance:

  • An OData list of just 8 Customers from a WCF Data Service was extremely verbose and weighed in at a whopping 8.5 kb.  Yikes!

<?xml version=”1.0″ encoding=”utf-8″ standalone=”yes” ?>
– <feed xml:base=”
http://localhost:33779/WcfDataService1.svc/” xmlns:d=”http://schemas.microsoft.com/ado/2007/08/dataservices” xmlns:m=”http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” xmlns=”http://www.w3.org/2005/Atom”>
<title type=”text”>Drivers</title>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers</id>
<updated>2010-05-24T22:12:38Z</updated>
<link rel=”self” title=”Drivers” href=”Drivers” />
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(1)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(1)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(1)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(1)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>1</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>1</d:DistributionCenterId>
<d:FirstName>Rob</d:FirstName>
<d:LastName>Tiffany</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(2)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(2)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(2)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(2)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>2</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>1</d:DistributionCenterId>
<d:FirstName>Loke Uei</d:FirstName>
<d:LastName>Tan</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(3)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(3)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(3)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(3)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>3</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>1</d:DistributionCenterId>
<d:FirstName>Dan</d:FirstName>
<d:LastName>Bouie</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(4)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(4)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(4)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(4)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>4</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>1</d:DistributionCenterId>
<d:FirstName>John</d:FirstName>
<d:LastName>Dietz</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(5)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(5)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(5)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(5)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>5</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>2</d:DistributionCenterId>
<d:FirstName>Derek</d:FirstName>
<d:LastName>Snyder</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(6)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(6)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(6)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(6)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>6</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>2</d:DistributionCenterId>
<d:FirstName>Steve</d:FirstName>
<d:LastName>Hegenderfer</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(7)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(7)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(7)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(7)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>7</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>2</d:DistributionCenterId>
<d:FirstName>Chip</d:FirstName>
<d:LastName>Vollers</d:LastName>
</m:properties>
</content>
</entry>
– <entry>
<id>
http://localhost:33779/WcfDataService1.svc/Drivers(8)</id>
<title type=”text” />
<updated>2010-05-24T22:12:38Z</updated>
– <author>
<name />
</author>
<link rel=”edit” title=”Driver” href=”Drivers(8)” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DistributionCenter” type=”application/atom+xml;type=entry” title=”DistributionCenter” href=”Drivers(8)/DistributionCenter” />
<link rel=”
http://schemas.microsoft.com/ado/2007/08/dataservices/related/Todays” type=”application/atom+xml;type=feed” title=”Todays” href=”Drivers(8)/Todays” />
<category term=”ContosoBottlingModel.Driver” scheme=”
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme” />
– <content type=”application/xml”>
– <m:properties>
<d:DriverId m:type=”Edm.Int32″>8</d:DriverId>
<d:DistributionCenterId m:type=”Edm.Int32″>2</d:DistributionCenterId>
<d:FirstName>James</d:FirstName>
<d:LastName>Pratt</d:LastName>
</m:properties>
</content>
</entry>
</feed>

  • The same list of 8 Customers using SOAP and a DataSet dropped us down to 3 kb but still too big for my taste.

<?xml version=”1.0″ encoding=”utf-8″?>
<DataSet xmlns=”
http://tempuri.org/”>
<xs:schema id=”NewDataSet” xmlns=”” xmlns:xs=”
http://www.w3.org/2001/XMLSchema” xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata”>
<xs:element name=”NewDataSet” msdata:IsDataSet=”true” msdata:UseCurrentLocale=”true”>
<xs:complexType>
<xs:choice minOccurs=”0″ maxOccurs=”unbounded”>
<xs:element name=”Driver”>
<xs:complexType>
<xs:sequence>
<xs:element name=”DriverId” type=”xs:int” minOccurs=”0″ />
<xs:element name=”DistributionCenterId” type=”xs:int” minOccurs=”0″ />
<xs:element name=”FirstName” type=”xs:string” minOccurs=”0″ />
<xs:element name=”LastName” type=”xs:string” minOccurs=”0″ />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<diffgr:diffgram xmlns:msdata=”urn:schemas-microsoft-com:xml-msdata” xmlns:diffgr=”urn:schemas-microsoft-com:xml-diffgram-v1″>
<NewDataSet xmlns=””>
<Driver diffgr:id=”Driver1″ msdata:rowOrder=”0″>
<DriverId>1</DriverId>
<DistributionCenterId>1</DistributionCenterId>
<FirstName>Rob</FirstName>
<LastName>Tiffany</LastName>
</Driver>
<Driver diffgr:id=”Driver2″ msdata:rowOrder=”1″>
<DriverId>2</DriverId>
<DistributionCenterId>1</DistributionCenterId>
<FirstName>Loke Uei</FirstName>
<LastName>Tan</LastName>
</Driver>
<Driver diffgr:id=”Driver3″ msdata:rowOrder=”2″>
<DriverId>3</DriverId>
<DistributionCenterId>1</DistributionCenterId>
<FirstName>Dan</FirstName>
<LastName>Bouie</LastName>
</Driver>
<Driver diffgr:id=”Driver4″ msdata:rowOrder=”3″>
<DriverId>4</DriverId>
<DistributionCenterId>1</DistributionCenterId>
<FirstName>John</FirstName>
<LastName>Dietz</LastName>
</Driver>
<Driver diffgr:id=”Driver5″ msdata:rowOrder=”4″>
<DriverId>5</DriverId>
<DistributionCenterId>2</DistributionCenterId>
<FirstName>Derek</FirstName>
<LastName>Snyder</LastName>
</Driver>
<Driver diffgr:id=”Driver6″ msdata:rowOrder=”5″>
<DriverId>6</DriverId>
<DistributionCenterId>2</DistributionCenterId>
<FirstName>Steve</FirstName>
<LastName>Hegenderfer</LastName>
</Driver>
<Driver diffgr:id=”Driver7″ msdata:rowOrder=”6″>
<DriverId>7</DriverId>
<DistributionCenterId>2</DistributionCenterId>
<FirstName>Chip</FirstName>
<LastName>Vollers</LastName>
</Driver>
<Driver diffgr:id=”Driver8″ msdata:rowOrder=”7″>
<DriverId>8</DriverId>
<DistributionCenterId>2</DistributionCenterId>
<FirstName>James</FirstName>
<LastName>Pratt</LastName>
</Driver>
</NewDataSet>
</diffgr:diffgram>
</DataSet>

  • Switching to REST + XML dropped us to a much leaner 1.2 kb.

<ArrayOfDriver xmlns=http://schemas.datacontract.org/2004/07/ContosoWcfService.Models

xmlns:i=”http://www.w3.org/2001/XMLSchema-instance”>
<Driver>
<DistributionCenterId>1</DistributionCenterId>
<DriverId>1</DriverId>
<FirstName>Rob</FirstName>
<LastName>Tiffany</LastName>
</Driver>
<Driver>
<DistributionCenterId>1</DistributionCenterId>
<DriverId>2</DriverId>
<FirstName>Loke Uei</FirstName>
<LastName>Tan</LastName>
</Driver>
<Driver>
<DistributionCenterId>1</DistributionCenterId>
<DriverId>3</DriverId>
<FirstName>Dan</FirstName>
<LastName>Bouie</LastName>
</Driver>
<Driver>
<DistributionCenterId>1</DistributionCenterId>
<DriverId>4</DriverId>
<FirstName>John</FirstName>
<LastName>Dietz</LastName>
</Driver>
<Driver>
<DistributionCenterId>2</DistributionCenterId>
<DriverId>5</DriverId>
<FirstName>Derek</FirstName>
<LastName>Snyder</LastName>
</Driver>
<Driver>
<DistributionCenterId>2</DistributionCenterId>
<DriverId>6</DriverId>
<FirstName>Steve</FirstName>
<LastName>Hegenderfer</LastName>
</Driver>
<Driver>
<DistributionCenterId>2</DistributionCenterId>
<DriverId>7</DriverId>
<FirstName>Chip</FirstName>
<LastName>Vollers</LastName>
</Driver>
<Driver>
<DistributionCenterId>2</DistributionCenterId>
<DriverId>8</DriverId>
<FirstName>James</FirstName>
<LastName>Pratt</LastName>
</Driver>
</ArrayOfDriver>

  • Switching my REST service encoding from XML to JSON to us down to a mere 639 bytes.
    • [{“DistributionCenterId”:1,”DriverId”:1,”FirstName”:”Rob”,”LastName”:”Tiffany”},{“DistributionCenterId”:1,”DriverId”:2,”FirstName”:”Loke Uei”,”LastName”:”Tan”},{“DistributionCenterId”:1,”DriverId”:3,”FirstName”:”Dan”,”LastName”:”Bouie”},{“DistributionCenterId”:1,”DriverId”:4,”FirstName”:”John”,”LastName”:”Dietz”},{“DistributionCenterId”:2,”DriverId”:5,”FirstName”:”Derek”,”LastName”:”Snyder”},{“DistributionCenterId”:2,”DriverId”:6,”FirstName”:”Steve”,”LastName”:”Hegenderfer”},{“DistributionCenterId”:2,”DriverId”:7,”FirstName”:”Chip”,”LastName”:”Vollers”},{“DistributionCenterId”:2,”DriverId”:8,”FirstName”:”James”,”LastName”:”Pratt”}]

 

Based on the title of this article, it’s probably obvious that I decided to go with REST + JSON because my customers care about speed, efficiency and reduced data costs.  I know I said JSON Serialization isn’t supported out of the box but that’s only partially true since you get the DataContractJsonSerializer to work with WCF objects encoded with JSON.  In this article, I’m going to walk you through the WCF project I built in Visual Studio 2010 so let’s get started.

Models

Since we won’t be generating a client-side proxy for your phone via adding a Service Reference or using slsvcutil.exe, then you can’t count on getting auto-generated Model objects.  This means you actually get to write some more code and build them yourself.  The Models you build on the server for your WCF Service will be the same one’s you copy to your Windows Phone 7 project so you’re client code will know what to do with them when they arrive. In order to ensure that your class and it’s properties are properly serialized for transport over the air, don’t forget to use the DataContract() and DataMember() attributes to make the magic happen.  Since I want my models to be Silverlight-friendly when it comes to data binding, I implement the INotifyPropertyChanged Interface.  While this may not seem important for the business entities you’re creating on the server, your Silverlight client needs this so I’m doing it now since I will be copying these same classes to my Windows Phone 7 project later.  The net of all this is that you add a PropertyChangedEventHandler to each class and you fire that event in each property’s setter.  This facilitates new or changed data in a bound control to update the model automatically.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace ContosoWcfService.Models
{
[DataContract()]
public class Customer : INotifyPropertyChanged
{
public Customer() { }

        private int customerId;
private int distributionCenterId;
private int routeId;
private string name;
private string streetAddress;
private string city;
private string stateProvince;
private string postalCode;

        [DataMember()]
public int CustomerId
{
get { return customerId; }
set
{
customerId = value;
NotifyPropertyChanged(“CustomerId”);
}
}

        [DataMember()]
public int DistributionCenterId
{
get { return distributionCenterId; }
set
{
distributionCenterId = value;
NotifyPropertyChanged(“DistributionCenterId”);
}
}

        [DataMember()]
public int RouteId
{
get { return routeId; }
set
{
routeId = value;
NotifyPropertyChanged(“RouteId”);
}
}

        [DataMember()]
public string Name
{
get { return name; }
set
{
name = value;
NotifyPropertyChanged(“Name”);
}
}

        [DataMember()]
public string StreetAddress
{
get { return streetAddress; }
set
{
streetAddress = value;
NotifyPropertyChanged(“StreetAddress”);
}
}

        [DataMember()]
public string City
{
get { return city; }
set
{
city = value;
NotifyPropertyChanged(“City”);
}
}

        [DataMember()]
public string StateProvince
{
get { return stateProvince; }
set
{
stateProvince = value;
NotifyPropertyChanged(“StateProvince”);
}
}

        [DataMember()]
public string PostalCode
{
get { return postalCode; }
set
{
postalCode = value;
NotifyPropertyChanged(“PostalCode”);
}
}

        public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (null != PropertyChanged)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

    }
}

Contract

In WCF, it’s all about contract-first development so you have to start out with a public Interface.  This is your Service Contract that exposes one or more Operation Contracts.  Since we’re going with REST, and I’m retrieving data, this means I’m going to use a GET request.  The WebGet attribute allows me to specify this easily.  Had I been Inserting, Updating or Deleting data, the WebInvoke attribute would’ve helped me with my POST, PUT or DELETE.  Next up is the use of the UriTemplate.  This allows me to point to REST/SEO friendly URIs to perform my operations rather than calling web methods that are buried inside a single URI.  In this case, I just want to retrieve a list of Customers so I set the UriTemplate = “/Customers.”  Since we’re trying to avoid the kind of extra baggage you get with SOAP, I set the BodyStyle == Bare which prevents extra XML wrapping of our parameters and return values.  For my ResponseFormat property, I set the WebMessageFormat to Json instead of XML in order to send the absolute minimum amount of data over the air.  Last but not least, I finish things up with my GetCustomers() method that returns an ObservableCollection of Customer objects to the Windows Phone 7 client.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using ContosoWcfService.Models;
using System.Collections.ObjectModel;

namespace ContosoWcfService
{
[ServiceContract]
public interface IRestData
{
[OperationContract]
[WebGet(UriTemplate = “/Customers”, BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
ObservableCollection<Customer> GetCustomers();

    }

}

Service Code

Now it’s time to implement my IRestData Interface with the RestData class.  Inside this class, I have my GetCustomers() method which connects to SQL Server, retrieves a list of Customers and sends it back to Windows Phone 7.  As you can see in the code below, I’m not using the Entity Framework but rather I’m just querying SQL Server directly.  Normally, I would call a stored procedure for even better performance but for clarity I’m showing the actual SELECT statement.  The key to this method is how I create new Customer objects and hydrate them with data as I loop through the SqlDataReader.  I then add them to the ObservableCollection which gets returned to the phone with wireless-friendly JSON encoding.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

using ContosoWcfService.Models;
using System.Data.SqlClient;
using System.Web.Configuration;
using System.Collections.ObjectModel;

namespace ContosoWcfService
{
public class RestData : IRestData
{
//Get the Database Connection string
private string _connectionString = WebConfigurationManager.ConnectionStrings[“ContosoBottlingConnectionString”].ConnectionString;

        public ObservableCollection<Customer> GetCustomers()
{
SqlConnection _cn = new SqlConnection(_connectionString);
SqlCommand _cmd = new SqlCommand();
_cmd.CommandText = “SELECT CustomerId, DistributionCenterId, RouteId, Name, StreetAddress, City, StateProvince, PostalCode FROM Customer”;

            try
{
_cn.Open();
_cmd.Connection = _cn;

                ObservableCollection<Customer> _customerList = new ObservableCollection<Customer>();

                SqlDataReader _dr = _cmd.ExecuteReader();
while (_dr.Read())
{
Customer _customer = new Customer();
_customer.CustomerId = Convert.ToInt32(_dr[“CustomerId”]);
_customer.DistributionCenterId = Convert.ToInt32(_dr[“DistributionCenterId”]);
_customer.RouteId = Convert.ToInt32(_dr[“RouteId”]);
_customer.Name = Convert.ToString(_dr[“Name”]);
_customer.StreetAddress = Convert.ToString(_dr[“StreetAddress”]);
_customer.City = Convert.ToString(_dr[“City”]);
_customer.StateProvince = Convert.ToString(_dr[“StateProvince”]);
_customer.PostalCode = Convert.ToString(_dr[“PostalCode”]);

                    //Add to List
_customerList.Add(_customer);
}
return _customerList;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
_cmd.Dispose();
_cn.Close();
}
}

Web.config

A WCF Service just wouldn’t be complete without a Web.config file.  The big takeway here is I’m storing my connection string to SQL Server and I’ve created a webHttp endpoint behavior for my REST services.  Down in my service name I point to my endpoint behavior, set my binding == webHttpBinding, and set my contract == IRestData.

<?xml version=”1.0″ encoding=”UTF-8″?>
<configuration>

  <system.web>
<compilation debug=”true” targetFramework=”4.0″ />
</system.web>

  <connectionStrings>
<add name=”ContosoBottlingConnectionString” connectionString=”Data Source=RTIFFANY3\SQLEXPRESS;Initial Catalog=ContosoBottling;Integrated Security=True” providerName=”System.Data.SqlClient” />
</connectionStrings>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled=”true” />
<!– To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults=”true” />
</behavior>
</serviceBehaviors>

      <endpointBehaviors>
<behavior name=”REST”>
<webHttp />
</behavior>

        <behavior name=”HelpBehavior”>
<webHttp helpEnabled=”true” />
</behavior>

      </endpointBehaviors>

    </behaviors>
<services>
<service name=”ContosoWcfService.RestData”>
<endpoint address=”” behaviorConfiguration=”REST” binding=”webHttpBinding” contract=”ContosoWcfService.IRestData” />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled=”true” />

  </system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true” />
<directoryBrowse enabled=”true” />
</system.webServer>
</configuration>

Conclusion

I hope this helps get you started down the road to building wireless bandwidth efficient WCF Services with REST and JSON.  Keep in mind that you can build these same types of services in Windows Azure as well along with connections to SQL Azure.  In the next article, I’ll show you how to consume these types of services from your Windows Phone 7 project

Keep coding,

Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]

Microsoft by the Numbers

Microsoft

With Microsoft Windows 7 selling more than 600,000 per day, it’s interesting to look at all our numbers and see how they stack up against the competition:

150,000,000
Number of Windows 7 licenses sold, making Windows 7 by far the fastest growing operating system in history.[source]


7.1 million
Projected iPad sales for 2010. [source]

58 million
Projected netbook sales in 2010. [source]

355 million
Projected PC sales in 2010. [source]


<10
Percentage of US netbooks running Windows in 2008. [source]

96
Percentage of US netbooks running Windows in 2009. [source]


0
Number of paying customers running on Windows Azure in November 2009.

10,000
Number of paying customers running on Windows Azure in June 2010. [source]

700,000
Number of students, teachers and staff using Microsoft’s cloud productivity tools in Kentucky public schools, the largest cloud deployment in the US.[source]


16 million
Total subscribers to largest 25 US daily newspapers. [source]

14 Million
Total number of Netflix subscribers. [source]

23 million
Total number of Xbox Live subscribers. [source]


9,000,000
Number of customer downloads of the Office 2010 beta prior to launch, the largest Microsoft beta program in history. [source]


21.4 million
Number of new Bing search users in one year. [Comscore report – requires subscription]


24%
Linux Server market share in 2005. [source]

33%
Predicted Linux Server market share for 2007 (made in 2005). [source]

21.2%
Actual Linux Server market share, Q4 2009. [source]


8.8 million
Global iPhone sales in Q1 2010. [source]

21.5 million
Nokia smartphone sales in Q1 2010. [source]

55 million
Total smartphone sales globally in Q1 2010. [source]

439 million
Projected global smartphone sales in 2014. [source]


9
Number of years it took Salesforce.com to reach 1 million paid user milestone. [source]

6
Number of years it took Microsoft Dynamics CRM to reach 1 million paid user milestone. [source]

100%
Percent chance that Salesforce.com CEO will mention Microsoft in a speech, panel, interview, or blog post.


173 million
Global Gmail users. [source]

284 million
Global Yahoo! Mail users.[source]

360 million
Global Windows Live Hotmail users.[source]

299 million
Active Windows Live Messenger Accounts worldwide. [Comscore MyMetrix, WW, March 2010 – requires subscription]

1
Rank of Windows Live Messenger globally compared to all other instant messaging services. [Comscore MyMetrix, WW, March 2010 – requires subscription]


$8.2 Billion
Apple Net income for fiscal year ending  Sep 2009. [source]

$6.5 Billion
Google Net income for fiscal year ending Dec 2009. [source]

$14.5 Billion
Microsoft Net Income for fiscal year ending June 2009. [source]

$23.0 billion
Total Microsoft revenue, FY2000. [source]

$58.4 billion
Total Microsoft revenue, FY2009. [source]

 

Good stuff!

-Rob

Sharing my knowledge and helping others never stops, so connect with me on my blog at http://robtiffany.com , follow me on Twitter at https://twitter.com/RobTiffany and on LinkedIn at https://www.linkedin.com/in/robtiffany

Sign Up for my Newsletter and get a FREE Chapter of “Mobile Strategies for Business!”

[mc4wp_form id=”5975″]