Azure Mobile Apps 用の管理されたクライアントの使用方法How to use the managed client for Azure Mobile Apps

注意

Visual Studio App Center では、モバイル アプリ開発の中心となる新しい統合サービスに投資しています。Visual Studio App Center is investing in new and integrated services central to mobile app development. 開発者は、ビルドテスト配布のサービスを使用して、継続的インテグレーションおよびデリバリー パイプラインを設定できます。Developers can use Build, Test and Distribute services to set up Continuous Integration and Delivery pipeline. アプリがデプロイされたら、開発者は分析および診断のサービスを利用してアプリの状態と使用状況を監視し、プッシュ サービスを利用してユーザーと関わることができます。Once the app is deployed, developers can monitor the status and usage of their app using the Analytics and Diagnostics services, and engage with users using the Push service. また、開発者は Auth を利用してユーザーを認証し、データ サービスを利用してクラウド内のアプリ データを保持および同期することもできます。Developers can also leverage Auth to authenticate their users and Data service to persist and sync app data in the cloud. App Center を今すぐチェックしてください。Check out App Center today.

概要Overview

このガイドでは、Windows および Xamarin アプリで Azure App Service Mobile Apps 用の管理されたクライアント ライブラリを使用する一般的なシナリオの実行方法を示します。This guide shows you how to perform common scenarios using the managed client library for Azure App Service Mobile Apps for Windows and Xamarin apps. Mobile Apps を初めて使用する場合は、まず、 Azure Mobile Apps のクイックスタート チュートリアルを完了することを検討してください。If you are new to Mobile Apps, you should consider first completing the Azure Mobile Apps quickstart tutorial. このガイドでは、クライアント側の管理された SDK に重点を置いています。In this guide, we focus on the client-side managed SDK. Mobile Apps 用のサーバー側 SDK の詳細については、.NET Server SDK or the Node.js Server SDK に関するドキュメントを参照してください。To learn more about the server-side SDKs for Mobile Apps, see the documentation for the .NET Server SDK or the Node.js Server SDK.

リファレンス ドキュメントReference documentation

クライアント SDK のリファレンス ドキュメントは、Azure Mobile Apps .NET クライアントのリファレンスに関するページにあります。The reference documentation for the client SDK is located here: Azure Mobile Apps .NET client reference. GitHub リポジトリの「 Azure Samples (Azure サンプル)」にも、いくつかのクライアント サンプルがあります。You can also find several client samples in the Azure-Samples GitHub repository.

サポートされているプラットフォームSupported Platforms

.NET プラットフォームでは、次のプラットフォームをサポートしています。The .NET Platform supports the following platforms:

  • API 19 ~ 24 (KitKat から Nougat) 対応 Xamarin Android リリースXamarin Android releases for API 19 through 24 (KitKat through Nougat)
  • iOS バージョン 8.0 以降対応 Xamarin iOS リリースXamarin iOS releases for iOS versions 8.0 and later
  • ユニバーサル Windows プラットフォームUniversal Windows Platform
  • Windows Phone 8.1Windows Phone 8.1
  • Windows Phone 8.0 (Silverlight アプリケーションを除く)Windows Phone 8.0 except for Silverlight applications

"サーバーフロー" の認証では、UI の表示に WebView を使用します。The "server-flow" authentication uses a WebView for the presented UI. デバイスで WebView UI を表示できない場合は、他の認証方法が必要になります。If the device is not able to present a WebView UI, then other methods of authentication are needed. そのため、この SDK は腕時計型デバイスのような制限付きデバイスには適していません。This SDK is thus not suitable for Watch-type or similarly restricted devices.

セットアップと前提条件Setup and Prerequisites

テーブルを少なくとも 1 つ含むモバイル アプリ バックエンド プロジェクトを既に作成して発行してあるものとします。We assume that you have already created and published your Mobile App backend project, which includes at least one table. このトピックで使用するコードでは、テーブルの名前は TodoItem であり、IdTextComplete の各列が含まれています。In the code used in this topic, the table is named TodoItem and it has the following columns: Id, Text, and Complete. このテーブルは、 Azure Mobile Apps クイックスタートで作成したものと同じテーブルです。This table is the same table created when you complete the Azure Mobile Apps quickstart.

C# での対応する型指定されたクライアント側の型は次のクラスです。The corresponding typed client-side type in C# is the following class:

public class TodoItem
{
    public string Id { get; set; }

    [JsonProperty(PropertyName = "text")]
    public string Text { get; set; }

    [JsonProperty(PropertyName = "complete")]
    public bool Complete { get; set; }
}

JsonPropertyAttribute を使用して、クライアントのフィールドとテーブルのフィールド間の PropertyName のマッピングが定義されます。The JsonPropertyAttribute is used to define the PropertyName mapping between the client field and the table field.

Mobile Apps バックエンドでテーブルを作成する方法については、.NET Server SDK のトピック or the Node.js Server SDK topicを参照してください。To learn how to create tables in your Mobile Apps backend, see the .NET Server SDK topic or the Node.js Server SDK topic. Azure ポータルでクイックスタートを使用してモバイル アプリ バックエンドを作成した場合は、 Azure ポータルEasy Tables設定を使用することもできます。If you created your Mobile App backend in the Azure portal using the QuickStart, you can also use the Easy tables setting in the Azure portal.

方法:マネージド クライアント SDK パッケージをインストールするHow to: Install the managed client SDK package

NuGetから、Mobile Apps 用の管理されたクライアント SDK パッケージをインストールするには、次のいずれかの方法を使用します。Use one of the following methods to install the managed client SDK package for Mobile Apps from NuGet:

  • Visual Studio でプロジェクトを右クリックし、 [NuGet パッケージの管理] をクリックします。Microsoft.Azure.Mobile.Client パッケージを見つけ、 [インストール] をクリックします。Visual Studio Right-click your project, click Manage NuGet Packages, search for the Microsoft.Azure.Mobile.Client package, then click Install.
  • Xamarin Studio でプロジェクトを右クリックし、 [Add](追加) 、> [Add NuGet Packages](NuGet パッケージの追加) の順にクリックします。Microsoft.Azure.Mobile.Client パッケージを見つけ、 [Add Package](パッケージの追加) をクリックします。Xamarin Studio Right-click your project, click Add > Add NuGet Packages, search for the Microsoft.Azure.Mobile.Client package, and then click Add Package.

メイン アクティビティ ファイルに、次の using ステートメントを必ず追加してください。In your main activity file, remember to add the following using statement:

using Microsoft.WindowsAzure.MobileServices;

注意

Android プロジェクトで参照されるすべてのサポート パッケージのバージョンが同じである必要があることに注意してください。Please note that all the support packages referenced in your Android project must have the same version. SDK には、Android プラットフォームに関して Xamarin.Android.Support.CustomTabs の依存関係があるため、プロジェクトで新しいサポート パッケージを使用する場合は、必要なバージョンを使用してこのパッケージを直接インストールし、競合を回避する必要があります。The SDK has Xamarin.Android.Support.CustomTabs dependency for Android platform, so if your project uses newer support packages you need to install this package with required version directly to avoid conflicts.

方法: Visual Studio でデバッグ シンボルを使用するHow to: Work with debug symbols in Visual Studio

SymbolSource を Visual Studio と統合するには、Microsoft.Azure.Mobile 名前空間のシンボルを SymbolSource. Refer to the SymbolSource instructions に使用します。The symbols for the Microsoft.Azure.Mobile namespace are available on SymbolSource. Refer to the SymbolSource instructions to integrate SymbolSource with Visual Studio.

Mobile Apps クライアントの作成Create the Mobile Apps client

次のコードでは、モバイル アプリ バックエンドへのアクセスに使用する MobileServiceClient オブジェクトを作成します。The following code creates the MobileServiceClient object that is used to access your Mobile App backend.

var client = new MobileServiceClient("MOBILE_APP_URL");

上記のコードで、MOBILE_APP_URL をモバイル アプリ バックエンドの URL に置き換えます。この URL は、Azure ポータルのモバイル アプリ バックエンドのブレードで確認できます。In the preceding code, replace MOBILE_APP_URL with the URL of the Mobile App backend, which is found in the blade for your Mobile App backend in the Azure portal. MobileServiceClient オブジェクトはシングルトンである必要があります。The MobileServiceClient object should be a singleton.

テーブルの操作Work with Tables

以下のセクションでは、レコードを検索し、取得する方法や、テーブル内のデータを変更する方法について詳しく説明します。The following section details how to search and retrieve records and modify the data within the table. 次のトピックについて説明します。The following topics are covered:

方法: テーブル参照を作成するHow to: Create a table reference

バックエンド テーブルのデータへのアクセスまたはデータの変更を行うすべてのコードで、 MobileServiceTable オブジェクトに対して関数を呼び出します。All the code that accesses or modifies data in a backend table calls functions on the MobileServiceTable object. 次のように、 GetTable メソッドを呼び出して、テーブルへの参照を取得します。Obtain a reference to the table by calling the GetTable method, as follows:

IMobileServiceTable<TodoItem> todoTable = client.GetTable<TodoItem>();

返されたオブジェクトでは、型指定されたシリアル化モデルを使用します。The returned object uses the typed serialization model. 型指定されていないシリアル化モデルもサポートされます。An untyped serialization model is also supported. 次のコード例では、型指定されていないテーブルへの参照を作成します。The following example creates a reference to an untyped table:

// Get an untyped table reference
IMobileServiceTable untypedTodoTable = client.GetTable("TodoItem");

型指定されていないクエリでは、基になる OData クエリ文字列を指定する必要があります。In untyped queries, you must specify the underlying OData query string.

方法: Mobile App のデータを照会するHow to: Query data from your Mobile App

このセクションでは、モバイル アプリ バックエンドにクエリを発行する方法について説明します。これには次の機能が含まれます。This section describes how to issue queries to the Mobile App backend, which includes the following functionality:

注意

すべての行が返されるのを防ぐために、サーバー側で設定されたページ サイズが適用されます。A server-driven page size is enforced to prevent all rows from being returned. ページングは、大きなデータ セットの既定の要求がサービスに悪影響を与えるのを防ぎます。Paging keeps default requests for large data sets from negatively impacting the service. 50 行を超える行を返すには、「ページにデータを返す」で説明するように、Skip メソッドと Take メソッドを使用します。To return more than 50 rows, use the Skip and Take method, as described in Return data in pages.

方法: 返されるデータをフィルター処理するHow to: Filter returned data

次のコードは、クエリに Where 句を含めることによってデータをフィルター処理する方法を示しています。The following code illustrates how to filter data by including a Where clause in a query. このコードは、Complete プロパティが false に等しい todoTable からすべての項目を返します。It returns all items from todoTable whose Complete property is equal to false. where 関数は、テーブルに対するクエリに行のフィルタリング述語を適用します。The Where function applies a row filtering predicate to the query against the table.

// This query filters out completed TodoItems and items without a timestamp.
List<TodoItem> items = await todoTable
    .Where(todoItem => todoItem.Complete == false)
    .ToListAsync();

ブラウザー開発者ツールや Fiddlerなどのメッセージ検査ソフトウェアを使用して、バックエンドに送信された要求の URI を表示できます。You can view the URI of the request sent to the backend by using message inspection software, such as browser developer tools or Fiddler. 要求 URI を確認すると、クエリ文字列が変更されていることがわかります。If you look at the request URI, notice that the query string is modified:

GET /tables/todoitem?$filter=(complete+eq+false) HTTP/1.1

この OData 要求は、Server SDK によって SQL クエリに変換されます。This OData request is translated into an SQL query by the Server SDK:

SELECT *
    FROM TodoItem
    WHERE ISNULL(complete, 0) = 0

Where メソッドに渡される関数には、任意の数の条件を設定できます。The function that is passed to the Where method can have an arbitrary number of conditions.

// This query filters out completed TodoItems where Text isn't null
List<TodoItem> items = await todoTable
    .Where(todoItem => todoItem.Complete == false && todoItem.Text != null)
    .ToListAsync();

次の例は、Server SDK によって SQL クエリに変換されます。This example would be translated into an SQL query by the Server SDK:

SELECT *
    FROM TodoItem
    WHERE ISNULL(complete, 0) = 0
          AND ISNULL(text, 0) = 0

このクエリは複数の句に分割することもできます。This query can also be split into multiple clauses:

List<TodoItem> items = await todoTable
    .Where(todoItem => todoItem.Complete == false)
    .Where(todoItem => todoItem.Text != null)
    .ToListAsync();

この 2 つの方法は等価であり、区別しないで使用できます。The two methods are equivalent and may be used interchangeably. 複数の述語を 1 つのクエリに連結する前のオプション — のほうが、—よりコンパクトでありお勧めです。The former option—of concatenating multiple predicates in one query—is more compact and recommended.

Where 句は、OData サブセットに変換される操作をサポートします。The Where clause supports operations that be translated into the OData subset. 操作には以下が含まれます。Operations include:

  • 関係演算子 (==、!=、<、<=、>、>=)Relational operators (==, !=, <, <=, >, >=),
  • 算術演算子 (+、-、/、*、%)Arithmetic operators (+, -, /, *, %),
  • 数値の精度 (Math.Floor、Math.Ceiling)Number precision (Math.Floor, Math.Ceiling),
  • 文字列関数 (Length、Substring、Replace、IndexOf、StartsWith、EndsWith)String functions (Length, Substring, Replace, IndexOf, StartsWith, EndsWith),
  • 日付プロパティ (Year、Month、Day、Hour、Minute、Second)Date properties (Year, Month, Day, Hour, Minute, Second),
  • オブジェクトのプロパティへのアクセスAccess properties of an object, and
  • これらの操作を組み合わせる式Expressions combining any of these operations.

Server SDK のサポート対象については、 OData v3 のドキュメントをご覧ください。When considering what the Server SDK supports, you can consider the OData v3 Documentation.

方法: 返されるデータを並べ替えるHow to: Sort returned data

次のコードは、クエリに OrderBy 関数または OrderByDescending 関数を含めることによってデータを並べ替える方法を示しています。The following code illustrates how to sort data by including an OrderBy or OrderByDescending function in the query. 次のコードは、todoTable から、Text フィールドの値に基づいて昇順に並べ替えられた項目を返します。It returns items from todoTable sorted ascending by the Text field.

// Sort items in ascending order by Text field
MobileServiceTableQuery<TodoItem> query = todoTable
                .OrderBy(todoItem => todoItem.Text)
List<TodoItem> items = await query.ToListAsync();

// Sort items in descending order by Text field
MobileServiceTableQuery<TodoItem> query = todoTable
                .OrderByDescending(todoItem => todoItem.Text)
List<TodoItem> items = await query.ToListAsync();

方法: ページにデータを返すHow to: Return data in pages

既定では、バックエンドは最初の 50 行のみを返します。By default, the backend returns only the first 50 rows. Take メソッドを呼び出すことによって、返される行の数を増やすことができます。You can increase the number of returned rows by calling the Take method. Skip メソッドと共に Take を使用して、クエリによって返されるデータセット全体のうち特定の "ページ" を要求します。Use Take along with the Skip method to request a specific "page" of the total dataset returned by the query. 次のクエリを実行すると、テーブルの最初の上位 3 つの項目が返されます。The following query, when executed, returns the top three items in the table.

// Define a filtered query that returns the top 3 items.
MobileServiceTableQuery<TodoItem> query = todoTable.Take(3);
List<TodoItem> items = await query.ToListAsync();

次の変更されたクエリは、最初の 3 つの結果をスキップし、その後の 3 つの結果を返します。The following revised query skips the first three results and returns the next three results. ページ サイズが 3 つの項目である場合、このクエリによってデータの 2 番目の "ページ" が生成されます。This query produces the second "page" of data, where the page size is three items.

// Define a filtered query that skips the top 3 items and returns the next 3 items.
MobileServiceTableQuery<TodoItem> query = todoTable.Skip(3).Take(3);
List<TodoItem> items = await query.ToListAsync();

IncludeTotalCount メソッドは、指定された paging/limit 句を無視して、返された " すべて " のレコードの総数を要求します。The IncludeTotalCount method requests the total count for all the records that would have been returned, ignoring any paging/limit clause specified:

query = query.IncludeTotalCount();

実際のアプリケーションでは、ページャー コントロールまたは同等の UI と共に前の例と同様のクエリを使用して、ページ間を移動することができます。In a real world app, you can use queries similar to the preceding example with a pager control or comparable UI to navigate between pages.

注意

また、モバイル アプリ バックエンドの 50 行の制限をオーバーライドするには、 EnableQueryAttribute をパブリック GET メソッドに適用し、ページング動作を指定する必要があります。To override the 50-row limit in a Mobile App backend, you must also apply the EnableQueryAttribute to the public GET method and specify the paging behavior. 次のコードをメソッドに適用すると、返される最大行数が 1000 行に設定されます。When applied to the method, the following sets the maximum returned rows to 1000:

[EnableQuery(MaxTop=1000)]

方法: 特定の列を選択するHow to: Select specific columns

クエリに Select 句を追加することで、結果に含める一連のプロパティを指定できます。You can specify which set of properties to include in the results by adding a Select clause to your query. たとえば、次のコードでは、1 つのフィールドだけを選択する方法と、複数のフィールドを選択し、フォーマットする方法も示しています。For example, the following code shows how to select just one field and also how to select and format multiple fields:

// Select one field -- just the Text
MobileServiceTableQuery<TodoItem> query = todoTable
                .Select(todoItem => todoItem.Text);
List<string> items = await query.ToListAsync();

// Select multiple fields -- both Complete and Text info
MobileServiceTableQuery<TodoItem> query = todoTable
                .Select(todoItem => string.Format("{0} -- {1}",
                    todoItem.Text.PadRight(30), todoItem.Complete ?
                    "Now complete!" : "Incomplete!"));
List<string> items = await query.ToListAsync();

これまでに説明した関数はいずれも付加的なものであるため、これらの関数を連鎖させることができます。All the functions described so far are additive, so we can keep chaining them. 連鎖した呼び出しはそれぞれ複数のクエリに影響を及ぼします。Each chained call affects more of the query. 次の例も参照してください。One more example:

MobileServiceTableQuery<TodoItem> query = todoTable
                .Where(todoItem => todoItem.Complete == false)
                .Select(todoItem => todoItem.Text)
                .Skip(3).
                .Take(3);
List<string> items = await query.ToListAsync();

方法: ID でデータを検索するHow to: Look up data by ID

LookupAsync 関数を使用すると、特定の ID でデータベースのオブジェクトを検索できます。The LookupAsync function can be used to look up objects from the database with a particular ID.

// This query filters out the item with the ID of 37BBF396-11F0-4B39-85C8-B319C729AF6D
TodoItem item = await todoTable.LookupAsync("37BBF396-11F0-4B39-85C8-B319C729AF6D");

方法: 型指定されていないクエリを実行するHow to: Execute untyped queries

型指定されていないテーブル オブジェクトを使用してクエリを実行するときは、次の例のように ReadAsyncを呼び出して、OData クエリ文字列を明示的に指定する必要があります。When executing a query using an untyped table object, you must explicitly specify the OData query string by calling ReadAsync, as in the following example:

// Lookup untyped data using OData
JToken untypedItems = await untypedTodoTable.ReadAsync("$filter=complete eq 0&$orderby=text");

プロパティ バッグのように使用できる JSON 値が返されます。You get back JSON values that you can use like a property bag. JToken と Newtonsoft Json.NET の詳細については、 Json.NET サイトをご覧ください。For more information on JToken and Newtonsoft Json.NET, see the Json.NET site.

方法: モバイル アプリ バックエンドにデータを挿入するHow to: Insert data into a Mobile App backend

クライアントのすべての型には、Id という名前のメンバーが含まれる必要があります。その既定値は文字列です。All client types must contain a member named Id, which is by default a string. この Id は、オフライン同期で CRUD 操作を実行するために必要となります。次のコードは、InsertAsync メソッドを使用してテーブルに新しい行を挿入する方法を示しています。This Id is required to perform CRUD operations and for offline sync. The following code illustrates how to use the InsertAsync method to insert new rows into a table. パラメーターには、挿入するデータが .NET オブジェクトとして含まれます。The parameter contains the data to be inserted as a .NET object.

await todoTable.InsertAsync(todoItem);

挿入時に一意のカスタム ID 値が todoItem に含まれていない場合、サーバーによって GUID が生成されます。If a unique custom ID value is not included in the todoItem during an insert, a GUID is generated by the server. 生成された ID を取得するには、呼び出しから制御が戻った後にオブジェクトを調べます。You can retrieve the generated Id by inspecting the object after the call returns.

型指定されていないデータを挿入するときは、Json.NET を利用することもできます。To insert untyped data, you may take advantage of Json.NET:

JObject jo = new JObject();
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.InsertAsync(jo);

電子メール アドレスを一意の文字列 ID として使用する例を次に示します。Here is an example using an email address as a unique string id:

JObject jo = new JObject();
jo.Add("id", "myemail@emaildomain.com");
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.InsertAsync(jo);

ID 値の操作Working with ID values

Mobile Apps は、テーブルの ID 列で一意のカスタム文字列値をサポートしています。Mobile Apps supports unique custom string values for the table's id column. 文字列値により、アプリケーションで電子メール アドレスやユーザー名などのカスタム値を ID に使用することが可能になります。A string value allows applications to use custom values such as email addresses or user names for the ID. 文字列 ID には、次のような利点があります。String IDs provide you with the following benefits:

  • ID は、データベースとのラウンド トリップを行わずに生成されます。IDs are generated without making a round trip to the database.
  • 他のテーブルやデータベースのレコードをより簡単にマージできます。Records are easier to merge from different tables or databases.
  • ID 値をより適切にアプリケーションのロジックに統合できます。IDs values can integrate better with an application's logic.

挿入されたレコードで文字列 ID 値が設定されない場合は、モバイル アプリ バックエンドによって ID 用の一意の値が生成されます。When a string ID value is not set on an inserted record, the Mobile App backend generates a unique value for the ID. Guid.NewGuid メソッドを使用すると、クライアント上またはバックエンドで、独自の ID 値を生成できます。You can use the Guid.NewGuid method to generate your own ID values, either on the client or in the backend.

JObject jo = new JObject();
jo.Add("id", Guid.NewGuid().ToString("N"));

方法: モバイル アプリ バックエンドのデータを変更するHow to: Modify data in a Mobile App backend

次のコードは、 UpdateAsync メソッドを使用して、同じ ID を持つ既存のレコードを新しい情報で更新する方法を示しています。The following code illustrates how to use the UpdateAsync method to update an existing record with the same ID with new information. パラメーターには、更新するデータが .NET オブジェクトとして含まれます。The parameter contains the data to be updated as a .NET object.

await todoTable.UpdateAsync(todoItem);

型指定されていないデータを更新するには、次のように Json.NET を利用できます。To update untyped data, you may take advantage of Json.NET as follows:

JObject jo = new JObject();
jo.Add("id", "37BBF396-11F0-4B39-85C8-B319C729AF6D");
jo.Add("Text", "Hello World");
jo.Add("Complete", false);
var inserted = await table.UpdateAsync(jo);

更新を行うときは、 id フィールドを指定する必要があります。An id field must be specified when making an update. バックエンドでは、 id フィールドを使用して更新する行を識別します。The backend uses the id field to identify which row to update. id フィールドは、InsertAsync 呼び出しの結果から取得できます。The id field can be obtained from the result of the InsertAsync call. id 値を指定せずに項目を更新しようとすると、ArgumentException が発生します。An ArgumentException is raised if you try to update an item without providing the id value.

方法: モバイル アプリ バックエンドのデータを削除するHow to: Delete data in a Mobile App backend

次のコードは、 DeleteAsync メソッドを使用して既存のインスタンスを削除する方法を示しています。The following code illustrates how to use the DeleteAsync method to delete an existing instance. インスタンスは、todoItem に設定した id フィールドで識別されます。The instance is identified by the id field set on the todoItem.

await todoTable.DeleteAsync(todoItem);

型指定されていないデータを削除するには、次のような Json.NET を利用できます。To delete untyped data, you may take advantage of Json.NET as follows:

JObject jo = new JObject();
jo.Add("id", "37BBF396-11F0-4B39-85C8-B319C729AF6D");
await table.DeleteAsync(jo);

削除要求を行うときは、ID を指定する必要があります。When you make a delete request, an ID must be specified. それ以外のプロパティは、サービスに渡されないか、またはサービスで無視されます。Other properties are not passed to the service or are ignored at the service. 通常、DeleteAsync の呼び出しの結果は null です。The result of a DeleteAsync call is usually null. 渡す ID は、 InsertAsync の呼び出しの結果から取得できます。The ID to pass in can be obtained from the result of the InsertAsync call. id フィールドを指定せずに項目を削除しようとすると、MobileServiceInvalidOperationException がスローされます。A MobileServiceInvalidOperationException is thrown when you try to delete an item without specifying the id field.

方法: 競合の解決にオプティミスティック同時実行制御を使用するHow to: Use Optimistic Concurrency for conflict resolution

複数のクライアントが同じ項目に対して同時に変更を書き込む場合があります。Two or more clients may write changes to the same item at the same time. 競合を検出しない場合、最後に行われた書き込みによってそれ以前の更新がすべて上書きされます。Without conflict detection, the last write would overwrite any previous updates. オプティミスティック コンカレンシー では、それぞれのトランザクションがコミットでき、そのためリソース ロックが一切使用されないことを前提としています。Optimistic concurrency control assumes that each transaction can commit and therefore does not use any resource locking. オプティミスティック コンカレンシーではトランザクションをコミットする前に、他のトランザクションがそのデータを変更していないことを確認します。Before committing a transaction, optimistic concurrency control verifies that no other transaction has modified the data. データが変更されている場合、トランザクションのコミットはロール バックされます。If the data has been modified, the committing transaction is rolled back.

Mobile Apps はオプティミスティック コンカレンシーをサポートしており、モバイル アプリ バックエンドで各テーブルに定義されている version システム プロパティ列を使用して各項目の変更を追跡します。Mobile Apps supports optimistic concurrency control by tracking changes to each item using the version system property column that is defined for each table in your Mobile App backend. レコードが更新されるたびに、Mobile Apps はそのレコードの version プロパティを新しい値に設定します。Each time a record is updated, Mobile Apps sets the version property for that record to a new value. 各更新要求の際に、要求に含まれているレコードの version プロパティが、サーバー上のレコードの同じプロパティと比較されます。During each update request, the version property of the record included with the request is compared to the same property for the record on the server. 要求で渡されたバージョンがバックエンドと一致しない場合、クライアント ライブラリは MobileServicePreconditionFailedException<T> 例外を生成します。If the version passed with the request does not match the backend, then the client library raises a MobileServicePreconditionFailedException<T> exception. 例外に含まれている型は、レコードのサーバー側のバージョンを含んでいるバックエンドのレコードです。The type included with the exception is the record from the backend containing the servers version of the record. アプリケーションはこの情報を使用して、バックエンドからの正しい version 値で更新要求をもう一度実行して変更をコミットするかどうかを判断できます。The application can then use this information to decide whether to execute the update request again with the correct version value from the backend to commit changes.

オプティミスティック コンカレンシーを有効にするには、テーブル クラスに version システム プロパティ用の列を定義します。Define a column on the table class for the version system property to enable optimistic concurrency. 例:For example:

public class TodoItem
{
    public string Id { get; set; }

    [JsonProperty(PropertyName = "text")]
    public string Text { get; set; }

    [JsonProperty(PropertyName = "complete")]
    public bool Complete { get; set; }

    // *** Enable Optimistic Concurrency *** //
    [JsonProperty(PropertyName = "version")]
    public string Version { set; get; }
}

型指定のないテーブルを使用しているアプリケーションは、テーブルの SystemProperties に次のように Version フラグを設定することによって、オプティミスティック コンカレンシーを有効にします。Applications using untyped tables enable optimistic concurrency by setting the Version flag on the SystemProperties of the table as follows.

//Enable optimistic concurrency by retrieving version
todoTable.SystemProperties |= MobileServiceSystemProperties.Version;

オプティミスティック コンカレンシーの有効化に加え、UpdateAsync の呼び出し時にコード内で MobileServicePreconditionFailedException<T> 例外をキャッチすることも必要です。In addition to enabling optimistic concurrency, you must also catch the MobileServicePreconditionFailedException<T> exception in your code when calling UpdateAsync. 更新対象のレコードに適切な version を適用して競合を解決し、解決済みのレコードで UpdateAsync を呼び出します。Resolve the conflict by applying the correct version to the updated record and call UpdateAsync with the resolved record. 次のコードは、書き込み競合が検出された場合にそれを解決する方法を示しています。The following code shows how to resolve a write conflict once detected:

private async void UpdateToDoItem(TodoItem item)
{
    MobileServicePreconditionFailedException<TodoItem> exception = null;

    try
    {
        //update at the remote table
        await todoTable.UpdateAsync(item);
    }
    catch (MobileServicePreconditionFailedException<TodoItem> writeException)
    {
        exception = writeException;
    }

    if (exception != null)
    {
        // Conflict detected, the item has changed since the last query
        // Resolve the conflict between the local and server item
        await ResolveConflict(item, exception.Item);
    }
}


private async Task ResolveConflict(TodoItem localItem, TodoItem serverItem)
{
    //Ask user to choose the resolution between versions
    MessageDialog msgDialog = new MessageDialog(
        String.Format("Server Text: \"{0}\" \nLocal Text: \"{1}\"\n",
        serverItem.Text, localItem.Text),
        "CONFLICT DETECTED - Select a resolution:");

    UICommand localBtn = new UICommand("Commit Local Text");
    UICommand ServerBtn = new UICommand("Leave Server Text");
    msgDialog.Commands.Add(localBtn);
    msgDialog.Commands.Add(ServerBtn);

    localBtn.Invoked = async (IUICommand command) =>
    {
        // To resolve the conflict, update the version of the item being committed. Otherwise, you will keep
        // catching a MobileServicePreConditionFailedException.
        localItem.Version = serverItem.Version;

        // Updating recursively here just in case another change happened while the user was making a decision
        UpdateToDoItem(localItem);
    };

    ServerBtn.Invoked = async (IUICommand command) =>
    {
        RefreshTodoItems();
    };

    await msgDialog.ShowAsync();
}

詳細については、「 Azure Mobile Apps でのオフライン データ同期 」をご覧ください。For more information, see the Offline Data Sync in Azure Mobile Apps topic.

方法: Mobile Apps のデータを Windows ユーザー インターフェイスにバインドするHow to: Bind Mobile Apps data to a Windows user interface

このセクションでは、Windows アプリで UI 要素を使用して、返されたデータ オブジェクトを表示する方法について説明します。This section shows how to display returned data objects using UI elements in a Windows app. 次のコード例では、不完全な項目のクエリによってリストのソースにバインドします。The following example code binds to the source of the list with a query for incomplete items. MobileServiceCollection は、Mobile Apps 対応のバインディング コレクションを作成します。The MobileServiceCollection creates a Mobile Apps-aware binding collection.

// This query filters out completed TodoItems.
MobileServiceCollection<TodoItem, TodoItem> items = await todoTable
    .Where(todoItem => todoItem.Complete == false)
    .ToCollectionAsync();

// itemsControl is an IEnumerable that could be bound to a UI list control
IEnumerable itemsControl  = items;

// Bind this to a ListBox
ListBox lb = new ListBox();
lb.ItemsSource = items;

マネージド ランタイムの一部のコントロールでは、 ISupportIncrementalLoadingというインターフェイスがサポートされます。Some controls in the managed runtime support an interface called ISupportIncrementalLoading. このインターフェイスにより、コントロールはユーザーによるスクロールの際に追加のデータを要求することができます。This interface allows controls to request extra data when the user scrolls. このインターフェイスには、コントロールからの呼び出しを自動的に処理する、 MobileServiceIncrementalLoadingCollectionによるユニバーサル Windows アプリのサポートが組み込まれています。There is built-in support for this interface for universal Windows apps via MobileServiceIncrementalLoadingCollection, which automatically handles the calls from the controls. 次のように、Windows アプリで MobileServiceIncrementalLoadingCollection を使用します。Use MobileServiceIncrementalLoadingCollection in Windows apps as follows:

MobileServiceIncrementalLoadingCollection<TodoItem,TodoItem> items;
items = todoTable.Where(todoItem => todoItem.Complete == false).ToIncrementalLoadingCollection();

ListBox lb = new ListBox();
lb.ItemsSource = items;

Windows Phone 8 と "Silverlight" アプリで新しいコレクションを使用するには、IMobileServiceTableQuery<T>IMobileServiceTable<T>ToCollection 拡張メソッドを使用します。To use the new collection on Windows Phone 8 and "Silverlight" apps, use the ToCollection extension methods on IMobileServiceTableQuery<T> and IMobileServiceTable<T>. データを読み込むには、 LoadMoreItemsAsync()を呼び出します。To load data, call LoadMoreItemsAsync().

MobileServiceCollection<TodoItem, TodoItem> items = todoTable.Where(todoItem => todoItem.Complete==false).ToCollection();
await items.LoadMoreItemsAsync();

ToCollectionAsync または ToCollection を呼び出して作成されたコレクションを使用する場合は、UI コントロールにバインドできるコレクションを取得します。When you use the collection created by calling ToCollectionAsync or ToCollection, you get a collection that can be bound to UI controls. このコレクションはページングに対応しています。This collection is paging-aware. このコレクションはネットワークからデータを読み込むため、読み込みが失敗することがあります。Since the collection is loading data from the network, loading sometimes fails. このようなエラーを処理するには、MobileServiceIncrementalLoadingCollectionOnException メソッドをオーバーライドして、LoadMoreItemsAsync の呼び出しによって発生する例外を処理します。To handle such failures, override the OnException method on MobileServiceIncrementalLoadingCollection to handle exceptions resulting from calls to LoadMoreItemsAsync.

テーブルに多くのフィールドが存在するときに、コントロールにその一部だけを表示する必要があるとします。Consider if your table has many fields but you only want to display some of them in your control. UI に表示する特定の列を選択するときは、前述の「特定の列を選択する」のガイダンスを参考にしてください。You may use the guidance in the preceding section "Select specific columns" to select specific columns to display in the UI.

ページ サイズの変更Change the Page size

Azure Mobile Apps は、既定で要求ごとに最大 50 個の項目を返します。Azure Mobile Apps returns a maximum of 50 items per request by default. クライアントとサーバーの両方で最大ページ サイズを増やすことで、ページング サイズを変更できます。You can change the paging size by increasing the maximum page size on both the client and server. 要求されたページ サイズを増やすには、PullAsync() の使用時に PullOptions を指定します。To increase the requested page size, specify PullOptions when using PullAsync():

PullOptions pullOptions = new PullOptions
    {
        MaxPageSize = 100
    };

サーバー内で PageSize に 100 以上の値を設定した場合は、要求で最大 100 個の項目が返されます。Assuming you have made the PageSize equal to or greater than 100 within the server, a request returns up to 100 items.

オフライン テーブルの操作Work with Offline Tables

オフライン テーブルは、ローカル SQLite ストア データを使用して、オフラインのときに使用するためのデータを格納します。Offline tables use a local SQLite store to store data for use when offline. テーブル操作はすべて、リモート サーバー ストアではなく、ローカル SQLite ストアに対して実行されます。All table operations are done against the local SQLite store instead of the remote server store. オフライン テーブルを作成するには、まずプロジェクトを準備します。To create an offline table, first prepare your project:

  1. Visual Studio で、ソリューション、 [ソリューションの NuGet パッケージの管理...] の順に右クリックし、ソリューション内のすべてのプロジェクトの Microsoft.Azure.Mobile.Client.SQLiteStore NuGet パッケージを探してインストールします。In Visual Studio, right-click the solution > Manage NuGet Packages for Solution..., then search for and install the Microsoft.Azure.Mobile.Client.SQLiteStore NuGet package for all projects in the solution.

  2. (省略可能) Windows デバイスをサポートする場合、次の SQLite ランタイム パッケージのいずれかをインストールします。(Optional) To support Windows devices, install one of the following SQLite runtime packages:

  3. (省略可能)。(Optional). Windows デバイスで、 [参照] 、 > [参照の追加] の順に右クリックします。Windows フォルダー、 [拡張機能] の順に展開してから、Visual C++ 2013 Runtime for Windows SDK と共に適切な SQLite for Windows SDK を有効にします。For Windows devices, click References > Add Reference..., expand the Windows folder > Extensions, then enable the appropriate SQLite for Windows SDK along with the Visual C++ 2013 Runtime for Windows SDK. Windows プラットフォームによって SQLite SDK の名前はわずかに異なります。The SQLite SDK names vary slightly with each Windows platform.

テーブル参照を作成する前に、ローカル ストアを準備する必要があります。Before a table reference can be created, the local store must be prepared:

var store = new MobileServiceSQLiteStore(Constants.OfflineDbPath);
store.DefineTable<TodoItem>();

//Initializes the SyncContext using the default IMobileServiceSyncHandler.
await this.client.SyncContext.InitializeAsync(store);

ストアの初期化は通常、クライアントが作成された直後に行います。Store initialization is normally done immediately after the client is created. OfflineDbPath は、サポートするすべてのプラットフォームで使用できるファイル名にする必要があります。The OfflineDbPath should be a filename suitable for use on all platforms that you support. パスが完全修飾パスである場合 (つまり、スラッシュで始まる場合)、そのパスが使用されます。If the path is a fully qualified path (that is, it starts with a slash), then that path is used. パスが完全修飾パスでない場合、ファイルはプラットフォーム固有の場所に配置されます。If the path is not fully qualified, the file is placed in a platform-specific location.

  • iOS と Android のデバイスの既定のパスは、「個人ファイル」フォルダーです。For iOS and Android devices, the default path is the "Personal Files" folder.
  • Windows デバイスの既定のパスは、アプリケーション固有の AppData フォルダーです。For Windows devices, the default path is the application-specific "AppData" folder.

テーブル参照は、GetSyncTable<> メソッドを使用して取得できます。A table reference can be obtained using the GetSyncTable<> method:

var table = client.GetSyncTable<TodoItem>();

オフライン テーブルを使用する際に、認証は必要ありません。You do not need to authenticate to use an offline table. 認証が必要になるのは、バックエンド サービスと通信するときのみです。You only need to authenticate when you are communicating with the backend service.

オフライン テーブルの同期Syncing an Offline Table

既定では、オフライン テーブルはバックエンドと同期されません。Offline tables are not synchronized with the backend by default. 同期は、2 つの部分に分割されます。Synchronization is split into two pieces. 新しい項目のダウンロードから個別に変更をプッシュできます。You can push changes separately from downloading new items. 典型的な同期メソッドを次に示します。Here is a typical sync method:

public async Task SyncAsync()
{
    ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;

    try
    {
        await this.client.SyncContext.PushAsync();

        await this.todoTable.PullAsync(
            //The first parameter is a query name that is used internally by the client SDK to implement incremental sync.
            //Use a different query name for each unique query in your program
            "allTodoItems",
            this.todoTable.CreateQuery());
    }
    catch (MobileServicePushFailedException exc)
    {
        if (exc.PushResult != null)
        {
            syncErrors = exc.PushResult.Errors;
        }
    }

    // Simple error/conflict handling. A real application would handle the various errors like network conditions,
    // server conflicts and others via the IMobileServiceSyncHandler.
    if (syncErrors != null)
    {
        foreach (var error in syncErrors)
        {
            if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
            {
                //Update failed, reverting to server's copy.
                await error.CancelAndUpdateItemAsync(error.Result);
            }
            else
            {
                // Discard local change.
                await error.CancelAndDiscardItemAsync();
            }

            Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
        }
    }
}

PullAsync の最初の引数が null の場合、増分同期は使用されません。If the first argument to PullAsync is null, then incremental sync is not used. 各同期操作で、すべてのレコードが取得されます。Each sync operation retrieves all records.

レコードを取得する前に、SDK で暗黙的な PushAsync() が実行されます。The SDK performs an implicit PushAsync() before pulling records.

競合の処理は、PullAsync() メソッドで行われます。Conflict handling happens on a PullAsync() method. オンライン テーブルと同じ方法で競合を処理することができます。You can deal with conflicts in the same way as online tables. 競合が発生するのは、挿入、更新、または削除のときではなく、PullAsync() が呼び出されたときです。The conflict is produced when PullAsync() is called instead of during the insert, update, or delete. 複数の競合が発生した場合、競合は単一の MobileServicePushFailedException にバンドルされます。If multiple conflicts happen, they are bundled into a single MobileServicePushFailedException. エラーは個別に処理します。Handle each failure separately.

カスタム API の使用Work with a custom API

カスタム API を使用してカスタム エンドポイントを定義することにより、insert、update、delete、read のいずれの操作にも関連しないサーバー機能を公開することができます。A custom API enables you to define custom endpoints that expose server functionality that does not map to an insert, update, delete, or read operation. カスタム API を使用することによって、HTTP メッセージ ヘッダーの読み取りや設定、JSON 以外のメッセージ本文形式の定義など、メッセージングをより柔軟に制御することができます。By using a custom API, you can have more control over messaging, including reading and setting HTTP message headers and defining a message body format other than JSON.

クライアントで InvokeApiAsync メソッドのいずれかを呼び出して、カスタム API を呼び出します。You call a custom API by calling one of the InvokeApiAsync methods on the client. たとえば、次のコード行は、バックエンドの completeAll API に POST 要求を送信します。For example, the following line of code sends a POST request to the completeAll API on the backend:

var result = await client.InvokeApiAsync<MarkAllResult>("completeAll", System.Net.Http.HttpMethod.Post, null);

この形式は型指定されたメソッド呼び出しであり、MarkAllResult の戻り値の型が定義されている必要があります。This form is a typed method call and requires that the MarkAllResult return type is defined. 型指定および型指定のないメソッドの両方がサポートされます。Both typed and untyped methods are supported.

API が "/" で始まっていない限り、InvokeApiAsync() メソッドは API の先頭に "/api/" を追加します。The InvokeApiAsync() method prepends '/api/' to the API that you wish to call unless the API starts with a '/'. 例:For example:

  • InvokeApiAsync("completeAll",...) はバックエンドで /api/completeAll を呼び出しますInvokeApiAsync("completeAll",...) calls /api/completeAll on the backend
  • InvokeApiAsync("/.auth/me",...) はバックエンドで /.auth/me を呼び出しますInvokeApiAsync("/.auth/me",...) calls /.auth/me on the backend

InvokeApiAsync を使用して、Azure Mobile Apps で定義されていない WebAPI を含むすべての WebAPI を呼び出すことができます。You can use InvokeApiAsync to call any WebAPI, including those WebAPIs that are not defined with Azure Mobile Apps. InvokeApiAsync() を使用した場合は、認証ヘッダーを含む適切なヘッダーが要求と一緒に送信されます。When you use InvokeApiAsync(), the appropriate headers, including authentication headers, are sent with the request.

ユーザーの認証Authenticate users

Mobile Apps は、Facebook、Google、Microsoft アカウント、Twitter、Azure Active Directory などのさまざまな外部 ID プロバイダーを使用したアプリケーション ユーザーの認証と承認をサポートします。Mobile Apps supports authenticating and authorizing app users using various external identity providers: Facebook, Google, Microsoft Account, Twitter, and Azure Active Directory. テーブルのアクセス許可を設定することにより、特定の操作へのアクセスを認証されたユーザーのみに制限できます。You can set permissions on tables to restrict access for specific operations to only authenticated users. さらに、認証されたユーザーの ID を使用することにより、サーバー スクリプトで承認ルールを実装することもできます。You can also use the identity of authenticated users to implement authorization rules in server scripts. 詳細については、チュートリアル「 アプリケーションへの認証の追加」を参照してください。For more information, see the tutorial Add authentication to your app.

クライアント側管理フローサーバー側管理フローの 2 つの認証フローがサポートされています。Two authentication flows are supported: client-managed and server-managed flow. サーバー側管理フローには、プロバイダーの Web 認証のインターフェイスを利用する、最も簡単な認証方法が用意されています。The server-managed flow provides the simplest authentication experience, as it relies on the provider's web authentication interface. クライアント側管理フローでは、プロバイダー固有とデバイス固有の SDK を利用することから、デバイス固有の機能との統合がさらに進みます。The client-managed flow allows for deeper integration with device-specific capabilities as it relies on provider-specific device-specific SDKs.

注意

運用環境のアプリでは、クライアント側管理フローをお勧めします。We recommend using a client-managed flow in your production apps.

認証を設定するには、1 つ以上の ID プロバイダーにアプリを登録する必要があります。To set up authentication, you must register your app with one or more identity providers. ID プロバイダーは、アプリのクライアント ID とクライアント シークレットを生成します。The identity provider generates a client ID and a client secret for your app. これらの値は、Azure App Service の認証/承認を有効にするためにバックエンドで設定されます。These values are then set in your backend to enable Azure App Service authentication/authorization. 詳細については、 アプリケーションへの認証の追加のチュートリアルの手順を参照してください。For more information, follow the detailed instructions in the tutorial Add authentication to your app.

このセクションでは、次のトピックについて説明します。The following topics are covered in this section:

クライアント側管理認証Client-managed authentication

アプリ側から自主的に ID プロバイダーにアクセスし、取得したトークンをバックエンドへのログイン時に渡すことができます。Your app can independently contact the identity provider and then provide the returned token during login with your backend. このクライアント フローでは、ユーザーにシングル サインオン エクスペリエンスを提供したり、ID プロバイダーから追加のユーザー データを取得したりすることができます。This client flow enables you to provide a single sign-on experience for users or to retrieve additional user data from the identity provider. ID プロバイダー SDK を使用すると、よりネイティブな UX が実現し、さらにカスタマイズすることが可能になるため、クライアント フローの認証はサーバー フローを使用する方法よりも推奨されます。Client flow authentication is preferred to using a server flow as the identity provider SDK provides a more native UX feel and allows for additional customization.

クライアント フローの認証パターンとして、次の例が提供されています。Examples are provided for the following client-flow authentication patterns:

Active Directory Authentication Library を使用したユーザーの認証Authenticate users with the Active Directory Authentication Library

Active Directory Authentication Library (ADAL) を使うと、クライアントから Azure Active Directory 認証を使用してユーザー認証を開始できます。You can use the Active Directory Authentication Library (ADAL) to initiate user authentication from the client using Azure Active Directory authentication.

  1. Azure Active Directory ログインを使用するように App Service を構成する方法」のチュートリアルに従って、AAD のサインイン用にモバイル アプリ バックエンドを構成します。Configure your mobile app backend for AAD sign-on by following the How to configure App Service for Active Directory login tutorial. ネイティブ クライアント アプリケーションを登録する省略可能な手順を確実に実行します。Make sure to complete the optional step of registering a native client application.

  2. Visual Studio または Xamarin Studio でプロジェクトを開き、 Microsoft.IdentityModel.Clients.ActiveDirectory NuGet パッケージへの参照を追加します。In Visual Studio or Xamarin Studio, open your project and add a reference to the Microsoft.IdentityModel.Clients.ActiveDirectory NuGet package. 検索時に、プレリリース版を含めます。When searching, include pre-release versions.

  3. ご使用のプラットフォームに応じて、以下のコードをアプリケーションに追加します。Add the following code to your application, according to the platform you are using. それぞれで、次の置換を行います。In each, make the following replacements:

    • INSERT-AUTHORITY-HERE を、アプリケーションをプロビジョニングしたテナントの名前に置き換えます。Replace INSERT-AUTHORITY-HERE with the name of the tenant in which you provisioned your application. 形式は https://login.microsoftonline.com/contoso.onmicrosoft.com である必要があります。The format should be https://login.microsoftonline.com/contoso.onmicrosoft.com. この値は、Azure ポータル の Azure Active Directory の [ドメイン] タブからコピーできます。This value can be copied from the Domain tab in your Azure Active Directory in the Azure portal.

    • INSERT-RESOURCE-ID-HERE を、モバイル アプリ バックエンドのクライアント ID に置き換えます。Replace INSERT-RESOURCE-ID-HERE with the client ID for your mobile app backend. クライアント ID は、ポータルの [Azure Active Directory の設定][詳細] タブで入手できます。You can obtain the client ID from the Advanced tab under Azure Active Directory Settings in the portal.

    • INSERT-CLIENT-ID-HERE を、ネイティブ クライアント アプリケーションからコピーしたクライアント ID に置き換えます。Replace INSERT-CLIENT-ID-HERE with the client ID you copied from the native client application.

    • INSERT-REDIRECT-URI-HERE を、HTTPS スキームを使用して、サイトの /.auth/login/done エンドポイントに置き換えます。Replace INSERT-REDIRECT-URI-HERE with your site's /.auth/login/done endpoint, using the HTTPS scheme. これは、 https://contoso.azurewebsites.net/.auth/login/done のような値である必要があります。This value should be similar to https://contoso.azurewebsites.net/.auth/login/done.

      各プラットフォームに必要なコードは次のとおりです。The code needed for each platform follows:

      Windows:Windows:

      private MobileServiceUser user;
      private async Task AuthenticateAsync()
      {
      
         string authority = "INSERT-AUTHORITY-HERE";
         string resourceId = "INSERT-RESOURCE-ID-HERE";
         string clientId = "INSERT-CLIENT-ID-HERE";
         string redirectUri = "INSERT-REDIRECT-URI-HERE";
         while (user == null)
         {
             string message;
             try
             {
                 AuthenticationContext ac = new AuthenticationContext(authority);
                 AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId,
                     new Uri(redirectUri), new PlatformParameters(PromptBehavior.Auto, false) );
                 JObject payload = new JObject();
                 payload["access_token"] = ar.AccessToken;
                 user = await App.MobileService.LoginAsync(
                     MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
                 message = string.Format("You are now logged in - {0}", user.UserId);
             }
             catch (InvalidOperationException)
             {
                 message = "You must log in. Login Required";
             }
             var dialog = new MessageDialog(message);
             dialog.Commands.Add(new UICommand("OK"));
             await dialog.ShowAsync();
         }
      }
      

      Xamarin.iOSXamarin.iOS

      private MobileServiceUser user;
      private async Task AuthenticateAsync(UIViewController view)
      {
      
         string authority = "INSERT-AUTHORITY-HERE";
         string resourceId = "INSERT-RESOURCE-ID-HERE";
         string clientId = "INSERT-CLIENT-ID-HERE";
         string redirectUri = "INSERT-REDIRECT-URI-HERE";
         try
         {
             AuthenticationContext ac = new AuthenticationContext(authority);
             AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId,
                 new Uri(redirectUri), new PlatformParameters(view));
             JObject payload = new JObject();
             payload["access_token"] = ar.AccessToken;
             user = await client.LoginAsync(
                 MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
         }
         catch (Exception ex)
         {
             Console.Error.WriteLine(@"ERROR - AUTHENTICATION FAILED {0}", ex.Message);
         }
      }
      

      Xamarin.AndroidXamarin.Android

      private MobileServiceUser user;
      private async Task AuthenticateAsync()
      {
      
         string authority = "INSERT-AUTHORITY-HERE";
         string resourceId = "INSERT-RESOURCE-ID-HERE";
         string clientId = "INSERT-CLIENT-ID-HERE";
         string redirectUri = "INSERT-REDIRECT-URI-HERE";
         try
         {
             AuthenticationContext ac = new AuthenticationContext(authority);
             AuthenticationResult ar = await ac.AcquireTokenAsync(resourceId, clientId,
                 new Uri(redirectUri), new PlatformParameters(this));
             JObject payload = new JObject();
             payload["access_token"] = ar.AccessToken;
             user = await client.LoginAsync(
                 MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);
         }
         catch (Exception ex)
         {
             AlertDialog.Builder builder = new AlertDialog.Builder(this);
             builder.SetMessage(ex.Message);
             builder.SetTitle("You must log in. Login Required");
             builder.Create().Show();
         }
      }
      protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
      {
      
         base.OnActivityResult(requestCode, resultCode, data);
         AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
      }
      

Facebook または Google から取得したトークンを使用したシングル サインオンSingle Sign-On using a token from Facebook or Google

この Facebook や Google のスニペットに示すようにクライアント フローを使用できます。You can use the client flow as shown in this snippet for Facebook or Google.

var token = new JObject();
// Replace access_token_value with actual value of your access token obtained
// using the Facebook or Google SDK.
token.Add("access_token", "access_token_value");

private MobileServiceUser user;
private async Task AuthenticateAsync()
{
    while (user == null)
    {
        string message;
        try
        {
            // Change MobileServiceAuthenticationProvider.Facebook
            // to MobileServiceAuthenticationProvider.Google if using Google auth.
            user = await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token);
            message = string.Format("You are now logged in - {0}", user.UserId);
        }
        catch (InvalidOperationException)
        {
            message = "You must log in. Login Required";
        }

        var dialog = new MessageDialog(message);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
}

サーバー側管理認証Server-managed authentication

ID プロバイダーを登録したら、プロバイダーの LoginAsync 値を指定して、[MobileServiceClient] で LoginAsync メソッドを呼び出します。Once you have registered your identity provider, call the LoginAsync method on the [MobileServiceClient] with the MobileServiceAuthenticationProvider value of your provider. たとえば、次のコードは、Facebook を使用してサーバー フローのサインインを開始します。For example, the following code initiates a server flow sign-in by using Facebook.

private MobileServiceUser user;
private async System.Threading.Tasks.Task Authenticate()
{
    while (user == null)
    {
        string message;
        try
        {
            user = await client
                .LoginAsync(MobileServiceAuthenticationProvider.Facebook);
            message =
                string.Format("You are now logged in - {0}", user.UserId);
        }
        catch (InvalidOperationException)
        {
            message = "You must log in. Login Required";
        }

        var dialog = new MessageDialog(message);
        dialog.Commands.Add(new UICommand("OK"));
        await dialog.ShowAsync();
    }
}

Facebook 以外の ID プロバイダーを使用している場合は、LoginAsync の値をプロバイダーに対応する値に変更してください。If you are using an identity provider other than Facebook, change the value of MobileServiceAuthenticationProvider to the value for your provider.

サーバー フローでは、Azure App Service は、選択したプロバイダーのサインイン ページを表示することで OAuth 認証フローを管理します。In a server flow, Azure App Service manages the OAuth authentication flow by displaying the sign-in page of the selected provider. ID プロバイダーから制御が戻ったら、Azure App Service は App Service 認証トークンを生成します。Once the identity provider returns, Azure App Service generates an App Service authentication token. LoginAsync メソッドは MobileServiceUser を返します。これにより、認証されたユーザーの UserId と、JSON Web トークン (JWT) としての MobileServiceAuthenticationToken が提供されます。The LoginAsync method returns a MobileServiceUser, which provides both the UserId of the authenticated user and the MobileServiceAuthenticationToken, as a JSON web token (JWT). このトークンをキャッシュし、有効期限が切れるまで再利用できます。This token can be cached and reused until it expires. 詳細については、「認証トークンをキャッシュする」を参照してください。For more information, see Caching the authentication token.

認証トークンをキャッシュするCaching the authentication token

最初の認証に成功した後、プロバイダーからの認証トークンを保存することによって、ログイン メソッドの呼び出しを回避できる場合があります。In some cases, the call to the login method can be avoided after the first successful authentication by storing the authentication token from the provider. Microsoft Storeアプリと UWP アプリでは、正常にサインインした後、次にように PasswordVault を使用して現在の認証トークンをキャッシュできます:Microsoft Store and UWP apps can use PasswordVault to cache the current authentication token after a successful sign-in, as follows:

await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook);

PasswordVault vault = new PasswordVault();
vault.Add(new PasswordCredential("Facebook", client.currentUser.UserId,
    client.currentUser.MobileServiceAuthenticationToken));

UserId 値は、資格情報の UserName として保存され、トークンは Password として保存されます。The UserId value is stored as the UserName of the credential and the token is the stored as the Password. 以降の起動時には、資格情報がキャッシュされていないか PasswordVault をチェックすることができます。On subsequent start-ups, you can check the PasswordVault for cached credentials. 以下の例では、キャッシュされた資格情報が見つかればそれを使用し、それ以外の場合は、バックエンドに対して再度認証を試みます。The following example uses cached credentials when they are found, and otherwise attempts to authenticate again with the backend:

// Try to retrieve stored credentials.
var creds = vault.FindAllByResource("Facebook").FirstOrDefault();
if (creds != null)
{
    // Create the current user from the stored credentials.
    client.currentUser = new MobileServiceUser(creds.UserName);
    client.currentUser.MobileServiceAuthenticationToken =
        vault.Retrieve("Facebook", creds.UserName).Password;
}
else
{
    // Regular login flow and cache the token as shown above.
}

ユーザーをサインアウトさせるときは、次のように、保存された資格情報を削除する必要があります。When you sign out a user, you must also remove the stored credential, as follows:

client.Logout();
vault.Remove(vault.Retrieve("Facebook", client.currentUser.UserId));

Xamarin アプリでは、 Xamarin.Auth API を使用して、 Account オブジェクトに資格情報を安全に保存します。Xamarin apps use the Xamarin.Auth APIs to securely store credentials in an Account object. これらの API の使用例については、ContosoMoments 写真共有サンプルAuthStore.cs コード ファイルを参照してください。For an example of using these APIs, see the AuthStore.cs code file in the ContosoMoments photo sharing sample.

クライアント側管理認証を使用するときは、Facebook や Twitter などのプロバイダーから取得したアクセス トークンをキャッシュすることもできます。When you use client-managed authentication, you can also cache the access token obtained from your provider such as Facebook or Twitter. このトークンを指定することで、新しい認証トークンをバックエンドに要求することができます。その例を次に示します。This token can be supplied to request a new authentication token from the backend, as follows:

var token = new JObject();
// Replace <your_access_token_value> with actual value of your access token
token.Add("access_token", "<your_access_token_value>");

// Authenticate using the access token.
await client.LoginAsync(MobileServiceAuthenticationProvider.Facebook, token);

プッシュ通知Push Notifications

以下のトピックでは、プッシュ通知について説明します。The following topics cover Push Notifications:

方法: プッシュ通知に登録するHow to: Register for Push Notifications

Mobile Apps クライアントでは、Azure Notification Hubs によるプッシュ通知に登録できます。The Mobile Apps client enables you to register for push notifications with Azure Notification Hubs. 登録する場合、プラットフォーム固有のプッシュ通知サービス (PNS) からハンドルを取得します。When registering, you obtain a handle that you obtain from the platform-specific Push Notification Service (PNS). この値は、登録を作成するときに、任意のタグと一緒に指定します。You then provide this value along with any tags when you create the registration. 次のコードは、Windows Notification Service (WNS) によるプッシュ通知用の Windows アプリを登録します。The following code registers your Windows app for push notifications with the Windows Notification Service (WNS):

private async void InitNotificationsAsync()
{
    // Request a push notification channel.
    var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();

    // Register for notifications using the new channel.
    await MobileService.GetPush().RegisterNativeAsync(channel.Uri, null);
}

WNS に対するプッシュを行う場合は、Microsoft Store パッケージ SID を取得する必要があります。If you are pushing to WNS, then you MUST obtain a Microsoft Store package SID. テンプレート登録に登録する方法を含む Windows アプリの詳細については、「 アプリにプッシュ通知を追加する」を参照してください。For more information on Windows apps, including how to register for template registrations, see Add push notifications to your app.

クライアントからのタグ要求はサポートされていません。Requesting tags from the client is not supported. タグ要求は、通告なく登録から削除されます。Tag Requests are silently dropped from registration. タグと共にデバイスを登録したい場合は、Notification Hubs API を使用するカスタム API を作成し、登録を代行させます。If you wish to register your device with tags, create a Custom API that uses the Notification Hubs API to perform the registration on your behalf. RegisterNativeAsync() メソッドの代わりに、カスタム API を呼び出します。Call the Custom API instead of the RegisterNativeAsync() method.

方法:Microsoft Store のパッケージ SID を取得するHow to: Obtain a Microsoft Store package SID

Microsoft Store アプリでプッシュ通知を有効にするには、パッケージ SID が必要です。A package SID is needed for enabling push notifications in Microsoft Store apps. パッケージ SID を受け取るには、Microsoft Store にアプリケーションを登録します。To receive a package SID, register your application with the Microsoft Store.

この値を取得するには:To obtain this value:

  1. Visual Studio ソリューション エクスプローラーで、Microsoft Store アプリプロジェクトを右クリックし、 [ストア] 、 > [アプリケーションをストアと関連付ける] の順にクリックします。In Visual Studio Solution Explorer, right-click the Microsoft Store app project, click Store > Associate App with the Store....
  2. ウィザードで [次へ] をクリックし、Microsoft アカウントでサインインします。次に、 [新しいアプリケーション名の予約] にアプリの名前を入力し、 [予約] をクリックします。In the wizard, click Next, sign in with your Microsoft account, type a name for your app in Reserve a new app name, then click Reserve.
  3. アプリの登録が正常に作成されたら、アプリ名を選択し、 [次へ] をクリックして、 [関連付け] をクリックします。After the app registration is successfully created, select the app name, click Next, and then click Associate.
  4. Microsoft アカウントを使用して Windows デベロッパー センター にログインします。Log in to the Windows Dev Center using your Microsoft Account. [マイ アプリ] で、作成したアプリ登録をクリックします。Under My apps, click the app registration you created.
  5. [アプリ管理] 、 > [アプリ ID] の順にクリックし、下にスクロールして [パッケージ SID] を探します。Click App management > App identity, and then scroll down to find your Package SID.

多くの場合、パッケージ SID は URI として処理されます。その場合、スキームとして ms-app:// を使用する必要があります。Many uses of the package SID treat it as a URI, in which case you need to use ms-app:// as the scheme. この値をプレフィックスとして連結して形成されたパッケージ SID のバージョンをメモしておきます。Make note of the version of your package SID formed by concatenating this value as a prefix.

Xamarin アプリでは、iOS または Android プラットフォームで実行されているアプリを登録できる追加のコードが必要です。Xamarin apps require some additional code to be able to register an app running on the iOS or Android platforms. 詳細については、ご使用のプラットフォームに関するトピックをご覧ください。For more information, see the topic for your platform:

方法: プッシュ テンプレートを登録してクロス プラットフォーム通知を送信するHow to: Register push templates to send cross-platform notifications

テンプレートを登録するには、次のようにテンプレートで RegisterAsync() メソッドを使用します。To register templates, use the RegisterAsync() method with the templates, as follows:

JObject templates = myTemplates();
MobileService.GetPush().RegisterAsync(channel.Uri, templates);

テンプレートは JObject 型である必要があり、次の JSON 形式で複数のテンプレートを含めることができます。Your templates should be JObject types and can contain multiple templates in the following JSON format:

public JObject myTemplates()
{
    // single template for Windows Notification Service toast
    var template = "<toast><visual><binding template=\"ToastText01\"><text id=\"1\">$(message)</text></binding></visual></toast>";

    var templates = new JObject
    {
        ["generic-message"] = new JObject
        {
            ["body"] = template,
            ["headers"] = new JObject
            {
                ["X-WNS-Type"] = "wns/toast"
            },
            ["tags"] = new JArray()
        },
        ["more-templates"] = new JObject {...}
    };
    return templates;
}

RegisterAsync() メソッドは次のセカンダリ タイルも受け入れます。The method RegisterAsync() also accepts Secondary Tiles:

MobileService.GetPush().RegisterAsync(string channelUri, JObject templates, JObject secondaryTiles);

セキュリティを確保するために、登録時にすべてのタグが削除されます。All tags are stripped away during registration for security. インストールまたはインストール内のテンプレートにタグを追加する方法については、「Azure Mobile Apps 用 .NET バックエンド サーバー SDK の操作」を参照してください。To add tags to installations or templates within installations, see [Work with the .NET backend server SDK for Azure Mobile Apps].

これらの登録済みテンプレートを使用して通知を送信する方法については、 Notification Hubs APIに関するページをご覧ください。To send notifications utilizing these registered templates, refer to the Notification Hubs APIs.

その他のトピックMiscellaneous Topics

方法: エラーを処理するHow to: Handle errors

バックエンドでエラーが発生すると、クライアント SDK が MobileServiceInvalidOperationExceptionを生成します。When an error occurs in the backend, the client SDK raises a MobileServiceInvalidOperationException. 次の例では、バックエンドによって返される例外を処理する方法を示します。The following example shows how to handle an exception that is returned by the backend:

private async void InsertTodoItem(TodoItem todoItem)
{
    // This code inserts a new TodoItem into the database. When the operation completes
    // and App Service has assigned an Id, the item is added to the CollectionView
    try
    {
        await todoTable.InsertAsync(todoItem);
        items.Add(todoItem);
    }
    catch (MobileServiceInvalidOperationException e)
    {
        // Handle error
    }
}

エラー状況を処理する別の例については、 Mobile Apps ファイル サンプルで確認できます。Another example of dealing with error conditions can be found in the Mobile Apps Files Sample. LoggingHandler の例では、ログ記録代理ハンドラーを使用して、バックエンドに対する要求を記録します。The LoggingHandler example provides a logging delegate handler to log the requests being made to the backend.

方法: 要求ヘッダーをカスタマイズするHow to: Customize request headers

特定のアプリケーション シナリオをサポートするには、モバイル アプリ バックエンドとの通信をカスタマイズすることが必要な場合があります。To support your specific app scenario, you might need to customize communication with the Mobile App backend. たとえば、すべての送信要求にカスタム ヘッダーを追加したり、応答のステータス コードを変更したりすることが必要な場合がります。For example, you may want to add a custom header to every outgoing request or even change responses status codes. 次の例のように、カスタムの DelegatingHandlerを使用できます。You can use a custom DelegatingHandler, as in the following example:

public async Task CallClientWithHandler()
{
    MobileServiceClient client = new MobileServiceClient("AppUrl", new MyHandler());
    IMobileServiceTable<TodoItem> todoTable = client.GetTable<TodoItem>();
    var newItem = new TodoItem { Text = "Hello world", Complete = false };
    await todoTable.InsertAsync(newItem);
}

public class MyHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage>
        SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Change the request-side here based on the HttpRequestMessage
        request.Headers.Add("x-my-header", "my value");

        // Do the request
        var response = await base.SendAsync(request, cancellationToken);

        // Change the response-side here based on the HttpResponseMessage

        // Return the modified response
        return response;
    }
}