Come usare il client gestito per App per dispositivi mobili di AzureHow to use the managed client for Azure Mobile Apps

PanoramicaOverview

Questa guida illustra come eseguire scenari comuni usando la libreria client gestita per App per dispositivi mobili del servizio app di Azure in app Windows e Xamarin.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. Se non si conosce App per dispositivi mobili, è consigliabile completare prima l'esercitazione sull'introduzione ad App per dispositivi mobili di Azure.If you are new to Mobile Apps, you should consider first completing the Azure Mobile Apps quickstart tutorial. In questa Guida, l'attenzione è posta sull'SDK gestito sul lato client.In this guide, we focus on the client-side managed SDK. Per altre informazioni sugli SDK lato server per le app per dispositivi mobili, vedere la documentazione per .NET Server SDK o 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.

Documentazione di riferimentoReference documentation

La documentazione di riferimento per l'SDK per client è disponibile qui: riferimento al client .NET di App per dispositivi mobili di Azure.The reference documentation for the client SDK is located here: Azure Mobile Apps .NET client reference. È anche possibile trovare alcuni esempi per client nel repository GitHub degli esempi di Azure.You can also find several client samples in the Azure-Samples GitHub repository.

Piattaforme supportateSupported Platforms

La piattaforma .NET supporta le seguenti piattaforme:The .NET Platform supports the following platforms:

  • Versioni Android di Xamarin per API da 19 a 24 (KitKat tramite Nougat)Xamarin Android releases for API 19 through 24 (KitKat through Nougat)
  • Versioni iOS di Xamarin per le versioni iOS 8.0 e successiveXamarin iOS releases for iOS versions 8.0 and later
  • Piattaforma UWP (Universal Windows Platform)Universal Windows Platform
  • Windows Phone 8.1Windows Phone 8.1
  • Windows Phone 8.0, ad eccezione delle applicazioni SilverlightWindows Phone 8.0 except for Silverlight applications

L'autenticazione "flusso server" usa una visualizzazione Web per l'interfaccia utente presentata.The "server-flow" authentication uses a WebView for the presented UI. Se il dispositivo non è in grado di presentare una interfaccia utente con visualizzazione Web, sono necessari altri metodi di autenticazione.If the device is not able to present a WebView UI, then other methods of authentication are needed. Questo SDK non è quindi adatto per i dispositivi di tipo controllo o con restrizioni simili.This SDK is thus not suitable for Watch-type or similarly restricted devices.

Installazione e prerequisitiSetup and Prerequisites

Si presuppone che si sia già creato e pubblicato il progetto di back-end di App per dispositivi mobili, che include almeno una tabella.We assume that you have already created and published your Mobile App backend project, which includes at least one table. Nel codice usato in questo argomento la tabella è denominata TodoItem e si presenta con le colonne seguenti: Id, Text e Complete.In the code used in this topic, the table is named TodoItem and it has the following columns: Id, Text, and Complete. Si tratta della stessa tabella creata durante l'esercitazione introduttiva ad App per dispositivi mobili di Azure.This table is the same table created when you complete the Azure Mobile Apps quickstart.

Il tipo sul lato client tipizzato in C# è la classe seguente: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; }
}

Il valore di JsonPropertyAttribute viene usato per definire il mapping di PropertyName tra il campo del client e il campo della tabella.The JsonPropertyAttribute is used to define the PropertyName mapping between the client field and the table field.

Per informazioni su come creare le tabelle nel back-end di App per dispositivi mobili, vedere l'argomento .NET Server SDK o Node.js Server SDK.To learn how to create tables in your Mobile Apps backend, see the .NET Server SDK topic or the Node.js Server SDK topic. Se il back-end delle app per dispositivi mobili è stato creato nel portale di Azure mediante l'esercitazione introduttiva, è anche possibile usare l'impostazione Tabelle semplici del portale di Azure.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].

Procedura: Installare il pacchetto SDK client gestitoHow to: Install the managed client SDK package

Per installare il pacchetto SDK gestito da client per App per dispositivi mobili da NuGet attenersi a uno dei metodi seguenti:Use one of the following methods to install the managed client SDK package for Mobile Apps from NuGet:

  • Visual Studio Fare clic sul progetto con il pulsante destro del mouse, scegliere Gestisci pacchetti NuGet, cercare il pacchetto Microsoft.Azure.Mobile.Client e fare clic su Installa.Visual Studio Right-click your project, click Manage NuGet Packages, search for the Microsoft.Azure.Mobile.Client package, then click Install.
  • Xamarin Studio Fare clic sul progetto con il pulsante destro del mouse, scegliere Aggiungi>Aggiungi pacchetti NuGet, cercare il pacchetto Microsoft.Azure.Mobile.Client e fare clic su Aggiungi pacchetto.Xamarin Studio Right-click your project, click Add > Add NuGet Packages, search for the Microsoft.Azure.Mobile.Clientpackage, and then click Add Package.

Nel file dell'attività principale aggiungere l'istruzione using seguente:In your main activity file, remember to add the following using statement:

using Microsoft.WindowsAzure.MobileServices;

Procedura: Usare i simboli di debug in Visual StudioHow to: Work with debug symbols in Visual Studio

I simboli per lo spazio dei nomi di Microsoft.Azure.Mobile sono disponibili in SymbolSource.The symbols for the Microsoft.Azure.Mobile namespace are available on SymbolSource. Per l'integrazione di SymbolSource in Visual Studio, vedere le istruzioni di SymbolSource.Refer to the SymbolSource instructions to integrate SymbolSource with Visual Studio.

Creare il client di App per dispositivi mobiliCreate the Mobile Apps client

Il codice seguente crea l'oggetto MobileServiceClient che viene usato per accedere al back-end di App per dispositivi mobili.The following code creates the MobileServiceClient object that is used to access your Mobile App backend.

var client = new MobileServiceClient("MOBILE_APP_URL");

Nel codice precedente sostituire MOBILE_APP_URL con l'URL del back-end dell'App per dispositivi mobili, che si trova nel pannello relativo al back-end dell'App per dispositivi mobili nel portale di 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]. L'oggetto MobileServiceClient deve essere un singleton.The MobileServiceClient object should be a singleton.

Usare le tabelleWork with Tables

Nella sezione seguente viene illustrato come cercare e recuperare i record e modificare i dati all'interno della tabella.The following section details how to search and retrieve records and modify the data within the table. Vengono trattati gli argomenti seguenti:The following topics are covered:

Procedura: Creare un riferimento alla tabellaHow to: Create a table reference

Tutti i codici che accedono o modificano i dati nella tabella del back-end chiamano funzioni sull'oggetto MobileServiceTable .All the code that accesses or modifies data in a backend table calls functions on the MobileServiceTable object. Ottenere un riferimento alla tabella chiamando il metodo GetTable , nel modo seguente:Obtain a reference to the table by calling the GetTable method, as follows:

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

L'oggetto restituito usa il modello di serializzazione tipizzato.The returned object uses the typed serialization model. Viene supportato anche un modello di serializzazione non tipizzato.An untyped serialization model is also supported. L'esempio seguente crea un riferimento a una tabella non tipizzata:The following example [creates a reference to an untyped table]:

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

Nelle query non tipizzate, è necessario specificare la stringa di query OData sottostante.In untyped queries, you must specify the underlying OData query string.

Procedura: Eseguire query sui dati dall'app per dispositivi mobiliHow to: Query data from your Mobile App

Questa sezione descrive come eseguire query nel back-end di App per dispositivi mobili, incluse le funzionalità seguenti:This section describes how to issue queries to the Mobile App backend, which includes the following functionality:

Nota

Viene usata una dimensione di pagina basata sul server, per evitare la restituzione di tutte le righe.A server-driven page size is enforced to prevent all rows from being returned. Grazie al paging le richieste predefinite di set di dati di grandi dimensioni non hanno conseguenze negative sul servizio.Paging keeps default requests for large data sets from negatively impacting the service. Per restituire più di 50 righe, usare i metodi Skip e Take, come descritto in Restituire i dati in pagine.To return more than 50 rows, use the Skip and Take method, as described in Return data in pages.

Procedura: Filtrare i dati restituitiHow to: Filter returned data

Il codice seguente illustra come filtrare i dati includendo una clausola Where in una query.The following code illustrates how to filter data by including a Where clause in a query. Restituisce tutti gli elementi da todoTable per i quali la proprietà Complete è uguale a false.It returns all items from todoTable whose Complete property is equal to false. La funzione Where applica un predicato di filtro di riga alla query sulla tabella.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();

È possibile visualizzare l'URI della richiesta inviata al back-end usando un software di ispezione dei messaggi come gli strumenti di sviluppo per browser o Fiddler.You can view the URI of the request sent to the backend by using message inspection software, such as browser developer tools or Fiddler. Nell'URI della richiesta notare che la stringa di query è modificata:If you look at the request URI, notice that the query string is modified:

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

Questa richiesta OData viene convertita in una query SQL da un SDK del server:This OData request is translated into an SQL query by the Server SDK:

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

La funzione passata al metodo Where può avere un numero di condizioni arbitrario.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();

Questo esempio viene convertito in una query SQL dall'SDK del server: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

Questa query può anche essere suddivisa in più clausole: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();

I due metodi si equivalgono e possono essere utilizzati in modo intercambiabile.The two methods are equivalent and may be used interchangeably. La prima opzione, che prevede la concatenazione di più predicati in una query, è più compatta ed è consigliata.The former option—of concatenating multiple predicates in one query—is more compact and recommended.

La clausola Where supporta operazioni che vengono convertite nel subset OData.The Where clause supports operations that be translated into the OData subset. Alcune operazioni sono:Operations include:

  • Operatori relazionali (==, !=, <, <=, >, >=)Relational operators (==, !=, <, <=, >, >=),
  • Operatori aritmetici (+, -, /, *, %)Arithmetic operators (+, -, /, *, %),
  • Approssimazione dei numeri (Math.Floor, Math.Ceiling)Number precision (Math.Floor, Math.Ceiling),
  • Funzioni di stringa (Length, Substring, Replace, IndexOf, StartsWith, EndsWith)String functions (Length, Substring, Replace, IndexOf, StartsWith, EndsWith),
  • Proprietà relative alla data (Year, Month, Day, Hour, Minute, Second)Date properties (Year, Month, Day, Hour, Minute, Second),
  • Proprietà di accesso di un oggettoAccess properties of an object, and
  • Espressioni che combinano queste operazioni.Expressions combining any of these operations.

Per determinare gli elementi supportati dall'SDK del server, vedere la documentazione relativa a OData v3.When considering what the Server SDK supports, you can consider the [OData v3 Documentation].

Procedura: Ordinare i dati restituitiHow to: Sort returned data

Il codice seguente illustra come ordinare i dati includendo una funzione OrderBy o OrderByDescending nella query.The following code illustrates how to sort data by including an OrderBy or OrderByDescending function in the query. L'operazione restituisce elementi della tabella todoTable in ordine crescente in base al campo 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();

Procedura: Restituire i dati in pagineHow to: Return data in pages

Per impostazione predefinita, il server restituisce solo le prime 50 righe.By default, the backend returns only the first 50 rows. È possibile aumentare il numero di righe restituite mediante una chiamata al metodo Take .You can increase the number of returned rows by calling the Take method. Usare Take insieme al metodo Skip per richiedere una "pagina" specifica dell'intero set di dati restituito dalla query.Use Take along with the Skip method to request a specific "page" of the total dataset returned by the query. La query seguente, se eseguita, restituisce le prime tre voci della tabella.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();

La query modificata seguente ignora i primi tre risultati e restituisce i tre risultati successivi.The following revised query skips the first three results and returns the next three results. La query produce la seconda "pagina" di dati, la cui dimensione corrisponde a tre voci.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();

Il metodo IncludeTotalCount richiede il conteggio totale di tutti i record che sarebbero stati restituiti ignorando qualsiasi clausola di limite/paging specificata: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();

In un'app reale è possibile usare query simili all'esempio precedente con un controllo pager o un'interfaccia utente paragonabile per passare da una pagina all'altra.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.

Nota

Per ignorare il limite di 50 righe in un back-end di App per dispositivi mobili, è necessario anche applicare l'attributo EnableQueryAttribute al metodo pubblico GET e specificare il comportamento di paging.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. Se applicato al metodo, l'attributo seguente imposta il numero massimo di righe restituite su 1000:When applied to the method, the following sets the maximum returned rows to 1000:

[EnableQuery(MaxTop=1000)]

Procedura: Selezionare colonne specificheHow to: Select specific columns

È possibile specificare il set di proprietà da includere nei risultati aggiungendo alla query una clausola Select .You can specify which set of properties to include in the results by adding a Select clause to your query. Ad esempio, nel codice seguente viene illustrato come selezionare un solo campo e come selezionare e formattare più campi: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();

Tutte le funzioni descritte in precedenza sono di tipo additivo ed è quindi possibile usare la concatenazione.All the functions described so far are additive, so we can keep chaining them. Ogni chiamata concatenata incide ulteriormente sulla query.Each chained call affects more of the query. Un altro esempio: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();

Procedura: Cercare dati in base all'IDHow to: Look up data by ID

Per cercare oggetti dal database caratterizzati da un particolare ID, è possibile utilizzare la funzione LookupAsync .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");

Procedura: eseguire query non tipizzateHow to: Execute untyped queries

Quando si esegue una query usando un oggetto di tabella non tipizzata, è necessario specificare esplicitamente la stringa di query OData eseguendo una chiamata a ReadAsync, come nell'esempio seguente: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");

Si ottengono valori JSON utilizzabili come contenitore delle proprietà.You get back JSON values that you can use like a property bag. Per altre informazioni su JToken e Newtonsoft Json.NET, visitare il sito Json.NET .For more information on JToken and Newtonsoft Json.NET, see the Json.NET site.

Procedura: Inserire dati in un back-end di App per dispositivi mobiliHow to: Insert data into a Mobile App backend

Tutti i tipi di client devono contenere un membro denominato Id, che per impostazione predefinita è una stringa.All client types must contain a member named Id, which is by default a string. Questo Id è necessario per eseguire le operazioni CRUD e per la sincronizzazione offline. Il codice seguente illustra come usare il metodo InsertAsync per inserire nuove righe in una tabella.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. Il parametro contiene i dati da inserire come oggetto .NET.The parameter contains the data to be inserted as a .NET object.

await todoTable.InsertAsync(todoItem);

Se nell'elemento todoItem non è incluso un valore ID univoco personalizzato durante un inserimento, il server genera un GUID.If a unique custom ID value is not included in the todoItem during an insert, a GUID is generated by the server. È possibile recuperare l'ID generato controllando l'oggetto al termine della chiamata.You can retrieve the generated Id by inspecting the object after the call returns.

Per inserire dati non tipizzati, è possibile usare 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);

Di seguito è riportato un esempio con un indirizzo di posta elettronica come ID di stringa univoco: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);

Uso di valori IDWorking with ID values

App per dispositivi mobili supporta valori di stringa univoci personalizzati per la colonna id della tabella.Mobile Apps supports unique custom string values for the table's id column. Un valore di stringa consente alle applicazioni di usare valori personalizzati come indirizzi e-mail o nomi utente per l'ID.A string value allows applications to use custom values such as email addresses or user names for the ID. Gli ID stringa offrono i seguenti vantaggi:String IDs provide you with the following benefits:

  • Gli ID vengono generati senza creare un round trip al database.IDs are generated without making a round trip to the database.
  • L'unione di record da tabelle o database diversi risulta semplificata.Records are easier to merge from different tables or databases.
  • L'integrazione di valori di ID con la logica di un'applicazione è più efficace.IDs values can integrate better with an application's logic.

Quando un valore ID di stringa non è impostato su un record inserito, App per dispositivi mobili genera un valore univoco per l'ID.When a string ID value is not set on an inserted record, the Mobile App backend generates a unique value for the ID. È possibile usare il metodo Guid.NewGuid per generare valori ID personalizzati sul client o nel back-end.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"));

Procedura: Modificare dati in un back-end di App per dispositivi mobiliHow to: Modify data in a Mobile App backend

Il codice seguente illustra come usare il metodo UpdateAsync per aggiornare un record esistente con lo stesso ID con le nuove informazioni.The following code illustrates how to use the UpdateAsync method to update an existing record with the same ID with new information. Il parametro contiene i dati da aggiornare come oggetto .NET.The parameter contains the data to be updated as a .NET object.

await todoTable.UpdateAsync(todoItem);

Per eliminare dati non tipizzati, è possibile usare Json.NET come illustrato di seguito: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);

Quando si esegue un aggiornamento è necessario specificare un campo id .An id field must be specified when making an update. Il back-end usa il campo id per identificare la riga da aggiornare.The backend uses the id field to identify which row to update. È possibile ottenere il campo id dal risultato della chiamata InsertAsync.The id field can be obtained from the result of the InsertAsync call. Quando si tenta di aggiornare un elemento senza specificare il valore ArgumentException, viene generata un'eccezione id.An ArgumentException is raised if you try to update an item without providing the id value.

Procedura: Eliminare dati in un back-end di App per dispositivi mobiliHow to: Delete data in a Mobile App backend

Il codice seguente illustra come usare il metodo DeleteAsync per eliminare un'istanza esistente.The following code illustrates how to use the DeleteAsync method to delete an existing instance. L'istanza è identificata dal campo id impostato in todoItem.The instance is identified by the id field set on the todoItem.

await todoTable.DeleteAsync(todoItem);

Per eliminare dati non tipizzati, è possibile utilizzare Json.NET come illustrato di seguito: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);

Quando si esegue una richiesta di eliminazione, è necessario specificare un ID.When you make a delete request, an ID must be specified. Altre proprietà non vengono passate al servizio o vengono ignorate nel servizio.Other properties are not passed to the service or are ignored at the service. Il risultato di una chiamata DeleteAsync equivale in genere a null.The result of a DeleteAsync call is usually null. È possibile ottenere l'ID da passare dal risultato della chiamata InsertAsync .The ID to pass in can be obtained from the result of the InsertAsync call. Quando si tenta di eliminare un elemento senza specificare il campo id, viene generata un'eccezione MobileServiceInvalidOperationException.A MobileServiceInvalidOperationException is thrown when you try to delete an item without specifying the id field.

Procedura: Usare la concorrenza ottimistica per la risoluzione dei conflittiHow to: Use Optimistic Concurrency for conflict resolution

È possibile che due o più client scrivano modifiche nello stesso elemento contemporaneamente.Two or more clients may write changes to the same item at the same time. Se non viene rilevato un conflitto, l'ultima scrittura sovrascrive tutti gli aggiornamenti precedenti.Without conflict detection, the last write would overwrite any previous updates. controllo della concorrenza ottimistica presuppone che per ogni transazione sia possibile eseguire il commit, quindi non procede al blocco delle risorse.Optimistic concurrency control assumes that each transaction can commit and therefore does not use any resource locking. Prima di effettuare il commit di una transazione, il controllo della concorrenza ottimistica verifica che i dati non siano stati modificati da un'altra transazione.Before committing a transaction, optimistic concurrency control verifies that no other transaction has modified the data. Se i dati sono stati modificati, verrà eseguito il rollback di tale transazione.If the data has been modified, the committing transaction is rolled back.

App per dispositivi mobili supporta il controllo della concorrenza ottimistica tenendo traccia delle modifiche apportate a ogni elemento, usando la colonna di proprietà di sistema version definita per ogni tabella nel back-end di App per dispositivi mobili.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. Ogni volta che un record viene aggiornato, App per dispositivi mobili imposta la proprietà version per quel record su un nuovo valore.Each time a record is updated, Mobile Apps sets the version property for that record to a new value. Durante ogni richiesta di aggiornamento, la proprietà version del record inclusa nella richiesta viene confrontata con la stessa proprietà relativa al record sul server.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. Se la versione passata con la richiesta non corrisponde a quella del back-end, la libreria client genera un'eccezione MobileServicePreconditionFailedException<T> .If the version passed with the request does not match the backend, then the client library raises a MobileServicePreconditionFailedException<T> exception. Il tipo incluso nell'eccezione corrisponde al record del back-end contenente la versione dei server del record.The type included with the exception is the record from the backend containing the servers version of the record. L'applicazione può quindi usare questa informazione per decidere se eseguire nuovamente la richiesta di aggiornamento con il valore version corretto dal back-end per effettuare il commit delle modifiche.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.

Per abilitare la concorrenza ottimistica, definire una colonna sulla classe di tabella per la proprietà di sistema version .Define a column on the table class for the version system property to enable optimistic concurrency. Ad esempio: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; }
}

Le applicazioni che usano tabelle non tipizzate abilitano la concorrenza ottimistica impostando il flag Version per SystemProperties della tabella, come mostrato di seguito.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;

Oltre ad abilitare la concorrenza ottimistica, è necessario individuare l'eccezione MobileServicePreconditionFailedException<T> nel codice quando si esegue una chiamata a UpdateAsync.In addition to enabling optimistic concurrency, you must also catch the MobileServicePreconditionFailedException<T> exception in your code when calling UpdateAsync. Risolvere il conflitto applicando il valore corretto version al record aggiornato ed eseguire una chiamata a UpdateAsync con il record risolto.Resolve the conflict by applying the correct version to the updated record and call UpdateAsync with the resolved record. Il codice seguente illustra come risolvere un conflitto di scrittura, qualora venga rilevato.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 resoltion 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();
}

Per altre informazioni, vedere l'argomento Sincronizzazione di dati offline nelle App per dispositivi mobili di Azure .For more information, see the [Offline Data Sync in Azure Mobile Apps] topic.

Procedura: Associare dati di App per dispositivi mobili a un'interfaccia utente WindowsHow to: Bind Mobile Apps data to a Windows user interface

Questa sezione illustra come visualizzare gli oggetti dati restituiti usando elementi dell'interfaccia utente in un'app Windows.This section shows how to display returned data objects using UI elements in a Windows app. L'esempio di codice seguente associa all'origine dell'elenco una query per la ricerca di elementi non completati.The following example code binds to the source of the list with a query for incomplete items. MobileServiceCollection crea una raccolta di associazione compatibile con App per dispositivi mobili.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;

Alcuni controlli del runtime gestito supportano un'interfaccia denominata ISupportIncrementalLoading.Some controls in the managed runtime support an interface called ISupportIncrementalLoading. Questa interfaccia consente ai controlli di richiedere dati aggiuntivi nello scorrimento verso il basso.This interface allows controls to request extra data when the user scrolls. Per questa interfaccia per le app di Windows universale è disponibile un supporto incorporato tramite MobileServiceIncrementalLoadingCollection, che gestisce automaticamente le chiamate dai controlli.There is built-in support for this interface for universal Windows apps via MobileServiceIncrementalLoadingCollection, which automatically handles the calls from the controls. Usare MobileServiceIncrementalLoadingCollection nelle app di Windows come indicato di seguito: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;

Per usare la nuova raccolta in app di Windows Phone 8 e "Silverlight", usare i metodi di estensione ToCollection su IMobileServiceTableQuery<T> e IMobileServiceTable<T>.To use the new collection on Windows Phone 8 and "Silverlight" apps, use the ToCollection extension methods on IMobileServiceTableQuery<T> and IMobileServiceTable<T>. Per caricare i dati, chiamare LoadMoreItemsAsync().To load data, call LoadMoreItemsAsync().

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

Quando si usa la raccolta creata tramite la chiamata a ToCollectionAsync o ToCollection, si ottiene una raccolta che può essere associata ai controlli dell'interfaccia utente.When you use the collection created by calling ToCollectionAsync or ToCollection, you get a collection that can be bound to UI controls. Questa raccolta è compatibile con il paging.This collection is paging-aware. Poiché la raccolta sta caricando i dati dalla rete, talvolta il caricamento ha esito negativo.Since the collection is loading data from the network, loading sometimes fails. Per risolvere questi errori, eseguire l'override del metodo OnException in MobileServiceIncrementalLoadingCollection per gestire le eccezioni derivanti da chiamate a LoadMoreItemsAsync.To handle such failures, override the OnException method on MobileServiceIncrementalLoadingCollection to handle exceptions resulting from calls to LoadMoreItemsAsync.

Si supponga che la tabella sia costituita da molti campi, ma che si desideri visualizzarne solo alcuni nel controllo.Consider if your table has many fields but you only want to display some of them in your control. È possibile seguire le indicazioni riportate nella sezione "Selezionare colonne specifiche" precedente per scegliere specifiche colonne da visualizzare nell'interfaccia utente.You may use the guidance in the preceding section "Select specific columns" to select specific columns to display in the UI.

Modificare le dimensioni di paginaChange the Page size

Per impostazione predefinita, App per dispositivi mobili di Azure restituisce un massimo di 50 elementi per ogni richiesta.Azure Mobile Apps returns a maximum of 50 items per request by default. È possibile modificare la dimensione del paging aumentando le dimensioni massime della pagina nel client e nel server.You can change the paging size by increasing the maximum page size on both the client and server. Per aumentare le dimensioni richieste, specificare PullOptions quando si usa PullAsync():To increase the requested page size, specify PullOptions when using PullAsync():

PullOptions pullOptions = new PullOptions
    {
        MaxPageSize = 100
    };

Se il valore di PageSize è impostato in modo da essere uguale a o maggiore di 100 all'interno del server, verranno restituiti al massimo 100 elementi.Assuming you have made the PageSize equal to or greater than 100 within the server, a request returns up to 100 items.

Usare le tabelle offlineWork with Offline Tables

Le tabelle offline usano un archivio SQLite locale per archiviare dati da usare in modalità offline.Offline tables use a local SQLite store to store data for use when offline. Tutte le operazioni delle tabelle vengono eseguite nell'archivio SQLite locale anziché nell'archivio sul server remoto.All table operations are done against the local SQLite store instead of the remote server store. Per creare una tabella offline è necessario innanzitutto preparare il progetto:To create an offline table, first prepare your project:

  1. In Visual Studio fare clic con il pulsante destro del mouse sulla soluzione > Gestisci pacchetti NuGet per la soluzione, quindi cercare e installare il pacchetto NuGet Microsoft.Azure.Mobile.Client.SQLiteStore per tutti i progetti della soluzione.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. (Facoltativo) Per supportare i dispositivi Windows, installare uno dei pacchetti di runtime SQLite seguenti:(Optional) To support Windows devices, install one of the following SQLite runtime packages:

  3. (Facoltativo).(Optional). Per i dispositivi Windows fare clic su Riferimenti > Aggiungi riferimento, espandere la cartella Windows > Estensioni, quindi abilitare SQLite for Windows Runtime SDK con Visual C++ 2013 Runtime 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. I nomi degli SDK di SQLite sono leggermente diversi per ogni piattaforma Windows.The SQLite SDK names vary slightly with each Windows platform.

Prima di poter creare un riferimento alla tabella è necessario preparare l'archivio locale: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);

L'inizializzazione dell'archivio di solito viene effettuata immediatamente dopo aver creato il client.Store initialization is normally done immediately after the client is created. OfflineDbPath deve essere un nome di file appropriato per l'uso in tutte le piattaforme supportate.The OfflineDbPath should be a filename suitable for use on all platforms that you support. Se il percorso è completo (ovvero inizia con una barra), viene usato il percorso.If the path is a fully qualified path (that is, it starts with a slash), then that path is used. Se il percorso non è completo, il file viene posizionato in un percorso che dipende dalla piattaforma.If the path is not fully qualified, the file is placed in a platform-specific location.

  • Per i dispositivi iOS e Android il percorso predefinito è la cartella "File personali".For iOS and Android devices, the default path is the "Personal Files" folder.
  • Per i dispositivi Windows il percorso predefinito è la cartella "AppData" specifica dell'applicazione.For Windows devices, the default path is the application-specific "AppData" folder.

È possibile ottenere un riferimento alla tabella usando il metodo GetSyncTable<>:A table reference can be obtained using the GetSyncTable<> method:

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

Per usare una tabella offline non è necessario eseguire l'autenticazione.You do not need to authenticate to use an offline table. È necessario eseguire l'autenticazione solo quando si comunica con il servizio back-end.You only need to authenticate when you are communicating with the backend service.

Sincronizzazione di una tabella offlineSyncing an Offline Table

Per impostazione predefinita le tabelle offline non sono sincronizzate con il back-end.Offline tables are not synchronized with the backend by default. La sincronizzazione è suddivisa in due parti.Synchronization is split into two pieces. È possibile inserire le modifiche separatamente rispetto al download di nuovi elementi.You can push changes separately from downloading new items. Ecco un metodo di sincronizzazione tipico: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"]);
        }
    }
}

Se il primo argomento di PullAsync è null, non viene usata la sincronizzazione incrementale.If the first argument to PullAsync is null, then incremental sync is not used. Ogni operazione di sincronizzazione recupera tutti i record.Each sync operation retrieves all records.

L'SDK esegue un PushAsync() implicito prima di estrarre i record.The SDK performs an implicit PushAsync() before pulling records.

La gestione dei conflitti viene eseguita su un metodo PullAsync().Conflict handling happens on a PullAsync() method. È possibile gestire i conflitti allo stesso modo delle tabelle in linea.You can deal with conflicts in the same way as online tables. Il conflitto viene generato quando viene chiamato PullAsync() al posto di durante l'inserimento, l'aggiornamento o l'eliminazione.The conflict is produced when PullAsync() is called instead of during the insert, update, or delete. Se si verificano più conflitti, vengono aggregati in un singolo MobileServicePushFailedException.If multiple conflicts happen, they are bundled into a single MobileServicePushFailedException. Gestire separatamente ogni errore.Handle each failure separately.

Usare un'API personalizzataWork with a custom API

Un'API personalizzata consente di definire endpoint personalizzati che espongono la funzionalità del server di cui non è possibile eseguire il mapping a un'operazione di inserimento, aggiornamento, eliminazione o lettura.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. L'utilizzo di un'API personalizzata offre maggiore controllo sulla messaggistica, incluse la lettura e l'impostazione delle intestazioni del messaggio HTTP e la definizione di un formato del corpo del messaggio diverso da 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.

Per chiamare un'API personalizzata, è sufficiente chiamare uno dei metodi InvokeApiAsync sul client.You call a custom API by calling one of the InvokeApiAsync methods on the client. Ad esempio, la riga di codice seguente invia una richiesta POST all'API completeAll sul back-end: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);

Questo formato è una chiamata tipizzata al metodo, che richiede che il tipo restituito MarkAllResult sia definito.This form is a typed method call and requires that the MarkAllResult return type is defined. Sono supportati sia i metodi tipizzati, sia quelli non tipizzati.Both typed and untyped methods are supported.

Il metodo InvokeApiAsync() antepone "/api/" all'API che si desidera chiamare, a meno che l'API non inizi con una "/".The InvokeApiAsync() method prepends '/api/' to the API that you wish to call unless the API starts with a '/'. Ad esempio:For example:

  • InvokeApiAsync("completeAll",...) chiama /api/completeAll nel back-endInvokeApiAsync("completeAll",...) calls /api/completeAll on the backend
  • InvokeApiAsync("/.auth/me",...) chiama /.auth/me nel back-endInvokeApiAsync("/.auth/me",...) calls /.auth/me on the backend

È possibile utilizzare InvokeApiAsync per chiamare qualsiasi API Web, tra cui le API Web che non sono definite con App per dispositivi mobili di Azure.You can use InvokeApiAsync to call any WebAPI, including those WebAPIs that are not defined with Azure Mobile Apps. Quando si utilizza InvokeApiAsync(), le intestazioni appropriate, incluse le intestazioni di autenticazione, vengono inviate con la richiesta.When you use InvokeApiAsync(), the appropriate headers, including authentication headers, are sent with the request.

Autenticare gli utentiAuthenticate users

App per dispositivi mobili supporta l'autenticazione e l'autorizzazione di utenti di app tramite diversi provider di identità esterni: Facebook, Google, Microsoft Account, Twitter e Azure Active Directory.Mobile Apps supports authenticating and authorizing app users using various external identity providers: Facebook, Google, Microsoft Account, Twitter, and Azure Active Directory. È possibile impostare le autorizzazioni per le tabelle per limitare l'accesso per operazioni specifiche solo agli utenti autenticati.You can set permissions on tables to restrict access for specific operations to only authenticated users. È inoltre possibile utilizzare l'identità degli utenti autenticati per implementare regole di autorizzazione negli script del server.You can also use the identity of authenticated users to implement authorization rules in server scripts. Per altre informazioni, vedere l'esercitazione Aggiungere l'autenticazione all'app di Servizi mobili.For more information, see the tutorial [Add authentication to your app].

Sono supportati due flussi di autenticazione: flusso gestito dal client e flusso gestito dal server.Two authentication flows are supported: client-managed and server-managed flow. Il flusso gestito dal server è il processo di autenticazione più semplice, poiché si basa sull'interfaccia di autenticazione Web del provider.The server-managed flow provides the simplest authentication experience, as it relies on the provider's web authentication interface. Il flusso gestito dal client assicura una maggiore integrazione con funzionalità specifiche del dispositivo, poiché si basa su SDK specifici del provider e del dispositivo.The client-managed flow allows for deeper integration with device-specific capabilities as it relies on provider-specific device-specific SDKs.

Nota

Nelle app di produzione è consigliabile usare un flusso gestito dal client.We recommend using a client-managed flow in your production apps.

Per configurare l'autenticazione, è necessario registrare l'app con uno o più provider di identità.To set up authentication, you must register your app with one or more identity providers. Il provider di identità genera un ID client e un segreto client per l'app.The identity provider generates a client ID and a client secret for your app. Questi valori vengono quindi impostati nel back-end per abilitare l'autenticazione/l'autorizzazione del Servizio app di Azure.These values are then set in your backend to enable Azure App Service authentication/authorization. Per altre informazioni, seguire le istruzioni dettagliate dell'esercitazione Aggiungere l'autenticazione all'app di Servizi mobili.For more information, follow the detailed instructions in the tutorial [Add authentication to your app].

Questo articolo descrive gli argomenti seguenti:The following topics are covered in this section:

Autenticazione gestita dal clientClient-managed authentication

L'app può contattare il provider di identità in modo indipendente e quindi fornire il token restituito durante l'accesso con il back-end.Your app can independently contact the identity provider and then provide the returned token during login with your backend. Mediante il flusso client è possibile consentire agli utenti di effettuare l'accesso un'unica volta o recuperare dal provider di identità dati utente aggiuntivi.This client flow enables you to provide a single sign-on experience for users or to retrieve additional user data from the identity provider. L'autenticazione del flusso client è preferibile rispetto all'uso di un flusso server, perché l'SDK del provider di identità garantisce un'esperienza utente più naturale e consente una maggiore personalizzazione.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.

Vengono forniti esempi per i modelli di autenticazione del flusso client seguenti:Examples are provided for the following client-flow authentication patterns:

Autenticare gli utenti con Active Directory Authentication LibraryAuthenticate users with the Active Directory Authentication Library

È possibile usare Active Directory Authentication Library (ADAL) per avviare l'autenticazione degli utenti dal client usando l'autenticazione di 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. Configurare il back-end dell'app per dispositivi mobili per l'accesso ad Azure Active Directory seguendo l'esercitazione Come configurare un'applicazione del servizio app per usare l'account di accesso di Azure Active Directory.Configure your mobile app backend for AAD sign-on by following the [How to configure App Service for Active Directory login] tutorial. Assicurarsi di completare il passaggio facoltativo di registrazione di un'applicazione client nativa.Make sure to complete the optional step of registering a native client application.
  2. In Visual Studio o Xamarin Studio aprire il progetto e aggiungere un riferimento al pacchetto NuGet Microsoft.IdentityModel.CLients.ActiveDirectory .In Visual Studio or Xamarin Studio, open your project and add a reference to the Microsoft.IdentityModel.CLients.ActiveDirectory NuGet package. Includere nella ricerca le versioni non definitive.When searching, include pre-release versions.
  3. Aggiungere il codice seguente all'applicazione, in base alla piattaforma usata.Add the following code to your application, according to the platform you are using. Apportare le sostituzioni seguenti:In each, make the following replacements:

    • Sostituire INSERT-AUTHORITY-HERE con il nome del tenant in cui è stato eseguito il provisioning dell'applicazione.Replace INSERT-AUTHORITY-HERE with the name of the tenant in which you provisioned your application. Il formato deve essere https://login.microsoftonline.com/contoso.onmicrosoft.com. È possibile copiare questo valore dalla scheda Dominio di Azure Active Directory nel portale di Azure classico.The format should be https://login.microsoftonline.com/contoso.onmicrosoft.com. This value can be copied from the Domain tab in your Azure Active Directory in the [Azure classic portal].
    • Sostituire INSERT-RESOURCE-ID-HERE con l'ID client per il back-end dell'app per dispositivi mobili.Replace INSERT-RESOURCE-ID-HERE with the client ID for your mobile app backend. L'ID client è disponibile nella scheda Avanzate in Impostazioni di Azure Active Directory nel portale.You can obtain the client ID from the Advanced tab under Azure Active Directory Settings in the portal.
    • Sostituire INSERT-CLIENT-ID-HERE con l'ID client copiato dall'applicazione client nativa.Replace INSERT-CLIENT-ID-HERE with the client ID you copied from the native client application.
    • Sostituire INSERT-REDIRECT-URI-HERE con l'endpoint /.auth/login/done del sito, usando lo schema HTTPS.Replace INSERT-REDIRECT-URI-HERE with your site's /.auth/login/done endpoint, using the HTTPS scheme. Questo valore deve essere simile a https://contoso.azurewebsites.net/.auth/login/done.This value should be similar to https://contoso.azurewebsites.net/.auth/login/done.

      Il codice necessario per ogni piattaforma è riportato di seguito: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);
      }
      

Accesso singolo usando un token da Facebook o GoogleSingle Sign-On using a token from Facebook or Google

È possibile usare il flusso client come illustrato in questo frammento di codice per Facebook o 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();
    }
}

Accesso Single Sign-On tramite account Microsoft con Live SDKSingle Sign On using Microsoft Account with the Live SDK

Per autenticare gli utenti, è necessario registrare l'app presso il centro per sviluppatori degli account Microsoft.To authenticate users, you must register your app at the Microsoft account Developer Center. Configurare i dettagli di registrazione nel back-end dell'app per dispositivi mobili.Configure the registration details on your Mobile App backend. Per creare la registrazione di un account Microsoft e connetterlo al back-end dell'app per dispositivi mobili, completare i passaggi nell'articolo Come configurare l'applicazione del servizio app per usare l'account di accesso Microsoft.To create a Microsoft account registration and connect it to your Mobile App backend, complete the steps in [Register your app to use a Microsoft account login]. Se si dispone di entrambe le versioni dell'app (Windows Store e Windows Phone 8/Silverlight), registrare prima la versione di Windows Store.If you have both Windows Store and Windows Phone 8/Silverlight versions of your app, register the Windows Store version first.

Il codice seguente esegue l'autenticazione usando Live SDK e usa il token restituito per accedere al back-end di App per i dispositivi mobili.The following code authenticates using Live SDK and uses the returned token to sign in to your Mobile App backend.

private LiveConnectSession session;
    //private static string clientId = "<microsoft-account-client-id>";
private async System.Threading.Tasks.Task AuthenticateAsync()
{

    // Get the URL the Mobile App backend.
    var serviceUrl = App.MobileService.ApplicationUri.AbsoluteUri;

    // Create the authentication client for Windows Store using the service URL.
    LiveAuthClient liveIdClient = new LiveAuthClient(serviceUrl);
    //// Create the authentication client for Windows Phone using the client ID of the registration.
    //LiveAuthClient liveIdClient = new LiveAuthClient(clientId);

    while (session == null)
    {
        // Request the authentication token from the Live authentication service.
        // The wl.basic scope should always be requested.  Other scopes can be added
        LiveLoginResult result = await liveIdClient.LoginAsync(new string[] { "wl.basic" });
        if (result.Status == LiveConnectSessionStatus.Connected)
        {
            session = result.Session;

            // Get information about the logged-in user.
            LiveConnectClient client = new LiveConnectClient(session);
            LiveOperationResult meResult = await client.GetAsync("me");

            // Use the Microsoft account auth token to sign in to App Service.
            MobileServiceUser loginResult = await App.MobileService
                .LoginWithMicrosoftAccountAsync(result.Session.AuthenticationToken);

            // Display a personalized sign-in greeting.
            string title = string.Format("Welcome {0}!", meResult.Result["first_name"]);
            var message = string.Format("You are now logged in - {0}", loginResult.UserId);
            var dialog = new MessageDialog(message, title);
            dialog.Commands.Add(new UICommand("OK"));
            await dialog.ShowAsync();
        }
        else
        {
            session = null;
            var dialog = new MessageDialog("You must log in.", "Login Required");
            dialog.Commands.Add(new UICommand("OK"));
            await dialog.ShowAsync();
        }
    }
}

Per altre informazioni, vedere la documentazione su Windows Live SDK .For more information, see the Windows Live SDK documentation.

Autenticazione gestita dal serverServer-managed authentication

Dopo avere eseguito la registrazione del provider di identità, chiamare il metodo LoginAsync su [MobileServiceClient] con il valore MobileServiceAuthenticationProvider del provider.Once you have registered your identity provider, call the LoginAsync method on the [MobileServiceClient] with the MobileServiceAuthenticationProvider value of your provider. Ad esempio, con il codice seguente viene avviato un accesso al flusso server mediante 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();
    }
}

Se si usa un provider di identità diverso da Facebook, sostituire il valore di MobileServiceAuthenticationProvider con il nome del provider.If you are using an identity provider other than Facebook, change the value of MobileServiceAuthenticationProvider to the value for your provider.

In un flusso server, il Servizio app di Azure gestisce il flusso di autenticazione OAuth visualizzando la pagina di accesso del provider selezionato.In a server flow, Azure App Service manages the OAuth authentication flow by displaying the sign-in page of the selected provider. Una volta tornato al provider di identità, il Servizio app di Azure genera un token di autenticazione del servizio app.Once the identity provider returns, Azure App Service generates an App Service authentication token. Il metodo LoginAsync restituisce un utente MobileServiceUser, che fornisce sia un elemento UserId dell'utente autenticato sia un elemento MobileServiceAuthenticationToken sotto forma di token JSON Web (JWT).The LoginAsync method returns a MobileServiceUser, which provides both the UserId of the authenticated user and the MobileServiceAuthenticationToken, as a JSON web token (JWT). È possibile memorizzare questo token nella cache e riutilizzarlo fino alla scadenza.This token can be cached and reused until it expires. Per ulteriori informazioni, vedere Memorizzazione nella cache del token di autenticazione.For more information, see Caching the authentication token.

Memorizzazione nella cache del token di autenticazioneCaching the authentication token

In alcuni casi, la chiamata al metodo di accesso può essere evitata dopo la prima autenticazione riuscita, archiviando il token di autenticazione del provider.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. Le app di Windows Store e UWP possono usare PasswordVault per memorizzare nella cache il token di autenticazione corrente dopo un accesso riuscito, come indicato di seguito:Windows 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));

Il valore UserId viene archiviato come UserName delle credenziali e il token viene archiviato come Password.The UserId value is stored as the UserName of the credential and the token is the stored as the Password. Negli avvii successivi è possibile usare PasswordVault per verificare le credenziali memorizzate nella cache.On subsequent start-ups, you can check the PasswordVault for cached credentials. L'esempio seguente usa le credenziali memorizzate nella cache quando vengono trovate e, in caso contrario, prova a eseguire di nuovo l'autenticazione con il back-end: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.
}

Quando si disconnette un utente, è necessario rimuovere anche le credenziali archiviate, come indicato di seguito: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));

Le app Xamarin usano le API Xamarin.Auth per archiviare in modo sicuro le credenziali in un oggetto Account .Xamarin apps use the Xamarin.Auth APIs to securely store credentials in an Account object. Per un esempio dell'uso di queste API, vedere il file di codice AuthStore.cs nell'esempio di condivisione di foto di ContosoMoments.For an example of using these APIs, see the AuthStore.cs code file in the ContosoMoments photo sharing sample.

Quando si usa l'autenticazione gestita dal client, è anche possibile memorizzare nella cache il token di accesso fornito dal provider, ad esempio Facebook o Twitter.When you use client-managed authentication, you can also cache the access token obtained from your provider such as Facebook or Twitter. Questo token può essere fornito per richiedere un nuovo token di autenticazione dal back-end, come indicato di seguito: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);

Notifiche pushPush Notifications

Gli argomenti seguenti descrivono le notifiche push:The following topics cover Push Notifications:

Procedura: Registrarsi per le notifiche pushHow to: Register for Push Notifications

Il client di App per dispositivi mobili consente di registrarsi per le notifiche push con Hub di notifica di Azure.The Mobile Apps client enables you to register for push notifications with Azure Notification Hubs. Durante la registrazione, si ottiene un handle fornito dal servizio di notifica push specifico della piattaforma.When registering, you obtain a handle that you obtain from the platform-specific Push Notification Service (PNS). È quindi possibile specificare questo valore con qualsiasi tag al momento della creazione della registrazione.You then provide this value along with any tags when you create the registration. Il codice seguente registra l'app Windows per le notifiche push mediante il Servizio di notifica Windows (WNS):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);
}

Se si effettua il push a WNS, è necessario ottenere un SID pacchetto di Windows Store (vedere sotto).If you are pushing to WNS, then you MUST obtain a Windows Store package SID. Per ulteriori informazioni sulle app di Windows, compresa la modalità di registrazione per le registrazioni del modello, vedere Aggiungere notifiche push all'app.For more information on Windows apps, including how to register for template registrations, see [Add push notifications to your app].

La richiesta di tag dal client non è supportata.Requesting tags from the client is not supported. Le richieste di tag vengono eliminate automaticamente dalla registrazione.Tag Requests are silently dropped from registration. Se si desidera registrare il dispositivo con tag, creare un'API personalizzata che usa l'API di hub di notifica per eseguire la registrazione automaticamente.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. Eseguire una chiamata all'API personalizzata invece che al metodo RegisterNativeAsync().Call the Custom API instead of the RegisterNativeAsync() method.

Procedura: ottenere un SID pacchetto di Windows StoreHow to: Obtain a Windows Store package SID

Per abilitare le notifiche push nelle app di Windows Store è necessario un SID pacchetto.A package SID is needed for enabling push notifications in Windows Store apps. Per ricevere un SID pacchetto, registrare l'applicazione in Windows Store.To receive a package SID, register your application with the Windows Store.

Per ottenere questo valore:To obtain this value:

  1. In Esplora soluzioni di Visual Studio, fare clic con il pulsante destro del mouse sul progetto app di Windows Store, quindi scegliere Store > Associa applicazione a Store.In Visual Studio Solution Explorer, right-click the Windows Store app project, click Store > Associate App with the Store....
  2. Nella procedura guidata fare clic su Avanti, effettuare l'accesso con l'account Microsoft, immettere un nome per l'app in Riserva un nuovo nome dell'app e quindi fare clic su Riserva.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. Dopo la creazione della registrazione dell'app, selezionare il nome dell'app, fare clic su Avanti e quindi su Associa.After the app registration is successfully created, select the app name, click Next, and then click Associate.
  4. Accedere al Windows Dev Center con l'account Microsoft.Log in to the Windows Dev Center using your Microsoft Account. In App personalifare clic sulla registrazione dell'app creata.Under My apps, click the app registration you created.
  5. Fare clic su Gestione dell'app > Identità dell'app, e poi scorrere fino a trovare il SID pacchetto.Click App management > App identity, and then scroll down to find your Package SID.

In molti casi il SID pacchetto viene considerato come un URI ed è necessario usare ms-app: / / come schema.Many uses of the package SID treat it as a URI, in which case you need to use ms-app:// as the scheme. Prendere nota della versione del SID pacchetto formato tramite la concatenazione di questo valore come prefisso.Make note of the version of your package SID formed by concatenating this value as a prefix.

Le app di Xamarin richiedono codice aggiuntivo per registrare un'app in esecuzione sulle piattaforme Android o iOS.Xamarin apps require some additional code to be able to register an app running on the iOS or Android platforms. Per altre informazioni, vedere l'argomento relativo alla piattaforma in uso:For more information, see the topic for your platform:

Procedura: registrare modelli push per inviare notifiche multipiattaformaHow to: Register push templates to send cross-platform notifications

Per registrare i modelli, usare il metodo RegisterAsync() con i modelli, come indicato di seguito:To register templates, use the RegisterAsync() method with the templates, as follows:

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

I modelli sono di tipo JObject e possono contenere più modelli nel formato JSON seguente: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;
}

Il metodo RegisterAsync() accetta anche riquadri secondari:The method RegisterAsync() also accepts Secondary Tiles:

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

Tutti i tag vengono eliminati durante la registrazione per motivi di sicurezza.All tags are stripped away during registration for security. Per aggiungere tag alle istallazione o modelli all'interno delle istallazioni, vedere [Lavorare con l'SDK del server back-end .NET per App per dispositivi mobili di Azure].To add tags to installations or templates within installations, see [Work with the .NET backend server SDK for Azure Mobile Apps].

Per inviare notifiche usando questi modelli registrati, vedere l'argomento relativo alle API di Hub di notifica.To send notifications utilizing these registered templates, refer to the [Notification Hubs APIs].

Argomenti variMiscellaneous Topics

Procedura: Gestire gli erroriHow to: Handle errors

Quando si verifica un errore nel back-end, l'SDK del client genera MobileServiceInvalidOperationException.When an error occurs in the backend, the client SDK raises a MobileServiceInvalidOperationException. Nell'esempio seguente viene illustrato come gestire un'eccezione che viene restituita dal back-end: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
    }
}

Un altro esempio di gestione delle condizioni di errore è disponibile nell' esempio di file di App per dispositivi mobili.Another example of dealing with error conditions can be found in the [Mobile Apps Files Sample]. L'esempio LoggingHandler fornisce un gestore delegato di registrazione per registrare le richieste inoltrate al back-end.The LoggingHandler example provides a logging delegate handler to log the requests being made to the backend.

Procedura: Personalizzare le intestazioni delle richiesteHow to: Customize request headers

Per supportare lo scenario specifico dell'app, potrebbe essere necessario personalizzare la comunicazione con il back-end di App per dispositivi mobili.To support your specific app scenario, you might need to customize communication with the Mobile App backend. È possibile ad esempio aggiungere un'intestazione personalizzata a tutte le richieste in uscita oppure modificare i codici di stato delle risposte.For example, you may want to add a custom header to every outgoing request or even change responses status codes. È possibile usare un DelegatingHandler personalizzato, come illustrato nell'esempio seguente: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;
    }
}