共用方式為


Quickstart: Adding a mobile service using C++

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

This Quickstart shows how to use Azure Mobile Services to add a cloud-based back-end service to an existing Windows Store app that's written in C++. Mobile Services makes it easy to store and query for data, log users in with popular identity providers, and send and receive push notifications in your app. To learn more, see the Mobile Services dev center. When you're done, you will have created a mobile service in your Azure subscription, added Mobile Services code to the starter app project, and run the app to insert data into the new mobile service.

Prerequisites

  • Microsoft Visual Studio 2013**.
  • Active Azure account. If you don't have an account, you can create a free trial account in just a couple of minutes. For details, see Microsoft Azure Free Trial.
  • Active Windows Store Developer account. If you don't have an account, you can create one by using Visual Studio.

Create the GetStartedWithMobileServicesCpp project

First, you will create and test a Visual Studio 2013 project for a Windows 8.1 app to which Mobile Services support will be added. This starter app stores To do list items in memory.

  1. In Visual Studio, on the menu bar, choose File, New, Project.
  2. 2. In the left pane of the New Project dialog box, expand Installed, Templates, Visual C++, Windows Store. In the center pane, select the Blank App (XAML) template. Specify GetStartedWithMobileServices as the name for the project, and then choose the OK button. Visual Studio creates the GetStartedWithMobileServices application for you.

Add a custom user control

Next you will add a custom user control for displaying the UI of your app.

  1. In Solution Explorer, open the shortcut menu for the Common folder, and then choose Add, New Item.

  2. In the left pane of the Add New Item dialog box, expand Visual C++, Windows Store, and then select User Control in the center pane. Specify Task.xaml as the name for the item, and then choose Add.

  3. In the Task.xaml window in the editor, replace the Grid element in the XAML with this code:

        <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" TextWrapping="Wrap" MaxWidth="500" />
                </StackPanel>
            </StackPanel>
        </Grid>
    

    This defines the UI elements and bindings for the custom control.

  4. In Solution Explorer, expand Task.xaml and open Task.xaml.h in the editor, and then replace its contents with this code:

    //
    // Task.xaml.h
    // Declaration of the Task class
    //
    
    #pragma once
    
    #include "Task.g.h"
    
    namespace GetStartedWithMobileServices
    {
        [Windows::Foundation::Metadata::WebHostHidden]
        public ref class Task sealed
        {
    public:
            Task();
    
            property int Number
            {
                int get()
                {
                    return safe_cast<int>(GetValue(NumberProperty));
                }
                void set(int value)
                {
                    SetValue(NumberProperty, value);
                }
            }
    
            property Platform::String^ Title
            {
                Platform::String^ get()
                {
                    return safe_cast<Platform::String^>(GetValue(TitleProperty));
                }
                void set(Platform::String^ value)
                {
                    SetValue(TitleProperty, value);
                }
            }
    
            property Platform::String^ Description
            {
                Platform::String^ get()
                {
                    return safe_cast<Platform::String^>(GetValue(DescriptionProperty));
                }
                void set(Platform::String^ value)
                {
                    SetValue(DescriptionProperty, value);
                }
            }
    
        private:
            static Windows::UI::Xaml::DependencyProperty^ NumberProperty;
            static Windows::UI::Xaml::DependencyProperty^ TitleProperty;
            static Windows::UI::Xaml::DependencyProperty^ DescriptionProperty;
        };
    }
    

    This code declares the Task class, which contains the properties and fields used for the XAML data binding in the custom control.

  5. In Solution Explorer, open Task.xaml.cpp in the editor, and replace the code in the file with this code:

    //
    // Task.xaml.cpp
    // Implementation of the Task class
    //
    
    #include "pch.h"
    #include "Task.xaml.h"
    
    using namespace GetStartedWithMobileServices;
    
    using namespace Platform;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Interop;
    
    // The User Control item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234236
    
    Task::Task()
    {
        InitializeComponent();
        this->DataContext = this;
    }
    
    // Using a DependencyProperty as the backing store for Number.  
    // This enables animation, styling, binding, etc... 
    DependencyProperty^ Task::NumberProperty =
        DependencyProperty::Register(
            "Number", TypeName(int::typeid), TypeName(Task::typeid), nullptr);
    
    // Using a DependencyProperty as the backing store for Title.  
    // This enables animation, styling, binding, etc... 
    DependencyProperty^ Task::TitleProperty =
        DependencyProperty::Register(
            "Title", TypeName(String::typeid), TypeName(Task::typeid), nullptr);
    
    // Using a DependencyProperty as the backing store for Description.  
    // This enables animation, styling, binding, etc... 
    DependencyProperty^ Task::DescriptionProperty =
        DependencyProperty::Register(
            "Description", TypeName(String::typeid), TypeName(Task::typeid), nullptr);
    

    This code implements the XAML data binding for the custom control.

Add the user interface code

Next you will add the user interface and implementation code to your app to enter and display to do list items, represented by the TodoItem class. The app uses an in-memory Platform::Collections::Vector<TodoItem^>^ collection to store the TodoItem objects for display in the UI. For now, the app does not persist the items to the cloud.

  1. In Solution Explorer, open MainPage.xaml in the editor, and then replace the XAML with this code:

    <Page
        x:Class="GetStartedWithMobileServices.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:GetStartedWithMobileServices"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <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">MICROSOFT AZURE MOBILE SERVICES</TextBlock>
                        <TextBlock Foreground="Gray" FontFamily="Segoe UI Light" FontSize="45" >Sample: Get started with Mobile Services in C++</TextBlock>
                    </StackPanel>
                </Grid>
    
                <Grid Grid.Row="1">
                    <StackPanel>
                        <local:Task Number="1" Title="Insert a TodoItem" 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="Query and Update Data" Description="Click refresh below to load the unfinished TodoItems from your database. Use the checkbox to complete and update your TodoItems" />
                        <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 Name="CheckBoxComplete" IsChecked="{Binding Complete, Mode=TwoWay}" Checked="CheckBoxComplete_Checked" Content="{Binding Text}" Margin="10,5" VerticalAlignment="Center"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </Grid>
        </Grid>
    </Page>
    

    This declares the UI elements for the app. The Task custom controls are used to describe the to do list item insertion and display areas. The to do list items are displayed in a ListView of CheckBox elements, which is data bound to the TodoItem collection.

  2. In Solution Explorer, expand MainPage.xaml and open MainPage.xaml.h in the editor, and then replace its contents with this code:

    //
    // MainPage.xaml.h
    // Declaration of the MainPage class.
    //
    
    #pragma once
    
    #include "MainPage.g.h"
    
    namespace GetStartedWithMobileServices
    {
        /// <summary>
        /// Represents a to do list item.
        /// </summary>
        [Windows::UI::Xaml::Data::BindableAttribute]
        public ref class TodoItem sealed
        {
        public:
            TodoItem()
            {
                Text = L"";
                Complete = false;
                ID = "0";
            }
    
            property Platform::String^ ID;
            property Platform::String^ Text;
            property bool Complete;
    
        internal:
            TodoItem(Platform::String^ text, bool complete = false, Platform::String^ id = "0")
            {
                Text = text;
                Complete = complete;
                ID = id;
            }
    
        };   
    
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public ref class MainPage sealed
        {
           public:
                MainPage();
    
        protected:
            virtual void ButtonRefresh_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
            virtual void ButtonSave_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
            virtual void CheckBoxComplete_Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args);
            virtual void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override;
    
        private:
            void InsertTodoItem(TodoItem^ todoItem);
            void RefreshTodoItems();
            void UpdateCheckedTodoItem(TodoItem^ todoItem);
    
            Platform::Collections::Vector<TodoItem^>^ items;
        };
    }
    

    This code declares the TodoItem class and adds event handlers and the TodoItem collection to the MainPage class.

  3. In Solution Explorer, open MainPage.xaml.cpp in the editor, and then replace its contents with this code:

    //
    // MainPage.xaml.cpp
    // Implementation of the MainPage class.
    //
    
    #include "pch.h"
    #include "MainPage.xaml.h"
    
    using namespace GetStartedWithMobileServices;
    
    using namespace Platform;
    using namespace Platform::Collections;
    using namespace Windows::Foundation;
    using namespace Windows::Foundation::Collections;
    using namespace Windows::UI::Xaml;
    using namespace Windows::UI::Xaml::Controls;
    using namespace Windows::UI::Xaml::Controls::Primitives;
    using namespace Windows::UI::Xaml::Data;
    using namespace Windows::UI::Xaml::Input;
    using namespace Windows::UI::Xaml::Media;
    using namespace Windows::UI::Xaml::Navigation;
    
    // The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?LinkID=234238
    
    MainPage::MainPage()
    {
        InitializeComponent();
    
        items = ref new Vector<TodoItem^>();
        ListItems->ItemsSource = items;
    }
    
    void MainPage::InsertTodoItem(TodoItem^ todoItem)
    {
        // For this local example, we do not initialize
        // the Id property. When we change this method
        // to use Azure Mobile Services, the value will
        // be automatically created for us. To create your
        // own Guid string, you can use the COM function 
        // CoCreateGuid in objbase.h.
        items->Append(todoItem);
    }
    
    void MainPage::RefreshTodoItems()
    {
    }
    
    void MainPage::UpdateCheckedTodoItem(TodoItem^ item)
    {
    }
    
    void MainPage::ButtonRefresh_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args)
    {
        RefreshTodoItems();
    }
    
    void MainPage::ButtonSave_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args)
    {
        auto todoItem = ref new TodoItem(TextInput->Text);
        InsertTodoItem(todoItem);
    }
    
    void MainPage::CheckBoxComplete_Checked(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ args)
    {
        auto cb = dynamic_cast<CheckBox^>(sender);
        TodoItem^ item = dynamic_cast<TodoItem^>(cb->DataContext);
        UpdateCheckedTodoItem(item);
    }
    
    void MainPage::OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e)
    {
        RefreshTodoItems();
    }
    

    This implements the code to insert and update the to do list items.

Build and run the project

Now you will build and test your app before adding mobile services features.

  1. Press the F5 key to build the project and start the app. If there are build errors, review the code to verify that you followed all of the instructions to create and edit the app.
  2. In the app, enter some text in Insert a TodoItem, then choose Save. Notice that the saved text is displayed in the second column under Query and update data.
  3. Close the app and stop the debugger when you are satisfied that the app is working correctly. Since this version of the application does not save the to do list items when the application is not running, it is not very useful. Next, we will add code to persist the to do list in the cloud with Mobile Services.

Create a new mobile service

The following steps create a new mobile service in Azure and add code to your project that enables access to this new service. Before you can create the mobile service, you must import the publishsettings file from your Azure subscription into Visual Studio. This enables Visual Studio to connect to Azure on your behalf. When you create a new mobile service, you must specify a Azure SQL Database that is used by the mobile service to store app data.

  1. In Visual Studio 2013, open Solution Explorer, open the project's shortcut menu then choose Add Connected Service....

  2. If you have not imported your Azure subscription information before, in the Services Manager dialog, choose Import subscriptions..., then choose Download subscription file. Log in to Azure Management Portal if required, then choose Save when your browser requests to save the file. Make a note of where you saved the downloaded .publishsettings file. Choose Browse, navigate to the location where you saved the .publishsettings file, select the file, then choose Open and then Import. Visual Studio imports the data needed to connect to your Azure subscription. When your subscription already has one or more existing mobile services, the service names are displayed.

    Note  After importing the publish settings, consider deleting the downloaded .publishsettings file as it contains information that can be used by others to access your account. Secure the file if you plan to keep it for use in other connected app projects.

     

  3. Choose Create service..., then in the Create Mobile Service dialog, select your Subscription and the desired Region for your mobile service. Enter a Name for your mobile service and make sure that name is available. A red X is displayed when the name is not available. In Database, select <Create New>, supply the Server user name and Server password for your database administration account, then choose Create.

    Note  As part of this Quickstart, you create a new SQL Database instance and server. You can reuse this new database and administer it as you would any other SQL Database instance. If you already have a database in the same region as the new mobile service, you can instead choose the existing database. When you choose an existing database, make sure that you supply correct login credentials. If you supply incorrect login credentials, the mobile service is created in an unhealthy state.

     

    After the mobile service is created, Visual Studio adds references to the C++ REST Extension SDK for Windows Store apps and to the Mobile Services C++ Client library to the project and your project source code is updated.

  4. In Solution Explorer, open the services folder, then open the mobile services folder to find and open the folder containing the mobile service class for your app. When Visual Studio generates the header and implementation file for the class used to interact with your mobile service, the generated files and class are named by appending "MobileService" to your service name. Your generated code will be similar to, but not the same as, the code that follows. In the instructions, substitute the name of your mobile service class when you see TodoListMobileService. Open the header file for your mobile service class:

    #pragma once
    
    #include <azuremobile.h>
    
    namespace AzureMobileHelper
    {
        /// <summary>
        /// TodoListMobileService contains support for contacting an associated mobile service.
        /// </summary>
        class TodoListMobileService
        {
        public:
            static azure::mobile::client& GetClient();
        };
    }
    

    This code provides access to your new mobile service in your app by using the static GetClient member function of the class. This client instance is created by supplying the URI and the application key of the new mobile service, found in the .cpp file for the class:

    #include "pch.h"
    #include "services\mobile services\TodoListMobileService\MY_MOBILE_SERVICE_MobileService.h"
    
    using namespace AzureMobileHelper;
    
    /// <summary>
    /// Returns the client instance representing the associated mobile service account.
    /// </summary>
    /// <returns>A non-const reference to the client instance.</returns>
    azure::mobile::client& TodoListMobileService::GetClient()
    {
        static azure::mobile::client c(L"https://MY_MOBILE_SERVICE.azure-mobile.net/", 
                                       L"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
        return c;
    }
    

    The path to the include file, the name of the include file, and the parameters to the client constructor will all be based on the name of your service and the application key, and will be filled in automatically by Visual Studio.

Add a new table to the mobile service

Before you can store data in your new mobile service, you must create a new storage table in the service. These steps show how to use Visual Studio 2013 to create a new table in the mobile service. Then you update the app to use Mobile Services to store items in Azure instead of only in the local collection.

  1. In Server Explorer, expand Microsoft Azure Mobile Services, open the shortcut menu for your mobile service, then choose Create Table. In the Create Table dialog, enter TodoItem in Table Name.

  2. Expand Advanced, verify that the table operation permissions default to Anybody with the Application Key, then choose Create. This creates the TodoItem table on the server, where anyone that has the application key can access and change data in the table without having to first be authenticated.

    Note  The application key is distributed with the application. Because this key is not securely distributed, it cannot be considered a security token. To secure access to your mobile service data, you must instead authenticate users before accessing. For more information, see Permissions.

     

  3. In the file MainPage.xaml.h, add the following include statement:

    #include <azuremobile.h>
    
  4. In this same file, add the following constructor in the internal: section of the TodoItem class:

    // TodoItem conversion constructor from json object
    TodoItem(const web::json::value& jsonvalue)
    {
        Text = ref new Platform::String(jsonvalue[U("text")].as_string().c_str());
        Complete = jsonvalue[U("complete")].as_bool();
        ID = ref new Platform::String(jsonvalue[U("id")].as_string().c_str());
    }
    

    Add this declaration in the private: section of the MainPage class:

            std::shared_ptr<azure::mobile::table> todoTable;
    

    The todoTable is used to define a proxy class for the database table.

  5. In the file MainPage.xaml.cpp, add an include statement for the mobile service header file. The path and name of this file depends on the name you chose for your mobile service. Start typing "include "services\" and Visual Studio will help you complete the path to your header file:

    #include "services\mobile services\TodoListMobileService\MY_MOBILE_SERVICE_HEADER_FILE.h"
    

    Still in MainPage.xaml.cpp, add a using statement to enable the web namespace by adding the following line to the using statements:

    using namespace web;
    

    This simplifies access to the JSON types used to transfer information between your app and the mobile service back end.

  6. In the MainPage constructor, add code to initialize the todoTable with your client class. After you type "AzureMobileHelper::" Visual Studio will help you complete the statement with your specific class name and the static GetClient method.

    todoTable = std::make_shared<azure::mobile::table>
        (AzureMobileHelper::MY_MOBILE_SERVICE::GetClient(), L"TodoItem");
    

    This makes a proxy class for the database table.

Add code to read and write from the table

The azure::mobile::table class contains the find, insert, read, remove, and update methods to perform operations on the table.

  1. Replace the existing InsertTodoItem member function with this code:

    void MainPage::InsertTodoItem(TodoItem^ todoItem)
    {
        auto obj = json::value::object();
        obj[U("text")] = json::value::string(todoItem->Text->Data());
        obj[U("complete")] = json::value::boolean(todoItem->Complete);
        todoTable->insert(obj).then([=](json::value result)
        {
            if (result.is_object())
            {
                items->Append(todoItem);
            }
        }, concurrency::task_continuation_context::use_current());
    }
    

    This code creates a JSON object containing the values of the new TodoItem and inserts the new item into the table.

    Note  New tables are created with only an Id column. Because we don't specify a value for the Id property in our TodoItem, Azure Mobile Services will automatically create a string Guid value for that column in the table. Also, when dynamic schema is enabled, the mobile service automatically generates the other columns based on the JSON object in the insert or update request. For more information, see Dynamic schema.

     

  2. Replace the existing RefreshTodoItems member function with this code:

    void MainPage::RefreshTodoItems()
    {
        todoTable->read().then([this](json::value result)
        {
            if (result.is_array())
            {
                items = ref new Vector<TodoItem^>();
                for (auto iter = result.cbegin(); iter != result.cend(); ++iter)
                {
                    if (iter->second.is_object())
                    {
                        items->Append(ref new TodoItem(iter->second));
                    }
                }
                ListItems->ItemsSource = items;
            }
        }, concurrency::task_continuation_context::use_current());
    }
    

    This reads the array of JSON objects returned and constructs a new items collection, then appends a newly constructed TodoItem for each table row, which is returned as the second member of the JSON object. When the collection is filled, the code sets the ListItems binding to the items collection, which contains all of the TodoItem objects returned from the mobile service.

  3. In the UpdateCheckedTodoItem member function, insert the following lines of code:

    void MainPage::UpdateCheckedTodoItem(TodoItem^ item)
    {
        auto obj = json::value::object();
        obj[U("id")] = json::value::string(item->ID->Data());
        obj[U("text")] = json::value::string(item->Text->Data());
        obj[U("complete")] = json::value::boolean(true);
    
        todoTable->update(item->ID->Data(), obj);
    }
    

    This constructs a JSON object with the data for the TodoItem, and then sends an item update to the mobile service. The call is asynchronous, so if you want to do any further work in this method that depends on the result of the update operation, you need to do that work inside a task::then continuation method.

Test the app against your new mobile service

Now that the app has been updated to use Mobile Services for backend storage, it's time to test the app against Mobile Services.

  1. In Visual Studio, press the F5 key to run the app.
  2. As before, type text in Insert a TodoItem, and then choose Save. This sends a command to insert a new item to the mobile service, and the item is added to the collection. When the data is retrieved from the mobile service, it is stored in the local TodoItem collection and displayed in the list under Query and update data.
  3. Shut down and then restart the app. Notice that the added data is displayed, having been persisted and then reloaded from the mobile service.

Modify the query to filter out completed items

Now that the app is storing data in Azure, let's modify the query to filter out completed items from the results.

  1. In the MainPage.xaml.cpp project file, replace the existing RefreshTodoItems member function with the following version that filters out completed items:

    void MainPage::RefreshTodoItems()
    {
        azure::mobile::query_params query;
        query.where(U("complete ne true"));
    
        todoTable->read(query).then([this](json::value result)
        {
            if (result.is_array())
            {
                items = ref new Vector<TodoItem^>();
    
                for (auto iter = result.cbegin(); iter != result.cend(); ++iter)
                {
                    if (iter->second.is_object())
                    {
                        items->Append(ref new TodoItem(iter->second));
                    }
                }
                ListItems->ItemsSource = items;
            }
        }, concurrency::task_continuation_context::use_current());
    
    }
    

    The query parameter "complete ne true" is described by the OData URI specification.

  2. Restart the app, check another one of the items in the list and then choose the Refresh button. Notice that the checked item now disappears from the list. Each refresh results in a round-trip to the mobile service, which now returns filtered data.

Summary and next steps

Now you know how to use Mobile Services to add remote data storage capabilities to an existing app in a Visual Studio 2013 project.

To learn how to add Mobile Services push notification functionality to your Windows 8.1 app in Visual Studio 2013: Quickstart: Adding push notifications for a mobile service.

To learn how to use various identity providers to authenticate users and limit table access to authenticated users, see User authentication for C++ apps.

Validate and modify data in Mobile Services by using server scripts

Refine Mobile Services queries with paging