Monday, December 31, 2012
Using the OakLeaf ToDo List App with Windows 8 or a Surface RT Tablet
The OakLeaf ToDo List app is a simple, multi-tenanted application intended to demonstrate the basic capabilities of Windows Azure Mobile Services (WAMoS) in conjunction with data storage in a Windows Azure SQL Database (formerly SQL Azure) instance in Microsoft’s West US (Bay Area) data center. The app is available without charge to Windows 8 and Windows RT users from the OakLeaf Store.
You’ll find OakLeaf’s Terms of Service and Use for the App here and our Privacy Statement here.
To test drive the app with Windows 8 or Windows RT, do the following:
1. Click the OakLeaf ToDo List tile to momentarily display a splash screen:
imageImages were capture from a Surface RT device. Click to display them in full size.
and then open a Sign In page:
Note: Privacy and Terms link to a Microsoft privacy statement for Microsoft Accounts and terms of service for Microsoft-branded services, not the app’s privacy and terms statements required for Windows Store apps. Other authentication options provided by Windows Azure Access Control services are Facebook, Twitter, and Google accounts.
• 2. Complete the sign-in information and click Sign in to display the following permissions screen, if you haven’t used your Windows Account for the app previously:
3. Click Sign In or Yes to display an acknowledgment screen with a GUID representing your Microsoft Account name:
4. Click OK to display the main (and only) user screen, which displays uncompleted ToDo items (see item 22 in the todoitem table screen capture above:
5. Type a ToDo item in the Insert a TodoItem text box and click the Save button to display a push notification and add the item to the Query and Update Data list:
6. Click the check box of items in the Query and Update Data list to mark it completed and remove it from the list.
7. Click the Refresh button to list currently uncompleted ToDo items.
Posted by Roger Jennings (--rj) at 4:50 PM 0 comments
Labels: Azure, Azure Mobile Services, Cloud Computing, SQL Azure, Windows 8, Windows Azure, Windows Azure Access Control Services, Windows Azure Mobile Services, Windows Notification Services
Saturday, September 22, 2012
Windows Azure Mobile Services Preview Walkthrough–Part 3: Pushing Notifications to Windows 8 Users (C#)
Previous members of this series:
- Windows Azure Mobile Services Preview Walkthrough–Part 1: Windows 8 ToDo Demo Application (C#) - 9/8/2012
- Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#) - 9/9/2012
Part 3 of 5: The Windows Azure Mobile Services (WAMoS) Preview’s initial release enables application developers targeting Windows 8 to automate the following programming tasks for Windows Store apps:
- Creating a Windows Azure SQL Database (WASDB) instance and table to persist data entered in a Windows Store app’s form
- Connecting the table to the data entry front end app
- Adding and authenticating the application’s users
- Pushing notifications to users
image_thumb[1][1]My Windows Azure Mobile Services Preview Walkthrough–Part 1: Windows 8 ToDo Demo Application (C#) post of 9/8/2012 covered tasks 1 and 2; Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#) covered task 3.
This walkthrough describes the process for completing task 4 based on the Get started with push notifications and Push notifications to users by using Mobile Services tutorials. The process involves the following steps:
- Add push notifications to the app
- Update scripts to send push notifications
- Insert data to receive notifications
- Create the Channel table
- Update the app (code updated 9/12/2012 3:45 PM PDT)
- Update server scripts
- Verify the push notification behavior
- Viewing the Push Notification Log (added 9/20/2012 11:15 AM PDT, updated 9/22/2012 10:30 AM)
•• Updated Section “8 – Viewing Push Notification Logs” at the end of this article regarding multiple push notifications and errors on 9/22/2012.
• Updated Section 7 on 9/13/2012 at 1:00 PM PDT with elements marked • related to duplicate entries in the Channel table.
Screen captures for each step are added to the two tutorials and code modifications are made to accommodate user authentication.
Prerequisites: Completing the oakleaf-todo C# application in Part 1, as well as the user authentication addition of Part 2, and downloading/installing the Live SDK for Windows and Windows Phone, which provides a set of controls and APIs that enable applications to integrate single sign-on (SSO) with Microsoft accounts and access information from SkyDrive, Hotmail, and Windows Live Messenger on Windows Phone and Windows 8.
• If your Visual Studio 2012 version doesn’t include the SQL Server Object Manager feature and you receive multiple notifications when adding new todo items, download SQL Server Management Studio 2012 Express to view and remove duplicate entries in the Channel table, as described in steps 7-3 through 7-10 below.
1 – Add Push Notifications to the App
1-1. Launch your WAMoS app in Visual Studio 2012 for Windows 8 or higher, open the App.xaml.cs file and add the following using statement:
using Windows.Networking.PushNotifications;
1-2. Add the following code to App.xaml.cs after the OnSuspending() event handler:
public static PushNotificationChannel CurrentChannel { get; private set; }
private async void AcquirePushChannel()
{
CurrentChannel =
await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
}
This code acquires and stores a push notification channel.
1-3. At the top of the OnLaunched event handler in App.xaml.cs, add the following call to the new AcquirePushChannel method:
AcquirePushChannel();
1-3 AcquirePushChannel
This guarantees that the CurrentChannel property is initialized each time the application is launched.
1-4. Open the project file MainPage.xaml.cs and add the following new attributed property to the TodoItem class:
[DataMember(Name = "channel")]
public string Channel { get; set; }
Note: When dynamic schema is enabled on your mobile service, a new 'channel' column is automatically added to the TodoItem table when a new item that contains this property is inserted.
1-5. Replace the ButtonSave_Click event handler method with the following code:
private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
var todoItem = new TodoItem { Text = TextInput.Text, Channel = App.CurrentChannel.Uri };
InsertTodoItem(todoItem);
}
1-5 ButtonSave_ClickHandler
This sets the client's current channel value on the item before it is sent to the mobile service.
1-6. In the Management Portal’s Mobile Services Preview section, click the service name (oakleaf-todo for this example), click the Push tab and paste the Package SID value from Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#) step 1-3:
to the Package SID text box and click the Save button:
Figure6-OakLeaf_ToDo Push Client Credentials
2 – Update Scripts to Send Push Notifications
2-1. In the Management Portal’s Mobile Services Preview section, click the service name (oakleaf-todo for this example) click the Data tab and then click the TodoItem table.
2-2. In the todoitem page, click the Script tab and select theInsert script in the Operation list:
This displays the function that is invoked when an insert occurs in the TodoItem table.
2-3. Replace the insert function with the following code, and then click the Save button:
function insert(item, user, request) {
item.userId = user.userId;
request.execute({
success: function() {
// Write to the response and then send the notification in the background
request.respond();
push.wns.sendToastText04(item.channel, {
text1: item.text
}, {
success: function(pushResponse) {
console.log("Sent push:", pushResponse);
}
});
}
});
}
This registers a new insert script, which sends a push notification (the inserted text) to the channel provided in the insert request. The item.userId = user.userId; instruction is required to add the userId value to the todoitem.
3 – Insert Data to Receive Notifications
3-1. In Visual Studio, press the F5 key to run the app, log in if requested, click OK to confirm the user’s identity and click the Refresh button.
3-2. In the TodoList, type an item in the Insert a TodoItem text box and click the Save button.
3-3. Observe that after the insert completes, the app receives a push notification from WNS.
3-4. In the Management Portal’s Mobile Services Preview section, click the service name (oakleaf-todo for this example) click the Data tab, the TodoItem table, and the Browse tab:
Notice that the latest TodoItem has the channel value added.
4 - Create the Channel Table
4-1. In the Management Portal’s Mobile Services Preview with the todoitem table active as above, click the Mobile Services node in the navigation pane, click the oakleaf-todo item, and click the Data tab:
4-1 Activate Table Create Button
4-2. Click the Create button to open the Create New Table form, type Channel as the Table name and accept the default permissions:
This creates the Channel table, which stores the channel URIs used to send push notifications separate from item data.
Next, you will modify the push notifications app to store data in this new table instead of in the TodoItem table.
5- Update Your App (Revised 9/12/2012 4:00 PM PDT)
* Steps marked with an asterisk depart from the Push notifications to users by using Mobile Services instructions.
5-1. Reopen the project in Visual Studio 2012, open the MainPage.xaml.cs file, and remove the Channel property from the TodoItem class, which then should appear as follows:
public class TodoItem
{
public int Id { get; set; }
[DataMember(Name = "text")]
public string Text { get; set; }
[DataMember(Name = "complete")]
public bool Complete { get; set; }
}
5-1 FixTodoItemClass
5-2. Replace the ButtonSave_Click event handler method with the original version of this method, as follows:
private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
var todoItem = new TodoItem { Text = TextInput.Text };
InsertTodoItem(todoItem);
}
* 5-3. Add the following using statement at the top of the App.xaml.cs class to support the DataMember decoration:
using Microsoft.WindowsAzure.MobileServices;
5-3 using System.Runtime.Searialization
* 5-4. Add the following code to create a new Channel class to the end of App.xaml.cs class:
public class Channel
{
public int Id { get; set; }
[DataMember(Name = "uri")]
public string Uri { get; set; }
}
5-5. Replace the App.xaml.cs class’s AcquirePushChannel method with the following code:
private async void AcquirePushChannel()
{
CurrentChannel =
await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
IMobileServiceTable<Channel> channelTable = App.MobileService.GetTable<Channel>();
var channel = new Channel { Uri = CurrentChannel.Uri };
await channelTable.InsertAsync(channel);
}
This code inserts the current channel into the Channel table.
6 – Update Server Scripts
6-1. In the Management Portal select the TodoList database in the Mobile Services’ navigation pane, click the Data tab:
6-2. Click the Channel node to open its page, click the Script tab and select Insert to display the default script:
6-2 Channel Table Insert Default
This displays the function that is invoked when an insert occurs in the Channel table.
6-3. Replace the default Insert() function with the following code:
function insert(item, user, request) {
var channelTable = tables.getTable('Channel');
channelTable
.where({ uri: item.uri })
.read({ success: insertChannelIfNotFound });
function insertChannelIfNotFound(existingChannels) {
if (existingChannels.length > 0) {
request.respond(200, existingChannels[0]);
} else {
request.execute();
}
}
}
This script checks the Channel table for an existing channel with the same URI. The insert only proceeds if no matching channel was found. This prevents duplicate channel records.
6-3 Channel Table Insert Updated
• Note: If you have built and run the app before updating the Insert script with the preceding code, you might have issues with the Channel table. See step 7-3 below, which shows duplicate rows in the Channels table.
6-4. Click the Save button, and then click the TodoItem, click Script and select Insert to display the code added in Part 2.
6-4 Todo Table Insert From Part 2
6-5. Replace the Insert() function with the following code:
function insert(item, user, request) {
item.userId = user.userId;
request.execute({
success: function() {
request.respond();
sendNotifications();
}
});
function sendNotifications() {
var channelTable = tables.getTable('Channel');
channelTable.read({
success: function(channels) {
channels.forEach(function(channel) {
push.wns.sendToastText04(channel.uri, {
text1: item.text
}, {
success: function(pushResponse) {
console.log("Sent push:", pushResponse);
}
});
});
}
});
}
}
This insert script sends a push notification (with the text of the inserted item) to all channels stored in the Channel table.
6-6. Click the Save button to save the new code.
7 - Verify the Push Notification Behavior
7-1. In Visual Studio, press F5 to build and run the app, log on, if necessary, and type text in the Insert a TodoItem text box.
7-2. Click the Save button:
7-2 Click Save a Couple of Times
• Note that after the insert completes, the app receives multiple push notifications from WNS instead of the single notification expected, apparently due to unwanted duplicate rows in the Channels table having the same uri (identical token values).
• 7-3. To check for duplicate rows in the Channels table, launch the Management Portal and open the Channel table:
7-3 Duplicate Channel Table Rows
• 7-4. To remove the extra rows, find the Manage URL (server instance name) by opening the database you created in part 1:
• 7-5. Open the Channel table in Visual Studio’s SQL Object Explorer or SQL Management Studio 2012 by clicking New Connection and completing the Connect to Server dialog with the Mobile Services’ SQL Server instance name and your administrative credentials:
• 7-6 Click connect, choose View, SQL Server Object Explorer if you’re using Visual Studio, expand the server nodes, expand the Tables node right-click the oakleaf_todo.Channel table node, choose View Data to open a grid view of the table rows, and select all but one of the duplicate rows:
7-5 SQLServerObjectExplorerGrid
• 7-7. Press delete to open a confirmation dialog:
7-6 SQLServerObjectExplorerDelete3
• 7-8. Click OK to delete the selected rows.
• 7-9. Repeat steps 1 and 2 a couple of times to verify that you receive only one notification.
7-7 MultipleNotificationsFixed
7-10 (Optional). Run the app on two machines at the same time, and repeat the previous step. In this case, the notification is sent to all running app instances.
•• 8 – Viewing the Push Notification Log
Despite having removed duplicate rows in the Channel table, as described in the preceding section’s steps 7-3 through 7-9, I again encountered duplicate notifications for single ToDo Items. So I started a Why Do I Receive Three Notifications for a Single ToDo Entry? thread in the Windows Azure Mobile Services forum about this issue.
The Mobile Services team’s Josh Twist made the following observation in a reply to my question:
It is technically possible to receive multiple active (different) channelUrls for the same installed app on the same device. I'd recommend taking a look at our push implementation in the doto client sample which stores an 'installation id' in the channel table to ensure we only have one channel url per actual device installation.
The doto sample is available here: http://code.msdn.microsoft.com/windowsapps/doto-a-simple-social-todo-7e6ba464
If you’ve removed duplicate Channel rows and continue to incur multiple notifications for individual ToDo Item insertions, check the Push Notification Log and solve the problem by following these steps:
8–1. Open the oakleaf-todo WAMoS in the Management Portal, click the Logs tab to display the latest notification messages and select an Info item for a successful notification:
LogForMultipleNotificationsPerTodoItem
The preceding 21 items (7 successful (Info) and 14 failed (Error)) log entries are for inserting a single new ToDo Item.
8-2. Click the Details (i) button to display the Log Entry Details form:
8-3. Select an Error item and click the Details button to display the full error message:
The MSDN Library’s Push notification service request and response headers topic says the following about notificationstatus = dropped:
Josh Twist added the following comment in the forum thread after viewing the log entries in step 8-1:
I can't see the image clearly above but I suspect your app has multiple active channels for the device (you sent three notifications to three different channel urls, but they all point to your device). Take a look at the RegisterDevice method from the doto sample: https://github.com/WindowsAzure/azure-mobile-services/blob/master/samples/doto/C%23/ViewModels/MainViewModel.cs which uses the InstallationId type: https://github.com/WindowsAzure/azure-mobile-services/blob/master/samples/doto/C%23/Common/InstallationId.cs.
Then check the script we have on insert: https://github.com/WindowsAzure/azure-mobile-services/blob/master/samples/doto/ServerScripts/devices.insert.js
Following is the C# code for the InstallationId class:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Windows.Storage; namespace Doto { /// <summary> /// Generates a persistant unique identifier for this installation that is persisted in /// local storage. This is used by Doto to manage channelUrls for push notifications /// </summary> public static class InstallationId { private static string _fileName = "installation-id.dat"; private static string _value = null; private static object _lock = new object(); public static async Task<string> GetInstallationId() { if (_value != null) { return _value; } var file = await ApplicationData.Current.LocalFolder.CreateFileAsync(_fileName, CreationCollisionOption.OpenIfExists); _value = await FileIO.ReadTextAsync(file); if (string.IsNullOrWhiteSpace(_value)) { _value = Guid.NewGuid().ToString(); await FileIO.WriteTextAsync(file, _value); } return _value; } } }
And this is the JavaScript code for an insert event handler for an added Devices table, which would replace the Channel table:
function insert(item, user, request) { // we don't trust the client, we always set the user on the server item.userId = user.userId; // require an installationId if (!item.installationId || item.installationId.length === 0) { request.respond(400, "installationId is required"); return; } // find any records that match this device already (user and installationId combo) var devices = tables.getTable('devices'); devices.where({ userId: item.userId, installationId: item.installationId }).read({ success: function (results) { if (results.length > 0) { // This device already exists, so don't insert the new entry, // update the channelUri (if it's different) if (item.channelUri === results[0].channelUri) { request.respond(200, results[0]); return; } // otherwise, update the notification id results[0].channelUri = item.channelUri; devices.update(results[0], { success: function () { request.respond(200, results[0]); return; } }); } else { request.execute(); } } }); }
Accommodating the added class, as well as a new table and event handler, requires considerable effort to modify the original code. Simply deleting all existing rows of the Channel and, optionally, the TodoItem table(s) solved the problem for me, at least temporarily.
If I encounter multiple notifications for individual ToDo Item entries, I’ll update the source code with the preceding class and event handler.
Posted by Roger Jennings (--rj) at 10:38 AM 0 comments
Labels: Azure, Cloud Computing, Windows 8, Windows Azure Mobile Services, Windows Azure Notifications, Windows Notification Services, Windows Store Apps
Saturday, September 15, 2012
Windows Azure Mobile Services Preview Walkthrough–Part 4: Customizing the Windows Store App’s UI
Previous members of this series:
- Windows Azure Mobile Services Preview Walkthrough–Part 1: Windows 8 ToDo Demo Application (C#) - 9/8/2012
- Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#) - 9/9/2012
- Windows Azure Mobile Services Preview Walkthrough–Part 3: Pushing Notifications to Windows 8 Users (C#) - 9/12/2012, updated 9/15/2012
Part 4 of 5: According to the MSDN Library’s Packaging your Windows Store app topic:
By using the Store menu in Visual Studio, you can access the Windows Store and package your Windows Store app for distribution. You will use the Store as the primary way to sell or otherwise make available your apps. For more information, see Previewing the Windows Store and Selling apps.
You must package and prepare your app before you can upload it to the Store. The packaging process gets started when you create a Windows Store project or item based on a template. When you create a Windows Store app, Visual Studio creates a source file for the app package (Package.appxmanifest) and adds that file to your solution. The first time that you build the project, Visual Studio transforms the source file to the manifest file (AppxManifest.xml) and puts it in the output folder for the app. The manifest file describes your app, including its name, description, start page, splash screen, and logos. In addition, you use the manifest file to add capabilities and declarations to your app, such as the ability to access a webcam. You can use the Manifest Designer in Visual Studio to edit the properties in the Package.appxmanifest file. For more information, see Using the Manifest Designer (Windows Store apps). [Emphasis added.]
OakLeafLogoMVPMedBlue50pxEmulating a commercial Windows Store app requires customizing the UI to replace default tile and splash-screen images with custom *.png or *.jpg logo images, such as this:
Prerequisites: Completion of the following OakLeaf Systems Walkthroughs:
- Windows Azure Mobile Services Preview Walkthrough–Part 1: Windows 8 ToDo Demo Application (C#)
- Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#)
- Windows Azure Mobile Services Preview Walkthrough–Part 3: Pushing Notifications to Windows 8 Users (C#)
You must also create 150 x 150 and 310 x 150 logo, as well as a 620 x 300-px splash screen image files and save resized 24, 30, 50-px square logo files for other purposes in the \Documents\Visual Studio 2012\Projects\ProjectName\SolutionName\Assets folder, which contains the default logo files.
Assigning Images to Tiles and Splash Screens
1-1. Launch Visual Studio 2012 with your version of the OakLeaf ToDo app, and choose Project, Store, Edit App Manifest or double-click the Package.appxmanifest item in Solution Explorer to open the file in the App Manifest Designer and click the Packaging tab:
1-1 Original App Manifest in Designer
Note: This capture is from step 1-1 of Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#).
1-2. Change the Package Display Name to OakLeaf ToDo, click the … button to open the Select Image form, and select the 50-px square image file:
1-3. Click the Application UI tab, type the Display Name, Short Name and Description, and select the image of the appropriate size for the Logo, Wide Logo, and Splash Screen:
Note: Assigning a 24-px image as the Badge Logo requires adding a Background Task, as described in MSDN’s Background task sample application, which is beyond the scope of this Walkthrough.
1-4. Press F5 to build and run the app, display the Start window and scroll to the location of the former default tile:
1-4 Start Menu with Standard Tile
1-5. Type oa to search for the OakLeaf ToDo app, which displays the 50-px square tile:
1-6. If you specify the wide tile, the 150 x 310-px image file appears in the Start menu:
1-7. Right-click Solution Explorer’s Package.appxmainfest item and choose Open With, XML (Text) Editor to open the XML file in Visual Studio’s XML Editor:
1-7 Package.appxmanifest in VS XML Editor
The VisualElements element contains the name and location of each custom image.
I was surprised to discover that packaging and submitting the app to the Windows Store broke the user authentication feature described in the Windows Azure Mobile Services Preview Walkthrough–Part 2: Authenticating Windows 8 App Users (C#) post, which causes the landing page to appear briefly and then disappear. Following is the app’s status in the Windows Store Dashboard as of 9/17/2012 9:00 AM PDT:
Note: The Windows Store folks apparently didn’t get the memo about the name change from Metro Style Apps to Windows Store Apps.
Here’s a screen shot of the exception thrown in the MainPage.xaml.cs code:
Stay tuned for more details about the authentication problem.
Posted by Roger Jennings (--rj) at 12:39 PM 0 comments
Labels: Azure, Cloud Computing, Windows 8, Windows Azure, Windows Azure Mobile Services, Windows Azure Notifications, Windows Notification Services, Windows Store Apps