C++ Windows Store apps and Windows Azure Mobile Services

I had promised earlier that I will blog about using C++ /CX and Windows Azure Mobile Services to develop Windows Store apps. Today is the big day Smile

Before you begin

  1. In order to successfully build Metro-style apps that communicate with Windows Azure Mobile Services, you should obtain the Mobile Services SDK from http://www.windowsazure.com/en-us/develop/mobile/tutorials/create-a-windows-azure-account.

Creating a simple Windows Store app with Windows Azure Mobile Services

Open Microsoft Visual Studio 2012. Select File->New Project->Templates->Visual C++->Windows Store and pick a Blank App (XAML) project template. Save the project with a name, such as, MobileServicesApp.

Add a reference to the Windows Azure Mobile Services by right clicking on the project file and choosing References.

In the References dialog, click on Add New Reference. In the Add Reference dialog, choose Windows Azure Mobile Services Native Client from the Windows->Extensions node.

Replace the xaml markup in the MainPage.xaml with the one shown below. When you replace the markup, make sure to do so only the section in the Grid and not the complete Page markup.

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Grid Margin="50,50,10,10">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions> 
                <Grid Grid.Row="0" Grid.ColumnSpan="2" Margin="0,0,0,20">
                    <StackPanel>
                        <TextBlock Foreground="#0094ff" FontFamily="Segoe UI Light" Margin="0,0,0,6">WINDOWS AZURE MOBILE SERVICES</TextBlock>
                        <TextBlock Foreground="Gray" FontFamily="Segoe UI Light" FontSize="45" >Windows Azure Mobile Services App</TextBlock>
                    </StackPanel>
                </Grid> 
                <Grid Grid.Row="1">
                    <StackPanel>
                        <local:Task Number="1" Title="Create a Todo Item" Description="Enter some text below and click Save to insert a new todo item into your database" /> 
                        <StackPanel Orientation="Horizontal" Margin="72,0,0,0">
                            <TextBox Name="TextInput" Margin="5" MinWidth="300"></TextBox>
                            <Button Name="ButtonSave" Click="ButtonSave_Click">Save</Button>
                        </StackPanel> 
                    </StackPanel>
                </Grid> 
                <Grid Grid.Row="1" Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition />
                    </Grid.RowDefinitions>
                    <StackPanel>
                        <local:Task Number="2" Title="Refresh List" Description="Click refresh below to load the unfinished todo items from your database." />
                        <Button Margin="72,0,0,0" Name="ButtonRefresh" Click="ButtonRefresh_Click">Refresh                        </Button>
                    </StackPanel> 
                    <ListView Name="ListItems" Margin="62,10,0,0" Grid.Row="1">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <CheckBox IsChecked="{Binding Complete, Mode=TwoWay}" Checked="CheckBox_Checked_1" Content="{Binding Text}" Margin="10,5" VerticalAlignment="Center"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView> 
                </Grid> 
            </Grid>
    </Grid>

Right click on the project file and choose Add->New Item. From the Add New Item dialog, choose User Control. Save it as Task.xaml

Replace the xaml markup in Task.xaml with the one below.

<UserControl
    x:Class="MobileServicesApp.Task"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:MobileServicesApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"> 

    <Grid VerticalAlignment="Top">
        <StackPanel Orientation="Horizontal">
            <Border BorderThickness="0,0,1,0" BorderBrush="DarkGray" Margin="0,10" MinWidth="70">
                <TextBlock Text="{Binding Number}" FontSize="45" Foreground="DarkGray" Margin="20,0"/>
            </Border>
            <StackPanel>
                <TextBlock Text="{Binding Title}" Margin="10,10,0,0" FontSize="16" FontWeight="Bold"/>
                <TextBlock Text="{Binding Description}" Margin="10,0,0,0" />
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

We will use a Number, Title and Description for each of our tasks. All of these, Number, Title and Description are dependency properties and their values will be set through the backing logic in the code-behind.

Replace the contents of the Task.xaml.h with the following code.

//
// Task.xaml.h
// Declaration of the Task class
//

#pragma once 
#include "Task.g.h"

namespace MobileServicesApp
{
	[Windows::Foundation::Metadata::WebHostHidden]
	public ref class Task sealed
	{
	public:
		Task();
		virtual ~Task(){}; 
	public:
		property int Number
		{
			int get()
			{
				return static_cast<int>(GetValue(NumberProperty_));
			}
			void set(int number)
			{
				SetValue(NumberProperty_, number);
			}
		}

		property Platform::String^ Title
		{
			Platform::String^ get()
			{
				return static_cast<Platform::String^>(GetValue(TitleProperty_));
			}
			void set(Platform::String^ s)
			{
				SetValue(TitleProperty_, s);
			}
		}

		property Platform::String^ Description
		{
			Platform::String^ get()
			{
				return static_cast<Platform::String^>(GetValue(DescriptionProperty_));
			}
			void set(Platform::String^ description)
			{
				SetValue(DescriptionProperty_, description);
			}
		} 

	private:
		static Windows::UI::Xaml::DependencyProperty^ NumberProperty_;
		static Windows::UI::Xaml::DependencyProperty^ TitleProperty_;
		static Windows::UI::Xaml::DependencyProperty^ DescriptionProperty_;
	};
}

Replace the contents of Tasks.xaml.cpp with the following code.

//
// Task.xaml.cpp
// Implementation of the Task class
//

#include "pch.h"
#include "Task.xaml.h"

using namespace MobileServicesApp; 
using namespace Platform;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Interop;

Windows::UI::Xaml::DependencyProperty^ MobileServicesApp::Task::NumberProperty_
= DependencyProperty::Register(ref new String(L"Number"), TypeName(int::typeid), TypeName(Task::typeid),  ref new PropertyMetadata(nullptr) );

Windows::UI::Xaml::DependencyProperty^ MobileServicesApp::Task::TitleProperty_
= DependencyProperty::Register(ref new String(L"Title"), TypeName(String::typeid), TypeName(Task::typeid),ref new PropertyMetadata(nullptr) );

Windows::UI::Xaml::DependencyProperty^ MobileServicesApp::Task::DescriptionProperty_
= DependencyProperty::Register(ref new String(L"Description"), TypeName(String::typeid),
TypeName(Task::typeid), ref new PropertyMetadata(nullptr) );


Task::Task()
{
     InitializeComponent();
this->DataContext = this;
}

We are now ready to connect our app with the Windows Azure Mobile Services.

Add four methods to the MainPage.xaml.h in the MainPage class as shown below.

virtual void CheckBox_Checked_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
virtual void ButtonRefresh_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
virtual void ButtonSave_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
void RefreshData();

Add a new class named “ToDoItems” as shown below. This can be added in the MainPage.xaml.h class. This class will have the BindableAttribute set. We will use data binding to set values to the right XAML elements from the properties exposed by this class. This class and its properties also correspond to the table we create on the Windows Azure Mobile Services backend.

        [BindableAttribute]
	public ref class ToDoItems sealed
	{
	public:
		ToDoItems()
		{
			text_ = L"";
			complete_ = false;
		}
		property int ID
		{
			int get()
			{
				return ID_;
			}
			void set(int value)
			{
				ID_ = value;
			}
		}

		property Platform::String^ Text
		{
			Platform::String^ get()
			{
				return text_;
			}
			void set(Platform::String^ value)
			{
				text_ = value;
			}
		}

		property bool Complete
		{
			bool get()
			{
				return complete_;
			}
			void set(bool value)
			{
				complete_ = value;
			}
		}
	private:
		int ID_;
		Platform::String^ text_;
		bool complete_;
	};

Also add a Vector of ToDoItems in the MainPage class.

private:
	Vector<ToDoItems^>^ items_;

Connect your app to the Windows Azure Mobile Services. In the App constructor, create an instance of the Mobile Service client.

client_ = ref new MobileServiceClient(ref new Uri(L"Your app URI/"),
            ref new String(L"Your Secret Key"));

Inserting data into the table in easy. You create an instance of a “ToDoItem”, create a JSON object from the item and call the InsertAsync method of the corresponding table in the Windows Azure Mobile Service.

void MainPage::ButtonSave_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args)
{
	auto item = ref new ToDoItems();
	item->Text = TextInput->Text;
	item->Complete = false;
	//save data to AzureMobile
	auto client = App::MobileClient;
	auto jsonObject = ref new JsonObject();
	jsonObject->Insert(L"text", JsonValue::CreateStringValue(item->Text));
	jsonObject->Insert(L"complete", JsonValue::CreateBooleanValue(item->Complete));

	auto table = client->GetTable("TodoItem");
	task<IJsonValue^> insertTask(table->InsertAsync(jsonObject));
	insertTask.then([this, item](IJsonValue^ V)
	{
		auto results = V->Stringify();
		JsonObject^ savedItem = ref new JsonObject();
		if (JsonObject::TryParse(results, &savedItem))
		{
			item->ID = savedItem->GetNamedNumber("id");
			items_->Append(item);
			ListItems->ItemsSource = items_;
		}
	});
}

Updating the items follows a similar process as inserting items. You create a JSON object of the “ToDoItem” to be updated and call the UpdateAsync method on the table.

void MainPage::CheckBox_Checked_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args)
{
	auto cb = dynamic_cast<CheckBox^>(sender);
	ToDoItems^ item = dynamic_cast<ToDoItems^>(cb->DataContext);
	auto client = App::MobileClient;
	auto jsonObject = ref new JsonObject();
	int ID = item->ID;
	bool Status = item->Complete;
	jsonObject->Insert(L"id", JsonValue::CreateNumberValue(item->ID));
	jsonObject->Insert(L"complete", JsonValue::CreateBooleanValue(item->Complete)); 

	auto table = client->GetTable("TodoItem");
	task<IJsonValue^> updateTask(table->UpdateAsync(jsonObject));
	updateTask.then([this, item](IJsonValue^ V)
	{
		int x = items_->Size;
		for (int i = 0; i < x; ++i)
		{
			if (items_->GetAt(i) == item)
			{
				items_->RemoveAt(i);
			}
		}
	});
}

Querying the table for all records is also simple. You create a simple “SQL” query and call the ReadAsync method on the table. The response is a JSONValue that can be parsed and populated as per your needs. In our case, we update the list of items for our sample.

void MainPage::RefreshData()
{
	String^ query = "Select * from TodoItem";
	auto client = App::MobileClient;
	auto table = client->GetTable("TodoItem");
	task<IJsonValue^> readTask(table->ReadAsync(query));
	readTask.then([this](IJsonValue^ V)
	{
		auto list = V->Stringify();
		JsonArray^ mapValue = ref new JsonArray();
		if(JsonArray::TryParse(list, &mapValue))
		{
			auto vec = mapValue->GetView();
			std::for_each(begin(vec), end(vec), [this](IJsonValue^ M)
			{
				if (M->GetObject()->GetNamedBoolean("complete") == false)
				{
					String^ str = M->Stringify();
					ToDoItems^ item = ref new ToDoItems();
					item->Text = M->GetObject()->GetNamedString("text");
					item->ID = M->GetObject()->GetNamedNumber("id");
					item->Complete = M->GetObject()->GetNamedBoolean("complete");
					items_->Append(item);
				}
			});
			ListItems->ItemsSource = items_;
		}
	});
}

 

Now you can go to the Windows Azure Management portal and verify that insertion and updating of records work. You can get the complete project here or from http://code.msdn.microsoft.com

Windows Azure Mobile Services coupled with the JSON APIs in the Windows Runtime (these APIs can be found under the Windows.Data.json namespace) make it very easy to communicate with the Azure Mobile Services. The JSON APIs are light weight APIs and can also be used to communicate with Windows Live Services such as Skydrive etc. Hopefully this project has whetted your interest in these new APIs and will encourage you to explore more of the awesomeness of the Windows Runtime!

Stay tuned for more!

-Sridhar

4 Comments

  1. Aditya

    Sir
    I was following your above post but i am not able to understand what to do at this line “Connect your app to the Windows Azure Mobile Services. In the App constructor, create an instance of the Mobile Service client.” Please explain it in detail,how to implement it.
    waiting for early reply.

    • Hello Aditya,
      The code snippet below the line shows how to connect to Windows Azure Mobile Services. I am reproducing that code below for your reference.
      client_ = ref new MobileServiceClient(ref new Uri(L”Your app URI/”), ref new String(L”Your Secret Key”));

      You will need to sign up for a Windows Azure account and get your app URI and secret key from the service. Those values should be passed to the call mentioned above. Please have a look at the sample solution attached to the blog post.

      -Sridhar

  2. Aditya

    sir
    where i have to put this client code and i got my app url but i am do not know from where i can get security key and what it is,and sir i am making app in which i want to allow user to upload video and pdf files to azure and they can also download from there,may you please guide me through this?
    I will be very grateful to you.

    • Hi Aditya,
      You can get an Azure account by signing up for one at http://windows.azure.com. You should use skydrive for your scenario as skydrive is meant for sharing content.
      Thanks,
      Sridhar

Comments are closed