Como usar o cliente gerenciado para Aplicativos Móveis do AzureHow to use the managed client for Azure Mobile Apps

Observação

O Visual Studio App Center dá suporte a serviços de ponta a ponta e integrados central ao desenvolvimento de aplicativos móveis.Visual Studio App Center supports end to end and integrated services central to mobile app development. Os desenvolvedores podem usar Compilar, testar e distribuir serviços para configurar o pipeline de integração e entrega contínua.Developers can use Build, Test and Distribute services to set up Continuous Integration and Delivery pipeline. Depois que o aplicativo é implantado, os desenvolvedores podem monitorar o status e o uso de seus aplicativos usando os serviços de análise e diagnóstico e se envolver com os usuários usando o serviço de envio por push .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. Os desenvolvedores também podem aproveitar a autenticação para autenticar seus usuários e o serviço de dados para manter e sincronizar dados de aplicativos na nuvem.Developers can also leverage Auth to authenticate their users and Data service to persist and sync app data in the cloud.

Se você estiver procurando integrar os serviços de nuvem em seu aplicativo móvel, Inscreva-se com o app Center hoje mesmo.If you are looking to integrate cloud services in your mobile application, sign up with App Center today.

Visão GeralOverview

Este guia mostra como executar cenários comuns usando a biblioteca de cliente gerenciado para os Aplicativos Móveis do Serviço de Aplicativo do Azure em aplicativos do 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 você for iniciante nos Aplicativos Móveis, primeiro conclua o tutorial Início rápido dos Aplicativos Móveis do Azure .If you are new to Mobile Apps, you should consider first completing the Azure Mobile Apps quickstart tutorial. Neste guia, abordaremos o SDK gerenciado do lado do cliente.In this guide, we focus on the client-side managed SDK. Para saber mais sobre os SDKs do lado do servidor para aplicativos móveis, consulte a documentação do SDK do servidor .net ou o SDK do servidor node. js.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.

Documentação de referênciaReference documentation

A documentação de referência para o SDK do cliente está localizada aqui: Referência do cliente do .NET dos Aplicativos Móveis do Azure.The reference documentation for the client SDK is located here: Azure Mobile Apps .NET client reference. Você também pode encontrar vários exemplos de cliente no Repositório GitHub Azure-Samples.You can also find several client samples in the Azure-Samples GitHub repository.

Plataformas com suporteSupported Platforms

A plataforma .NET dá suporte às seguintes plataformas:The .NET Platform supports the following platforms:

  • Versões de Xamarin Android para API 19 a 24 (KitKat usando Nougat)Xamarin Android releases for API 19 through 24 (KitKat through Nougat)
  • Versões de Xamarin iOS para versões 8.0 e posteriores do iOSXamarin iOS releases for iOS versions 8.0 and later
  • Plataforma Universal do WindowsUniversal Windows Platform
  • Windows Phone 8,1Windows Phone 8.1
  • Windows Phone 8.0, exceto para aplicativos SilverlightWindows Phone 8.0 except for Silverlight applications

A autenticação de "fluxo de servidor" usa um modo de exibição da Web para a interface do usuário apresentada.The "server-flow" authentication uses a WebView for the presented UI. Se o dispositivo não for capaz de apresentar uma interface do usuário do modo de exibição da Web, outros métodos de autenticação serão necessários.If the device is not able to present a WebView UI, then other methods of authentication are needed. Esse SDK, portanto, não é adequado para relógios ou dispositivos similarmente restritos.This SDK is thus not suitable for Watch-type or similarly restricted devices.

Configuração e pré-requisitosSetup and Prerequisites

Supomos que você já criou e publicou o projeto de back-end do Aplicativo Móvel, que inclui pelo menos uma tabela.We assume that you have already created and published your Mobile App backend project, which includes at least one table. No código usado neste tópico, a tabela é denominada TodoItem e tem as seguintes colunas: 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. Essa tabela é a mesma tabela criada quando você conclui o Tutorial de início rápido dos Aplicativos Móveis do Azure.This table is the same table created when you complete the Azure Mobile Apps quickstart.

O tipo em C# do lado do cliente tipado correspondente é a seguinte classe: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; }
}

O JsonPropertyAttribute é usado para definir o mapeamento de PropertyName entre o campo de cliente e o campo de tabela.The JsonPropertyAttribute is used to define the PropertyName mapping between the client field and the table field.

Para saber como criar tabelas em seu back-end de aplicativos móveis, consulte o tópico SDK do servidor .net ou o tópico SDK do servidor node. js.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 você tiver criado o back-end do Aplicativo Móvel no portal do Azure usando o Início Rápido, também poderá usar a configuração Tabelas Fáceis no Azure portal.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.

Como instalar o pacote SDK do cliente gerenciadoHow to: Install the managed client SDK package

Use um dos métodos a seguir para instalar o pacote SDK do cliente gerenciado para Aplicativos Móveis do NuGet:Use one of the following methods to install the managed client SDK package for Mobile Apps from NuGet:

  • No Visual Studio, clique com o botão direito do mouse no projeto, clique em Gerenciar Pacotes NuGet, pesquise pelo pacote Microsoft.Azure.Mobile.Client e clique em Instalar.Visual Studio Right-click your project, click Manage NuGet Packages, search for the Microsoft.Azure.Mobile.Client package, then click Install.
  • Xamarin Studio Clique com o botão direito do mouse em seu projeto, clique em adicionar > adicionar pacotes NuGet, procure o pacote Microsoft.Azure.Mobile.Client e clique em Adicionar pacote.Xamarin Studio Right-click your project, click Add > Add NuGet Packages, search for the Microsoft.Azure.Mobile.Client package, and then click Add Package.

No arquivo de atividade principal, lembre-se de adicionar a seguinte instrução using :In your main activity file, remember to add the following using statement:

using Microsoft.WindowsAzure.MobileServices;

Observação

Observe que todos os pacotes de suporte referenciados em seu projeto Android devem ter a mesma versão.Please note that all the support packages referenced in your Android project must have the same version. O SDK tem a dependência Xamarin.Android.Support.CustomTabs para a plataforma Android e, portanto, se o projeto usar pacotes de suporte mais recentes, será necessário instalar diretamente esse pacote com a versão necessária para evitar conflitos.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.

Como trabalhar com símbolos de depuração no Visual StudioHow to: Work with debug symbols in Visual Studio

Os símbolos para o namespace Microsoft.Azure.Mobile estão disponíveis em SymbolSource.The symbols for the Microsoft.Azure.Mobile namespace are available on SymbolSource. Consulte as instruções do SymbolSource para integrar o SymbolSource ao Visual Studio.Refer to the SymbolSource instructions to integrate SymbolSource with Visual Studio.

Criar o cliente dos Aplicativos MóveisCreate the Mobile Apps client

O código a seguir cria o objeto MobileServiceClient que é usado para acessar o back-end do seu Aplicativo Móvel.The following code creates the MobileServiceClient object that is used to access your Mobile App backend.

var client = new MobileServiceClient("MOBILE_APP_URL");

No código anterior, substitua MOBILE_APP_URL pela URL do back-end do Aplicativo Móvel, que está localizada na folha de back-end de seu Aplicativo Móvel no Azure portal.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. O objeto MobileServiceClient deve ser um singleton.The MobileServiceClient object should be a singleton.

Trabalhar com tabelasWork with Tables

A seção a seguir fornece detalhes sobre como pesquisar e recuperar registros e modificar os dados na tabela.The following section details how to search and retrieve records and modify the data within the table. Os tópicos a seguir serão abordados:The following topics are covered:

Como criar uma referência de tabelaHow to: Create a table reference

Todos os códigos que acessam e modificam dados em uma tabela de back-end chamam funções no objeto MobileServiceTable .All the code that accesses or modifies data in a backend table calls functions on the MobileServiceTable object. Obtenha uma referência à tabela chamando o método GetTable da seguinte maneira:Obtain a reference to the table by calling the GetTable method, as follows:

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

O objeto retornado usa o modelo de serialização tipado.The returned object uses the typed serialization model. Também há suporte para um modelo de serialização não tipado.An untyped serialization model is also supported. O exemplo abaixo cria uma referência para uma tabela não tipada:The following example creates a reference to an untyped table:

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

Em consultas não tipadas, você deve especificar a cadeia de caracteres de consulta OData subjacente.In untyped queries, you must specify the underlying OData query string.

Como consultar dados do seu Aplicativo MóvelHow to: Query data from your Mobile App

Esta seção descreve como emitir consultas para o back-end do Aplicativo Móvel, que inclui as seguintes funcionalidades:This section describes how to issue queries to the Mobile App backend, which includes the following functionality:

Observação

Um tamanho de página controlado por servidor é usado para impedir que todas as linhas sejam retornadas.A server-driven page size is enforced to prevent all rows from being returned. A paginação impede que as solicitações padrão de grandes conjuntos de dados prejudiquem o serviço.Paging keeps default requests for large data sets from negatively impacting the service. Para retornar mais de 50 linhas, use os métodos Skip e Take, conforme descrito em Retornar dados em páginas.To return more than 50 rows, use the Skip and Take method, as described in Return data in pages.

Como filtrar dados retornadosHow to: Filter returned data

O código a seguir ilustra como filtrar dados incluindo uma cláusula Where em uma consulta.The following code illustrates how to filter data by including a Where clause in a query. Ele retorna todos os itens de todoTable, cuja propriedade Complete é igual a false.It returns all items from todoTable whose Complete property is equal to false. A função Onde aplica um predicado de filtragem de linha à consulta na tabela.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();

Você pode exibir o URI da solicitação enviado ao back-end usando um software de inspeção de mensagem, como as ferramentas de desenvolvedor do navegador ou 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. Se você examinar o URI, verá que a própria cadeia de caracteres da consulta está sendo modificada:If you look at the request URI, notice that the query string is modified:

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

Essa solicitação de OData é convertida em uma consulta SQL pelo SDK do Servidor:This OData request is translated into an SQL query by the Server SDK:

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

A função passada para o método Where pode ter um número arbitrário de condições.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();

Esse exemplo deve ser convertido em uma consulta SQL pelo SDK do Servidor: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

Essa consulta pode ser dividida em várias cláusulas: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();

Os dois métodos são equivalentes e podem ser usados de maneira intercambiável.The two methods are equivalent and may be used interchangeably. A opção anterior—de concatenar vários predicados em uma consulta—é mais compacta e recomendada.The former option—of concatenating multiple predicates in one query—is more compact and recommended.

A cláusula Where dá suporte a operações que são convertidas para o subconjunto OData.The Where clause supports operations that be translated into the OData subset. As operações incluem:Operations include:

  • Operadores relacionais (==,!=, <, <=, >, >=),Relational operators (==, !=, <, <=, >, >=),
  • Operadores aritméticos (+, -, /, *, %),Arithmetic operators (+, -, /, *, %),
  • Número de precisão (Math.Floor, Math.Ceiling),Number precision (Math.Floor, Math.Ceiling),
  • Funções de cadeia de caracteres (Length, Substring, Replace, IndexOf, StartsWith, EndsWith),String functions (Length, Substring, Replace, IndexOf, StartsWith, EndsWith),
  • Propriedades de data (ano, mês, dia, hora, minuto, segundo),Date properties (Year, Month, Day, Hour, Minute, Second),
  • Propriedades de acesso de um objeto eAccess properties of an object, and
  • Expressões que combinam qualquer uma dessas operações.Expressions combining any of these operations.

Ao considerar o que é compatível com o SDK do Servidor, você pode consultar a Documentação do OData v3.When considering what the Server SDK supports, you can consider the OData v3 Documentation.

Como classificar dados retornadosHow to: Sort returned data

O código a seguir ilustra como classificar dados incluindo uma função OrderBy ou OrderByDescending na consulta.The following code illustrates how to sort data by including an OrderBy or OrderByDescending function in the query. Ele retorna os itens da todoTable classificada em ordem crescente pelo 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();

Como retornar dados em páginasHow to: Return data in pages

Por padrão, o back-end retorna apenas as primeiras 50 linhas.By default, the backend returns only the first 50 rows. Você pode aumentar o número de linhas retornadas chamando o método Take .You can increase the number of returned rows by calling the Take method. Use Take juntamente com o método Ignorar para solicitar uma "página" específica do conjunto de dados total retornado pela consulta.Use Take along with the Skip method to request a specific "page" of the total dataset returned by the query. A consulta a seguir, quando executada, retorna os três itens principais na tabela.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();

A consulta revisada a seguir ignora os três primeiros resultados e retorna os três seguintes.The following revised query skips the first three results and returns the next three results. Essa consulta produz a segunda "página" de dados, onde o tamanho da página é de três itens.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();

O método IncludeTotalCount solicita a contagem total de todos os registros que seriam retornados, ignorando cláusulas de paginação/limite especificadas: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();

Em um aplicativo de verdade, você pode usar consultas semelhantes ao exemplo anterior com um controle de paginação ou interface do usuário semelhante para navegar entre páginas.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.

Observação

Para substituir o limite de 50 linhas em um back-end do Aplicativo Móvel, você também deve aplicar o EnableQueryAttribute ao método GET público e especificar o comportamento de paginação.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. Quando aplicado ao método, o seguinte define o máximo de linhas retornadas para 1000:When applied to the method, the following sets the maximum returned rows to 1000:

[EnableQuery(MaxTop=1000)]

Como selecionar colunas específicasHow to: Select specific columns

Você pode especificar qual conjunto de propriedades incluir nos resultados adicionando uma cláusula Seleção à sua consulta.You can specify which set of properties to include in the results by adding a Select clause to your query. Por exemplo, o código a seguir mostra como selecionar apenas um campo e também como selecionar e formatar vários campos: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();

Todas as funções descritas até agora são aditivas e, portanto, podemos continuar a encadeá-las.All the functions described so far are additive, so we can keep chaining them. Cada chamada encadeada afeta mais a consulta.Each chained call affects more of the query. Mais um exemplo: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();

Como pesquisar dados pela IDHow to: Look up data by ID

A função LookupAsync pode ser usada para procurar objetos do banco de dados com uma ID específica.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");

Como executar consultas sem tipoHow to: Execute untyped queries

Ao executar uma consulta usando um objeto de tabela sem tipo, você deve especificar expressamente a cadeia de consulta OData chamando ReadAsync, como no exemplo a seguir: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");

Você recupera valores JSON que podem ser usados como um recipiente de propriedades.You get back JSON values that you can use like a property bag. Para obter mais informações sobre JToken e Newtonsoft Json.NET, confira o site Json.NET .For more information on JToken and Newtonsoft Json.NET, see the Json.NET site.

Como inserir dados em um back-end do Aplicativo MóvelHow to: Insert data into a Mobile App backend

Todos os tipos de cliente devem conter um membro chamado Id, que é por padrão uma cadeia de caracteres.All client types must contain a member named Id, which is by default a string. Essa ID é necessária para executar operações CRUD e para sincronização offline. O código a seguir ilustra como usar o método InsertAsync para inserir novas linhas em uma tabela.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. O parâmetro contém os dados a serem inseridos como um objeto .NET.The parameter contains the data to be inserted as a .NET object.

await todoTable.InsertAsync(todoItem);

Se um valor exclusivo de ID personalizada não é incluído no todoItem durante uma inserção, um GUID é gerado pelo servidor.If a unique custom ID value is not included in the todoItem during an insert, a GUID is generated by the server. Você poderá recuperar a Id gerada ao inspecionar o objeto após o retorno da chamada.You can retrieve the generated Id by inspecting the object after the call returns.

Para inserir dados não tipados, você pode tirar proveito do 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);

Aqui está um exemplo usando um endereço de email como uma id de cadeia de caracteres exclusiva: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);

Trabalhando com valores de IDWorking with ID values

Os Aplicativos Móveis dão suporte a valores exclusivos e personalizados de cadeia de caracteres para a coluna id da tabela.Mobile Apps supports unique custom string values for the table's id column. Um valor de cadeia de caracteres permite que aplicativos usem valores personalizados, como endereços de email ou nomes de usuário para a ID.A string value allows applications to use custom values such as email addresses or user names for the ID. IDs de cadeia de caracteres fornecem os seguintes benefícios:String IDs provide you with the following benefits:

  • As IDs são geradas sem fazer uma varredura no banco de dados.IDs are generated without making a round trip to the database.
  • Os registros são mais fáceis de mesclar a partir de tabelas ou bancos de dados diferentes.Records are easier to merge from different tables or databases.
  • Os valores de IDs podem integrar-se melhor a uma lógica do aplicativo.IDs values can integrate better with an application's logic.

Quando um valor de ID de cadeia de caracteres não está definido em um registro inserido, o back-end do Aplicativo Móvel gera um valor exclusivo para a ID.When a string ID value is not set on an inserted record, the Mobile App backend generates a unique value for the ID. Você pode usar o método Guid.NewGuid para gerar seus próprios valores de ID, seja no cliente ou no 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"));

Como modificar dados em um back-end de Aplicativo MóvelHow to: Modify data in a Mobile App backend

O código a seguir ilustra como usar o método UpdateAsync para atualizar um registro existente com a mesma ID com novas informações.The following code illustrates how to use the UpdateAsync method to update an existing record with the same ID with new information. O parâmetro contém os dados a serem atualizados como um objeto .NET.The parameter contains the data to be updated as a .NET object.

await todoTable.UpdateAsync(todoItem);

Para atualizar dados não tipados, você pode tirar proveito do Json.NET da seguinte forma: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);

Um campo id deve ser especificado ao fazer uma atualização.An id field must be specified when making an update. O back-end usa o campo id para identificar a linha a ser atualizada.The backend uses the id field to identify which row to update. O campo id pode ser obtido do resultado da chamada InsertAsync.The id field can be obtained from the result of the InsertAsync call. Quando você tenta atualizar um item sem fornecer o valor id, uma ArgumentException é gerada.An ArgumentException is raised if you try to update an item without providing the id value.

Como excluir dados em um back-end do Aplicativo MóvelHow to: Delete data in a Mobile App backend

O código a seguir ilustra como usar o método DeleteAsync para excluir uma instância existente.The following code illustrates how to use the DeleteAsync method to delete an existing instance. A instância é identificada pelo campo id definido em todoItem.The instance is identified by the id field set on the todoItem.

await todoTable.DeleteAsync(todoItem);

Para excluir dados não tipados, você pode tirar proveito do Json.NET da seguinte forma: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 você faz uma solicitação de exclusão, uma ID deve ser especificada.When you make a delete request, an ID must be specified. Outras propriedades não são passadas para o serviço ou são ignoradas no serviço.Other properties are not passed to the service or are ignored at the service. O resultado de uma chamada de DeleteAsync geralmente é null.The result of a DeleteAsync call is usually null. A ID a ser passada pode ser obtida do resultado da chamada de InsertAsync .The ID to pass in can be obtained from the result of the InsertAsync call. Um MobileServiceInvalidOperationException é gerado quando você tenta excluir um item sem especificar o campo id.A MobileServiceInvalidOperationException is thrown when you try to delete an item without specifying the id field.

Como usar a simultaneidade otimista para resolução de conflitosHow to: Use Optimistic Concurrency for conflict resolution

Dois ou mais clientes podem gravar alterações no mesmo item ao mesmo tempo.Two or more clients may write changes to the same item at the same time. Sem detecção de conflito, a última gravação substituiria as atualizações anteriores.Without conflict detection, the last write would overwrite any previous updates. Controle de simultaneidade otimista pressupõe que cada transação possa ser confirmada e, portanto, não usa nenhum recurso de bloqueio.Optimistic concurrency control assumes that each transaction can commit and therefore does not use any resource locking. Antes de confirmar uma transação, o controle de simultaneidade otimista verifica se nenhuma outra transação modificou os dados.Before committing a transaction, optimistic concurrency control verifies that no other transaction has modified the data. Se os dados foram modificados, a transação de confirmação será revertida.If the data has been modified, the committing transaction is rolled back.

Os Aplicativos Móveis dão suporte ao controle de simultaneidade otimista acompanhando as alterações em cada item na coluna de propriedades do sistema version definida para cada tabela no back-end do Aplicativo Móvel.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. Cada vez que um registro é atualizado, os Aplicativos Móveis definem a propriedade version desse registro como um novo valor.Each time a record is updated, Mobile Apps sets the version property for that record to a new value. Durante cada solicitação de atualização, a propriedade version do registro incluído na solicitação é comparada à mesma propriedade do registro no servidor.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 a versão transmitida com a solicitação não corresponder ao back-end, a biblioteca de cliente gerará uma exceção MobileServicePreconditionFailedException<T> .If the version passed with the request does not match the backend, then the client library raises a MobileServicePreconditionFailedException<T> exception. O tipo incluído com a exceção é o registro do back-end que contém a versão do registro dos servidores.The type included with the exception is the record from the backend containing the servers version of the record. O aplicativo poderá, então, usar essas informações para decidir se deve executar a solicitação de atualização novamente com o valor de version correto do back-end para confirmar as alterações.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.

Define uma coluna na classe da tabela para a propriedade do sistema version para habilitar a simultaneidade otimista.Define a column on the table class for the version system property to enable optimistic concurrency. Por exemplo: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; }
}

Aplicativos que usam tabelas não tipadas habilitam a simultaneidade otimista definindo o sinalizador Version nas SystemProperties da tabela da seguinte maneira.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;

Além de habilitar a simultaneidade otimista, você também deve capturar a exceção MobileServicePreconditionFailedException<T> em seu código ao chamar UpdateAsync.In addition to enabling optimistic concurrency, you must also catch the MobileServicePreconditionFailedException<T> exception in your code when calling UpdateAsync. Resolva o conflito aplicando a version correta ao registro atualizado e chame UpdateAsync com o registro resolvido.Resolve the conflict by applying the correct version to the updated record and call UpdateAsync with the resolved record. O código a seguir mostra como resolver um conflito de gravação quando detectado: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();
}

Para obter mais informações, confira o tópico Sincronização de Dados Offline em Aplicativos Móveis do Azure .For more information, see the Offline Data Sync in Azure Mobile Apps topic.

Como: associar dados dos Aplicativos Móveis a uma interface do usuário do WindowsHow to: Bind Mobile Apps data to a Windows user interface

Esta seção mostra como exibir os objetos de dados retornados usando elementos da interface do usuário em um aplicativo do Windows.This section shows how to display returned data objects using UI elements in a Windows app. O exemplo de código a seguir associa a origem da lista a uma consulta de itens incompletos.The following example code binds to the source of the list with a query for incomplete items. O MobileServiceCollection cria uma coleção de associações com reconhecimento de Aplicativos Móveis.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;

Alguns controles no tempo de execução gerenciado dão suporte a uma interface chamada ISupportIncrementalLoading.Some controls in the managed runtime support an interface called ISupportIncrementalLoading. Essa interface permite que os controles solicitem dados adicionais quando o usuário rola.This interface allows controls to request extra data when the user scrolls. Há suporte interno para essa interface para aplicativos universais do Windows via MobileServiceIncrementalLoadingCollection, que processa as chamadas automaticamente por meio dos controles.There is built-in support for this interface for universal Windows apps via MobileServiceIncrementalLoadingCollection, which automatically handles the calls from the controls. Use MobileServiceIncrementalLoadingCollection em aplicativos do Windows, da seguinte maneira: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;

Para usar a nova coleção nos aplicativos do Windows Phone 8 e do “Silverlight”, use os métodos da extensão ToCollection em 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>. Para carregar dados, chame LoadMoreItemsAsync().To load data, call LoadMoreItemsAsync().

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

Quando usa a coleção criada chamando ToCollectionAsync ou ToCollection, você obtém uma coleção que pode ser vinculada a controles da interface do usuário.When you use the collection created by calling ToCollectionAsync or ToCollection, you get a collection that can be bound to UI controls. Essa coleção tem reconhecimento de paginação.This collection is paging-aware. Como a coleção está carregando dados da rede, o carregamento às vezes falha.Since the collection is loading data from the network, loading sometimes fails. Para lidar com essas falhas, substitua o método OnException na MobileServiceIncrementalLoadingCollection para tratar das exceções resultantes de chamadas para LoadMoreItemsAsync.To handle such failures, override the OnException method on MobileServiceIncrementalLoadingCollection to handle exceptions resulting from calls to LoadMoreItemsAsync.

Pense que sua tabela tem muitos campos, mas você só deseja exibir alguns deles em seu controle.Consider if your table has many fields but you only want to display some of them in your control. Você pode usar as diretrizes contidas na seção anterior "Selecionar colunas específicas" para selecionar colunas específicas a serem exibidas na interface do usuário.You may use the guidance in the preceding section "Select specific columns" to select specific columns to display in the UI.

Alterar o Tamanho da páginaChange the Page size

Os Aplicativos Móveis do Azure retornam, no máximo, 50 itens por solicitação por padrão.Azure Mobile Apps returns a maximum of 50 items per request by default. Você pode alterar o tamanho de paginação aumentando o tamanho máximo da página no cliente e no servidor.You can change the paging size by increasing the maximum page size on both the client and server. Para aumentar o tamanho da página solicitada, especifique PullOptions ao usar PullAsync():To increase the requested page size, specify PullOptions when using PullAsync():

PullOptions pullOptions = new PullOptions
    {
        MaxPageSize = 100
    };

Supondo que você deixou o PageSize igual ou maior a 100 no servidor, uma solicitação retorna até 100 itens.Assuming you have made the PageSize equal to or greater than 100 within the server, a request returns up to 100 items.

Trabalhar com tabelas offlineWork with Offline Tables

Tabelas offline usam um armazenamento local do SQLite para armazenamento de dados para uso no modo offline.Offline tables use a local SQLite store to store data for use when offline. Todas as operações da tabela são executadas no armazenamento local do SQLite em vez de no armazenamento do servidor remoto.All table operations are done against the local SQLite store instead of the remote server store. Para criar uma tabela offline, primeiro, prepare seu projeto:To create an offline table, first prepare your project:

  1. No Visual Studio, clique com o botão direito do mouse na solução > Gerenciar Pacotes NuGet para a Solução... , procure e instale o pacote NuGet Microsoft.Azure.Mobile.Client.SQLiteStore para todos os projetos na solução.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. (Opcional) Para dar suporte a dispositivos Windows, instale um dos seguintes pacotes de tempo de execução do SQLite:(Optional) To support Windows devices, install one of the following SQLite runtime packages:

  3. (Opcional).(Optional). Para dispositivos Windows, clique com botão direito do mouse em Referências > Adicionar Referência… , expanda a pasta Windows > Extensões, habilite o SDK do SQLite para Windows apropriado junto com o SDK do Tempo de Execução do Visual C++ 2013 para Windows.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. Os nomes do SDK do SQLite variam ligeiramente de acordo com cada plataforma Windows.The SQLite SDK names vary slightly with each Windows platform.

Antes que uma referência de tabela possa ser criada, o armazenamento local precisa ser preparado: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);

A inicialização do armazenamento normalmente é feita imediatamente depois que o cliente é criado.Store initialization is normally done immediately after the client is created. O OfflineDbPath deve ser um nome de arquivo adequado para uso em todas as plataformas que tem suporte.The OfflineDbPath should be a filename suitable for use on all platforms that you support. Se o caminho for um caminho totalmente qualificado (ou seja, começa com uma barra invertida), então, ele será usado.If the path is a fully qualified path (that is, it starts with a slash), then that path is used. Se o caminho não for totalmente qualificado, o arquivo será colocado em um local específico da plataforma.If the path is not fully qualified, the file is placed in a platform-specific location.

  • Para dispositivos Android e iOS, o caminho padrão é a pasta "Arquivos pessoais".For iOS and Android devices, the default path is the "Personal Files" folder.
  • Para dispositivos Windows, o caminho padrão é a pasta "AppData" específica do aplicativo.For Windows devices, the default path is the application-specific "AppData" folder.

Uma referência de tabela pode ser obtida usando o método GetSyncTable<>:A table reference can be obtained using the GetSyncTable<> method:

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

Você não precisa se autenticar para usar uma tabela offline.You do not need to authenticate to use an offline table. Você precisa se autenticar apenas quando estiver se comunicando com o serviço de back-end.You only need to authenticate when you are communicating with the backend service.

Sincronizando uma tabela OfflineSyncing an Offline Table

Tabelas off-line não são sincronizadas com o back-end, por padrão.Offline tables are not synchronized with the backend by default. A sincronização é dividida em duas partes.Synchronization is split into two pieces. Você pode enviar alterações separadamente de download de novos itens.You can push changes separately from downloading new items. Este é um método de sincronização típico: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 o primeiro argumento para PullAsync for nulo, a sincronização incremental não será usado.If the first argument to PullAsync is null, then incremental sync is not used. Todas as operações de sincronização recuperam todos os registros.Each sync operation retrieves all records.

O SDK executa um PushAsync() implícito antes de extrair os registros.The SDK performs an implicit PushAsync() before pulling records.

Manipulação de conflito ocorre em um método PullAsync().Conflict handling happens on a PullAsync() method. Você pode lidar com conflitos da mesma maneira que com tabelas on-line.You can deal with conflicts in the same way as online tables. O conflito é produzido quando PullAsync() é chamado em vez de durante a inserção, atualização ou exclusão.The conflict is produced when PullAsync() is called instead of during the insert, update, or delete. Se vários conflitos ocorrerem, eles serão agrupados em uma única MobileServicePushFailedException.If multiple conflicts happen, they are bundled into a single MobileServicePushFailedException. Gerenciar cada falha separadamente.Handle each failure separately.

Trabalhar com uma API personalizadaWork with a custom API

Uma API personalizada permite que você defina pontos de extremidade personalizados que expõem a funcionalidade do servidor que não mapeia para uma inserção, atualização, exclusão ou operação de leitura.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. Usando uma API personalizada, você pode ter mais controle sobre mensagens, incluindo ler e definir cabeçalhos de mensagens HTTP e definir um formato de corpo de mensagem diferente do 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.

Você pode chamar uma API personalizada chamando um dos métodos InvokeApiSync no cliente.You call a custom API by calling one of the InvokeApiAsync methods on the client. Por exemplo, a seguinte linha de código envia uma solicitação POST à API completeAll no 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);

Essa forma é uma chamada de método tipada e exige que o tipo de retorno MarkAllResult seja definido.This form is a typed method call and requires that the MarkAllResult return type is defined. Os dois métodos, tipado e não tipado, são aceitos.Both typed and untyped methods are supported.

O método InvokeApiAsync() precede '/api /' para a API que você deseja chamar, a menos que a API comece com '/'.The InvokeApiAsync() method prepends '/api/' to the API that you wish to call unless the API starts with a '/'. Por exemplo:For example:

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

Você pode usar InvokeApiAsync para chamar qualquer API Web, incluindo as que não são definidas com aplicativos móveis do Azure.You can use InvokeApiAsync to call any WebAPI, including those WebAPIs that are not defined with Azure Mobile Apps. Ao usar InvokeApiAsync(), os cabeçalhos apropriados, incluindo os cabeçalhos de autenticação, são enviados com a solicitação.When you use InvokeApiAsync(), the appropriate headers, including authentication headers, are sent with the request.

Autenticar usuáriosAuthenticate users

Os Aplicativos Móveis dão suporte à autenticação e à autorização de usuários de aplicativo, usando vários provedores de identidade externos: Facebook, Google, Conta da Microsoft, Twitter e o 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. Você pode definir permissões em tabelas para restringir o acesso a operações específicas apenas para usuários autenticados.You can set permissions on tables to restrict access for specific operations to only authenticated users. Você também pode usar a identidade de usuários autenticados para implementar regras de autorização em scripts do servidor.You can also use the identity of authenticated users to implement authorization rules in server scripts. Para obter mais informações, consulte o tutorial Adicionar autenticação ao seu aplicativo.For more information, see the tutorial Add authentication to your app.

Dois fluxos de autenticação têm suporte: fluxo gerenciado pelo cliente e fluxo gerenciado pelo servidor.Two authentication flows are supported: client-managed and server-managed flow. O fluxo gerenciado pelo servidor fornece a experiência de autenticação mais simples, pois depende da interface de autenticação da web do provedor.The server-managed flow provides the simplest authentication experience, as it relies on the provider's web authentication interface. O fluxo gerenciado pelo cliente permite uma integração mais profunda com recursos específicos ao dispositivo pois depende dos SDKs específicos ao provedor e ao dispositivo.The client-managed flow allows for deeper integration with device-specific capabilities as it relies on provider-specific device-specific SDKs.

Observação

Recomendamos o uso de um fluxo gerenciado pelo cliente em seus aplicativos de produção.We recommend using a client-managed flow in your production apps.

Para configurar a autenticação, você precisa registrar seu aplicativo com um ou mais provedores de identidade.To set up authentication, you must register your app with one or more identity providers. O provedor de identidade gera uma ID de cliente e um segredo do cliente para seu aplicativo.The identity provider generates a client ID and a client secret for your app. Esses valores são definidos no seu back-end para habilitar a autenticação/autorização de Serviço de Aplicativo do Azure.These values are then set in your backend to enable Azure App Service authentication/authorization. Para saber mais, siga as instruções detalhadas no tutorial Adicionar autenticação ao seu aplicativo.For more information, follow the detailed instructions in the tutorial Add authentication to your app.

Os tópicos a seguir são abordados nesta seção:The following topics are covered in this section:

Autenticação gerenciada pelo clienteClient-managed authentication

Seu aplicativo pode entrar em contato de forma independente com o provedor de identidade e fornecer o token retornado durante o login com seu backend.Your app can independently contact the identity provider and then provide the returned token during login with your backend. Esse fluxo de cliente permite que você forneça uma experiência de logon único aos usuários ou recupere dados adicionais do usuário do provedor de identidade.This client flow enables you to provide a single sign-on experience for users or to retrieve additional user data from the identity provider. É melhor usar a autenticação de fluxo de cliente do que usar um fluxo de servidor, já que o SDK do provedor de identidade fornece uma aparência mais nativa do UX e permite uma maior personalização.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.

Veja exemplos para os seguintes padrões de autenticação de fluxo de cliente:Examples are provided for the following client-flow authentication patterns:

Autenticar usuários com a Active Directory Authentication LibraryAuthenticate users with the Active Directory Authentication Library

Você pode usar a ADAL (Biblioteca de autenticação do Active Directory) para iniciar a autenticação do usuário a partir do cliente usando a autenticação do 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. Configure o seu back-end de aplicativo móvel para entrada no AAD seguindo o tutorial Como configurar o Serviço de aplicativo para o logon do Active Directory .Configure your mobile app backend for AAD sign-on by following the How to configure App Service for Active Directory login tutorial. Complete a etapa opcional de registrar um aplicativo cliente nativo.Make sure to complete the optional step of registering a native client application.

  2. No Visual Studio ou Xamarin Studio, abra o projeto e adicione uma referência ao pacote 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. Ao pesquisar, inclua versões de pré-lançamento.When searching, include pre-release versions.

  3. Adicione o código a seguir ao seu aplicativo, de acordo com a plataforma que você está usando.Add the following code to your application, according to the platform you are using. Em cada um, faça as seguintes substituições:In each, make the following replacements:

    • Substitua INSERT-AUTHORITY-HERE pelo nome do locatário no qual o aplicativo foi provisionado.Replace INSERT-AUTHORITY-HERE with the name of the tenant in which you provisioned your application. O formato deve ser https://login.microsoftonline.com/contoso.onmicrosoft.com.The format should be https://login.microsoftonline.com/contoso.onmicrosoft.com. Esse valor pode ser copiado da guia Domínio no seu Azure Active Directory no Azure portal.This value can be copied from the Domain tab in your Azure Active Directory in the Azure portal.

    • Substitua INSERT-RESOURCE-ID-HERE pela ID do cliente do seu back-end de aplicativo móvel.Replace INSERT-RESOURCE-ID-HERE with the client ID for your mobile app backend. Você pode obter a ID do cliente na guia Avançadas em Configurações do Azure Active Directory no portal.You can obtain the client ID from the Advanced tab under Azure Active Directory Settings in the portal.

    • Substitua INSERT-CLIENT-ID-HERE pela ID do cliente copiada do aplicativo cliente nativo.Replace INSERT-CLIENT-ID-HERE with the client ID you copied from the native client application.

    • Substitua INSERT-REDIRECT-URI-HERE pelo ponto de extremidade /.auth/login/done do site, usando o esquema HTTPS.Replace INSERT-REDIRECT-URI-HERE with your site's /.auth/login/done endpoint, using the HTTPS scheme. Este valor deve ser semelhante a https://contoso.azurewebsites.net/.auth/login/done .This value should be similar to https://contoso.azurewebsites.net/.auth/login/done.

      Veja a seguir o código necessário para cada plataforma: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);
      }
      

Entrada única usando um token do Facebook ou do GoogleSingle Sign-On using a token from Facebook or Google

Você pode usar o fluxo de cliente como mostra este snippet de código para o Facebook ou 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();
    }
}

Autenticação gerenciada pelo servidorServer-managed authentication

Depois de registrar seu provedor de identidade, chame o método LoginAsync no [MobileServiceClient] com o valor MobileServiceAuthenticationProvider de seu provedor.Once you have registered your identity provider, call the LoginAsync method on the [MobileServiceClient] with the MobileServiceAuthenticationProvider value of your provider. Por exemplo, o código a seguir inicia uma entrada de fluxo do servidor usando o 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 você estiver usando um provedor de identidade além do Facebook, altere o valor MobileServiceAuthenticationProvider para o valor de seu provedor.If you are using an identity provider other than Facebook, change the value of MobileServiceAuthenticationProvider to the value for your provider.

Em um fluxo de servidor, o Serviço de Aplicativo do Azure gerencia o fluxo de autenticação OAuth exibindo a página de entrada do provedor selecionado.In a server flow, Azure App Service manages the OAuth authentication flow by displaying the sign-in page of the selected provider. Depois que o provedor de identidade retorna, o Serviço de Aplicativo do Azure gera um token de autenticação do Serviço de Aplicativo.Once the identity provider returns, Azure App Service generates an App Service authentication token. O método LoginAsync retorna um MobileServiceUser, que fornece a UserId do usuário autenticado e o MobileServiceAuthenticationToken como um JWT (token da Web JSON).The LoginAsync method returns a MobileServiceUser, which provides both the UserId of the authenticated user and the MobileServiceAuthenticationToken, as a JSON web token (JWT). Esse token pode ser armazenado em cache e reutilizado até que expire.This token can be cached and reused until it expires. Para obter mais informações, consulte Armazenando o token de autenticação em cache.For more information, see Caching the authentication token.

Armazenando o token de autenticação em cacheCaching the authentication token

Em alguns casos, a chamada para o método de logon pode ser evitada após a primeira autenticação bem-sucedida armazenando o token de autenticação do provedor.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. Aplicativos da Microsoft Store e UWP podem usar o PasswordVault para armazenar em cache o token de autenticação atual após uma conexão bem-sucedida, da seguinte maneira: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));

O valor de UserId é armazenado como o UserName da credencial e o token é armazenado como a Senha.The UserId value is stored as the UserName of the credential and the token is the stored as the Password. Em inicializações subsequentes, você pode verificar o PasswordVault para ter acesso às credenciais armazenadas em cache.On subsequent start-ups, you can check the PasswordVault for cached credentials. O exemplo a seguir usa as credenciais armazenadas em cache quando elas forem encontradas e tenta autenticar novamente com o 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 você faz o logoff de um usuário, também deve remover a credencial armazenada, da seguinte maneira: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));

Os aplicativos Xamarin usam as APIs Xamarin.Auth para armazenar com segurança as credenciais em um objeto Account .Xamarin apps use the Xamarin.Auth APIs to securely store credentials in an Account object. Para obter um exemplo de como usar essas APIs, confira o arquivo de código AuthStore.cs no exemplo de compartilhamento de fotos de ContosoMoments.For an example of using these APIs, see the AuthStore.cs code file in the ContosoMoments photo sharing sample.

Quando você usa a autenticação gerenciada pelo cliente, também pode armazenar em cache o token de acesso obtido de seu provedor, como o Facebook ou Twitter.When you use client-managed authentication, you can also cache the access token obtained from your provider such as Facebook or Twitter. Esse token pode ser fornecido para solicitar um novo token de autenticação a partir do back-end, da seguinte maneira: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);

Notificações por PushPush Notifications

Os tópicos a seguir abordam Notificações por Push:The following topics cover Push Notifications:

Como se registrar para receber notificações por pushHow to: Register for Push Notifications

O cliente de Aplicativos Móveis permite que você se registrar para notificações por push com Hubs de Notificação do Azure.The Mobile Apps client enables you to register for push notifications with Azure Notification Hubs. Ao se registrar, você obtém um identificador obtido do PNS (Serviço de Notificação por Push) específico da plataforma.When registering, you obtain a handle that you obtain from the platform-specific Push Notification Service (PNS). Então fornece este valor, juntamente com quaisquer marcas, no momento em que cria o registro.You then provide this value along with any tags when you create the registration. O seguinte código registra seu aplicativo do Windows para notificações de push no WNS (Serviço de Notificação do 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);
}

Se estiver enviando por push para o WNS, você PRECISARÁ obter um SID de pacote da Microsoft Store.If you are pushing to WNS, then you MUST obtain a Microsoft Store package SID. Para saber mais sobre os aplicativos do Windows, inclusive como se registrar para obter registros de modelo, confira Adicionar notificações por push ao aplicativo.For more information on Windows apps, including how to register for template registrations, see Add push notifications to your app.

A solicitação de marcas do cliente não tem suporte.Requesting tags from the client is not supported. As solicitações de marca são descartadas silenciosamente do registro.Tag Requests are silently dropped from registration. Se você deseja registrar seu dispositivo com marcas, crie uma API personalizada que usa a API de Hubs de Notificação para realizar o registro em seu nome.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. Chame a API Personalizada em vez do método RegisterNativeAsync().Call the Custom API instead of the RegisterNativeAsync() method.

Como obter um SID de pacote da Microsoft StoreHow to: Obtain a Microsoft Store package SID

Um SID de pacote é necessário para habilitar notificações por push em aplicativos da Microsoft Store.A package SID is needed for enabling push notifications in Microsoft Store apps. Para receber um SID de pacote, registre seu aplicativo na Microsoft Store.To receive a package SID, register your application with the Microsoft Store.

Para obter esse valor:To obtain this value:

  1. No Gerenciador de Soluções do Visual Studio, clique com o botão direito do mouse no projeto do aplicativo da Microsoft Store, clique em Armazenar > Associar Aplicativo à Store... .In Visual Studio Solution Explorer, right-click the Microsoft Store app project, click Store > Associate App with the Store....
  2. No assistente, clique em Avançar, entre com sua conta da Microsoft, digite um nome para seu aplicativo em Reservar um novo nome de aplicativo e clique em Reservar.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. Depois que o registro do aplicativo for criado com êxito, selecione o nome do aplicativo, clique em Avançar e em Associar.After the app registration is successfully created, select the app name, click Next, and then click Associate.
  4. Faça logon na Central de Desenvolvimento do Windows usando a sua Conta da Microsoft.Log in to the Windows Dev Center using your Microsoft Account. Em Meus aplicativos, clique no registro de aplicativo que você criou.Under My apps, click the app registration you created.
  5. Clique em Gerenciamento de aplicativos > Identidade de aplicativos e, em seguida, role para baixo até encontrar o SID do Pacote.Click App management > App identity, and then scroll down to find your Package SID.

Muitos usos do SID do pacote o tratam como um URI; nesse caso, você precisa usar ms-app:// como o esquema.Many uses of the package SID treat it as a URI, in which case you need to use ms-app:// as the scheme. Anote a versão do SID do pacote formado pela concatenação desse valor como um prefixo.Make note of the version of your package SID formed by concatenating this value as a prefix.

Os aplicativos Xamarin exigem mais código para poder registrar um aplicativo em execução nas plataformas iOS ou Android.Xamarin apps require some additional code to be able to register an app running on the iOS or Android platforms. Para saber mais, confira o tópico para sua plataforma:For more information, see the topic for your platform:

Como registrar modelos de envio por push para enviar notificações entre plataformasHow to: Register push templates to send cross-platform notifications

Para registrar modelos, use o método RegisterAsync() com os modelos, da seguinte maneira:To register templates, use the RegisterAsync() method with the templates, as follows:

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

Seus modelos devem ser do tipo JObject e podem conter vários modelos no seguinte formato 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;
}

O método RegisterAsync() também aceita Blocos Secundários:The method RegisterAsync() also accepts Secondary Tiles:

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

Todas as marcações são retiradas durante o registro para segurança.All tags are stripped away during registration for security. Para adicionar marcas a instalações ou modelos dentro de instalações, confira [Trabalhar com o SDK do servidor de back-end do .NET para Aplicativos Móveis do Azure].To add tags to installations or templates within installations, see [Work with the .NET backend server SDK for Azure Mobile Apps].

Para enviar notificações usando esses modelos registrados, consulte as APIs dos Hubs de Notificação.To send notifications utilizing these registered templates, refer to the Notification Hubs APIs.

Tópicos DiversosMiscellaneous Topics

Como tratar errosHow to: Handle errors

Quando ocorre um erro no back-end, o SDK do cliente dispara uma MobileServiceInvalidOperationException.When an error occurs in the backend, the client SDK raises a MobileServiceInvalidOperationException. O seguinte exemplo mostra como manipular uma exceção que é retornada pelo 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
    }
}

Outro exemplo de lidar com condições de erro pode ser encontrado no exemplo de arquivos de Aplicativos Móveis.Another example of dealing with error conditions can be found in the Mobile Apps Files Sample. O exemplo de LoggingHandler fornece um manipulador de representante de registro em log para registrar as solicitações que estão sendo feitas no back-end.The LoggingHandler example provides a logging delegate handler to log the requests being made to the backend.

Como personalizar cabeçalhos de solicitaçãoHow to: Customize request headers

Para dar suporte ao seu cenário específico de aplicativo, convém personalizar a comunicação com o back-end do Aplicativo Móvel.To support your specific app scenario, you might need to customize communication with the Mobile App backend. Por exemplo, convém adicionar um cabeçalho personalizado para cada solicitação de saída, ou até mesmo alterar códigos de status de respostas.For example, you may want to add a custom header to every outgoing request or even change responses status codes. Você pode usar um DelegatingHandlerpersonalizado, como no exemplo abaixo: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;
    }
}