Como usar o SDK do ASP.NET Framework para os Aplicativos Móveis do Azure

Este tópico mostra como usar o SDK do servidor de back-end do .NET nos principais cenários dos Aplicativos Móveis do Serviço de Aplicativo do Azure. Os Aplicativos Móveis SDK do Azure ajuda você a trabalhar com clientes móveis de seu aplicativo ASP.NET.

Aviso

Este artigo aborda informações para a versão da biblioteca v4.2.0, que é substituída pela biblioteca v5.0.0. Para obter as informações mais atualizadas, consulte o artigo para obter a versão mais recente

Criar um back-end do ASP.NET Framework dos Aplicativos Móveis do Azure

Você pode criar um aplicativo ASP.NET Framework usando o Visual Studio 2019.

  • Escolha o modelo Aplicativo Web ASP.NET (.NET Framework). Se você não conseguir localizar esse modelo, selecione C#, Todas as plataformas e Web.
  • Depois de selecionar um nome e uma localização para o aplicativo, selecione o modelo de projeto API Web. A coleção correta de serviços base do aplicativo será instalada.

Baixar e inicializar o SDK

O SDK está disponível em NuGet.org e fornece a funcionalidade base necessária para começar a usar os Aplicativos Móveis do Azure. Para instalar o pacote:

  1. Clique com o botão direito do mouse no projeto e selecione Gerenciar Pacotes NuGet....
  2. Na guia Procurar, insira Microsoft.Azure.Mobile.Server na caixa de pesquisa e pressione Enter.
  3. Selecione o pacote Microsoft.Azure.Mobile.Server.Quickstart.
  4. Clique em Instalar.
  5. Siga os prompts para concluir a instalação.

Repita o processo para instalar Microsoft.Owin.Host.SystemWeb também.

Observação

Não atualize os pacotes que são usados como dependências, como Newtonsoft.JSON ou System.IdentityModel.Jwt. As APIs desses pacotes, em muitos casos, foram alteradas e agora são incompatíveis com os Aplicativos Móveis do Azure para ASP.NET Framework.

Inicializar o projeto de servidor

Um projeto de servidor dos Aplicativos Móveis do Azure é inicializado de modo semelhante a outros projetos do ASP.NET Framework, por meio da inclusão de uma classe de inicialização OWIN. Para adicionar uma classe de inicialização OWIN:

  1. Clique com o botão direito do mouse no projeto e selecione Adicionar>Novo Item

  2. Selecione Web>Geral e depois escolha o modelo Classe de inicialização OWIN.

  3. Insira o nome Startup.cs como o nome da inicialização.

  4. O conteúdo do arquivo Startup.cs deve ser semelhante ao seguinte código:

    using Microsoft.Azure.Mobile.Server.Config;
    using Microsoft.Owin;
    using Owin;
    using System.Web.Http;
    
    [assembly: OwinStartup(typeof(WebApplication1.Startup))]
    namespace WebApplication1
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                HttpConfiguration config = new HttpConfiguration();
                new MobileAppConfiguration()
                    // no added features
                    .ApplyTo(config);
                app.UseWebApi(config);
            }
        }
    }
    

    A OwinStartup, o namespace e o nome de classe serão diferentes, dependendo do seu projeto. Especificamente, você deve substituir o conteúdo do método Configuration() e ajustar as diretivas using corretamente.

Para habilitar recursos individuais, você deve chamar os métodos de extensão no objeto MobileAppConfiguration antes de chamar ApplyTo. Por exemplo, o código a seguir adiciona as rotas padrão para todos os controladores de API que têm o atributo [MobileAppController] durante a inicialização:

new MobileAppConfiguration()
    .MapApiControllers()
    .ApplyTo(config);

A configuração a seguir é considerada um uso "normal" que permite que os controladores de tabela e de API usem o Entity Framework para acessar um serviço SQL.

new MobileAppConfiguration()
    .AddMobileAppHomeController()
    .MapApiControllers()
    .AddTables(
        new MobileAppTableConfiguration()
            .MapTableControllers()
            .AddEntityFramework()
    )
    .MapLegacyCrossDomainController()
    .ApplyTo(config);

Os métodos de extensão usados são:

  • AddMobileAppHomeController() fornece a home page padrão dos Aplicativos Móveis do Azure.
  • MapApiControllers() fornece recursos personalizados de API para controladores de API Web decorados com o atributo [MobileAppController].
  • AddTables() fornece um mapeamento dos pontos de extremidade /tables para controladores de tabela.
  • AddTablesWithEntityFramework() é uma abreviação para mapeamento de pontos de extremidade /tables usando os controladores baseados no Entity Framework.
  • MapLegacyCrossDomainController() fornece os cabeçalhos de CORS padrão para o desenvolvimento local.

Extensões SDK

Os seguintes pacotes com base em extensão no NuGet fornecem vários recursos móveis que podem ser usados pelo seu aplicativo. Habilitar extensões durante a inicialização usando o objeto MobileAppConfiguration .

  • Microsoft.Azure.Mobile.Server.Quickstart Dá suporte à configuração básica dos Aplicativos Móveis. Adicionado à configuração chamando o método de extensão UseDefaultConfiguration durante a inicialização. Essa extensão inclui as seguintes extensões: Notificações, Autenticação, Entidade, Tabelas, pacotes Crossdomain e Home.
  • Microsoft.Azure.Mobile.Server.Home implementa a página padrão este aplicativo móvel está em execução na raiz do site. Adicione à configuração chamando o método de extensão AddMobileAppHomeController .
  • Microsoft.Azure.Mobile.Server.Tables inclui classes para trabalhar com dados e define o pipeline de dados. Adicione à configuração chamando o método de extensão AddTables .
  • Microsoft.Azure.Mobile.Server.Entity permite que o Entity Framework acesse dados no Banco de Dados SQL. Adicionar à configuração chamando o método de extensão AddTablesWithEntityFramework .
  • Microsoft.Azure.Mobile.Server.Authentication Permite a autenticação e define o middleware OWIN usado para validar tokens. Adicionar à configuração chamando os métodos de extensão AddAppServiceAuthentication e IAppBuilder.UseAppServiceAuthentication.
  • Microsoft.Azure.Mobile.Server.Notifications permite as notificações por push e define um ponto de extremidade de registro push. Adicionar à configuração chamando o método de extensão AddPushNotifications .
  • Microsoft.Azure.Mobile.Server.CrossDomain Cria um controlador que fornece dados para os navegadores da Web herdados do seu Aplicativo Móvel. Adicione à configuração chamando o método de extensão MapLegacyCrossDomainController .
  • Microsoft.Azure.Mobile.Server.Login Fornece o método AppServiceLoginHandler.CreateToken(), que é um método estático usado nos cenários de autenticação personalizada.

Publicar o projeto do servidor

Essa seção mostra como publicar seu projeto de back-end do .NET a partir do Visual Studio. Há outros métodos pelos quais você pode publicar o aplicativo. Para obter mais informações, confira a Documentação do Serviço de Aplicativo do Azure.

  1. No Visual Studio, recompile o projeto para restaurar os pacotes do NuGet.
  2. No Gerenciador de Soluções, clique com o botão direito no projeto e clique em Publicar.
  3. Se este projeto ainda não foi publicado, você vai configurar a publicação.
    • Selecione Azure como o destino.
    • Selecione Serviço de Aplicativo do Azure (Windows) como o destino específico.
    • Selecione a instância do Serviço de Aplicativo de destino da implantação. Se você não tem uma instância, use o + para criá-la.
    • Clique em Concluir.
  4. Se você ainda não vinculou um banco de dados SQL, clique em Configurar ao lado do Banco de Dados SQL.
    • Selecione Banco de Dados SQL do Azure
    • Selecione o banco de dados. Se você não tem um banco de dados ou quer usar outro, clique em + para criar um banco de dados e um servidor.
    • Insira MS_TableConnectionString como o nome da cadeia de conexão de banco de dados. Preencha o nome de usuário e a senha nas caixas fornecidas.
    • Clique em Concluir
  5. Clique em Publicar

A publicação no Azure demora um pouco. Para obter mais informações, confira a Documentação do Visual Studio.

Definir um controlador de tabela

Defina um Controlador de Tabela para expor uma tabela SQL a clientes móveis. A configuração de um Controlador de Tabela exige três etapas:

  1. Criar uma classe DTO (Objeto de Transferência de Dados).
  2. Configurar uma referência de tabela na classe DbContext móvel.
  3. Criar um controlador de tabela.

Um DTO (objeto de transferência de dados) é um objeto C# simples que herda de EntityData. Por exemplo:

public class TodoItem : EntityData
{
    public string Text { get; set; }
    public bool Complete {get; set;}
}

O DTO é usado para definir a tabela no Banco de Dados SQL. Para criar a entrada de banco de dados, adicione uma propriedade DbSet<> ao DbContext que você está usando:

public class MobileServiceContext : DbContext
{
    private const string connectionStringName = "Name=MS_TableConnectionString";

    public MobileServiceContext() : base(connectionStringName)
    {

    }

    public DbSet<TodoItem> TodoItems { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Add(
            new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
                "ServiceColumnTable", (property, attributes) => attributes.Single().ColumnType.ToString()));
    }
}

Por fim, crie um controlador:

  1. Clique com o botão direito do mouse na pasta Controllers.

  2. Selecione API Web>Controlador 2 da API Web – Vazio

  3. Insira um nome para o controlador.

  4. Substitua o conteúdo do novo controlador pelo seguinte código:

    public class TodoItemController : TableController<TodoItem>
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            ZUMOAPPNAMEContext context = new ZUMOAPPNAMEContext();
            DomainManager = new EntityDomainManager<TodoItem>(context, Request);
        }
    
        // GET tables/TodoItem
        public IQueryable<TodoItem> GetAllTodoItems()
        {
            return Query();
        }
    
        // GET tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public SingleResult<TodoItem> GetTodoItem(string id)
        {
            return Lookup(id);
        }
    
        // PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
        {
            return UpdateAsync(id, patch);
        }
    
        // POST tables/TodoItem
        public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
        {
            TodoItem current = await InsertAsync(item);
            return CreatedAtRoute("Tables", new { id = current.Id }, current);
        }
    
        // DELETE tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
        public Task DeleteTodoItem(string id)
        {
            return DeleteAsync(id);
        }
    }
    

Ajustar o tamanho de paginação da tabela

Por padrão, os Aplicativos Móveis do Azure retornam 50 registros por solicitação. A paginação garante que o cliente não associará o thread de interface do usuário nem o servidor por muito tempo, garantindo uma boa experiência do usuário. Para alterar o tamanho da tabela de paginação, aumente o "tamanho de consulta permitido" e o tamanho de página do lado do cliente. O “tamanho de consulta permitido" no lado do servidor é ajustado usando o atributo EnableQuery:

[EnableQuery(PageSize = 500)]

Verifique se PageSize é igual ou maior do que o tamanho solicitado pelo cliente. Consulte a documentação de instruções específicas do cliente para obter detalhes sobre a alteração do tamanho de página do cliente.

Definir um controlador de API personalizada

O controlador da API personalizada fornece as funções mais básicas de back-end do Aplicativo Móvel, expondo um ponto de extremidade. Você pode registrar um controlador da API específico do dispositivo móvel usando o atributo [MobileAppController]. O atributo MobileAppController registra a rota, configura o serializador JSON dos Aplicativos Móveis e ativa a verificação de versão do cliente.

O conteúdo do controlador de API personalizado é:

[MobileAppController]
public class CustomAPIController : ApiController
{
    // Content here
}

Após a configuração com o atributo MobileAppController, você poderá definir a API personalizada do mesmo modo que definiria qualquer outra API Web.

Trabalhar com autenticação

Os Aplicativos Móveis do Azure usam autenticação/autorização do Serviço de Aplicativo para proteger seu back-end móvel. Esta seção mostra como executar as seguintes tarefas relacionadas à autenticação em seu projeto de servidor de back-end do .NET:

Adicionar autenticação a um projeto de servidor

Você pode adicionar autenticação ao seu projeto de servidor estendendo o objeto MobileAppConfiguration e configurando o middleware OWIN.

  1. No Visual Studio, instale o pacote Microsoft.Azure.Mobile.Server.Authentication .

  2. No arquivo de projeto Startup.cs, adicione a seguinte linha de código ao início do método Configuração:

    app.UseAppServiceAuthentication(config);
    

    Este componente de middleware OWIN valida os tokens emitidos pelo gateway do Serviço de Aplicativo associado.

  3. Adicione o atributo [Authorize] a qualquer controlador ou método que exija autenticação.

Usar autenticação personalizada para o aplicativo

Importante

Para habilitar a autenticação personalizada, você deve primeiro habilitar Autenticação do Serviço de Aplicativo sem selecionar um provedor para seu Serviço de Aplicativo no Portal do Azure. Assim, a variável de ambiente WEBSITE_AUTH_SIGNING_KEY será habilitada quando hospedada.

Caso não queria usar um dos provedores de Autenticação/Autorização do Serviço de Aplicativo, você pode implementar seu próprio sistema de logon. Instale o pacote Microsoft.Azure.Mobile.Server.Login para ajudá-lo na geração de token de autenticação. Forneça seu próprio código para validar as credenciais do usuário. Por exemplo, você pode comparar com senhas com sal e hash aplicados em um banco de dados. No exemplo abaixo, o método isValidAssertion() (definido em outro lugar) é responsável por essas verificações.

A autenticação personalizada é exposta criando um ApiController e expondo as ações register e login. O cliente deve usar uma interface do usuário personalizada para coletar as informações do usuário. As informações são enviadas para a API com uma chamada HTTP POST padrão. Depois que o servidor valida a asserção, um token é emitido usando o método AppServiceLoginHandler.CreateToken() . O ApiController não deve usar o atributo [MobileAppController].

Uma ação login de exemplo:

public IHttpActionResult Post([FromBody] JObject assertion)
{
    if (isValidAssertion(assertion)) // user-defined function, checks against a database
    {
        JwtSecurityToken token = AppServiceLoginHandler.CreateToken(new Claim[] { new Claim(JwtRegisteredClaimNames.Sub, assertion["username"]) },
            mySigningKey,
            myAppURL,
            myAppURL,
            TimeSpan.FromHours(24) );
        return Ok(new LoginResult()
        {
            AuthenticationToken = token.RawData,
            User = new LoginResultUser() { UserId = userName.ToString() }
        });
    }
    else // user assertion was not valid
    {
        return this.Request.CreateUnauthorizedResponse();
    }
}

No exemplo anterior, LoginResult e LoginResultUser são objetos serializáveis que expõem as propriedades necessárias. O cliente espera que as respostas de logon sejam retornadas como objetos JSON na forma:

{
    "authenticationToken": "<token>",
    "user": {
        "userId": "<userId>"
    }
}

O método AppServiceLoginHandler.CreateToken() inclui um parâmetro audience e um parâmetro issuer. Ambos os parâmetros são definidos para a URL da raiz do seu aplicativo usando o esquema HTTPS. Da mesma forma, você deve definir secretKey como o valor da chave de conexão do seu aplicativo. Não distribua a chave de assinatura em um cliente, já que ela pode ser usada para forjar chaves e se fazer passar por usuários. Você pode obter a chave de assinatura durante a hospedagem no Serviço de Aplicativo referenciando a variável de ambiente WEBSITE_AUTH_SIGNING_KEY. Se for necessário em um contexto de depuração local, siga as instruções na seção Depuração local com autenticação para recuperar a chave e armazená-la como uma configuração de aplicativo.

O token emitido também pode incluir outras declarações e uma data de expiração. No mínimo, o token emitido deve incluir uma declaração (sub) de assunto.

Você pode dar suporte ao método loginAsync() de cliente padrão sobrecarregando a rota de autenticação. Se o cliente chama client.loginAsync('custom'); para fazer logon, a rota deve ser /.auth/login/custom. Você pode definir a rota para o controlador de autenticação personalizada usando MapHttpRoute():

config.Routes.MapHttpRoute("custom", ".auth/login/custom", new { controller = "CustomAuth" });

Dica

Usar a abordagem loginAsync() garante que o token de autenticação está conectado a todas as chamadas subsequentes ao serviço.

Recuperar informações do usuário autenticado

Quando um usuário é autenticado pelo serviço de aplicativo, você pode acessar a ID de usuário atribuída e outras informações no seu código de back-end do .NET. As informações do usuário podem ser usadas para tomar decisões de autorização no back-end. O código abaixo obtém a ID do usuário associada a uma solicitação:

// Get the SID of the current user.
var claimsPrincipal = this.User as ClaimsPrincipal;
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;

A SID é derivado da ID de usuário específica do provedor e é estática para um determinado usuário e o provedor de logon. O SID é nulo para tokens de autenticação inválidos.

O Serviço de Aplicativo também permite solicitar declarações específicas do provedor de logon. Cada provedor de identidade pode fornecer mais informações usando o SDK do provedor de identidade. Por exemplo, você pode usar a API do Graph do Facebook para obter informações de amigos. Você pode especificar as declarações solicitadas na folha do provedor no portal do Azure. Algumas declarações exigem uma configuração adicional com o provedor de identidade.

O código a seguir chama o método de extensão GetAppServiceIdentityAsync para obter as credenciais de logon, que incluem o token de acesso necessário para fazer solicitações na API do Graph do Facebook:

// Get the credentials for the logged-in user.
var credentials = await this.User.GetAppServiceIdentityAsync<FacebookCredentials>(this.Request);

if (credentials.Provider == "Facebook")
{
    // Create a query string with the Facebook access token.
    var fbRequestUrl = "https://graph.facebook.com/me/feed?access_token="
        + credentials.AccessToken;

    // Create an HttpClient request.
    var client = new System.Net.Http.HttpClient();

    // Request the current user info from Facebook.
    var resp = await client.GetAsync(fbRequestUrl);
    resp.EnsureSuccessStatusCode();

    // Do something here with the Facebook user information.
    var fbInfo = await resp.Content.ReadAsStringAsync();
}

Adicione uma instrução using System.Security.Principal para fornecer o método de extensão GetAppServiceIdentityAsync .

Restringir o acesso a dados para usuários autorizados

Na seção anterior, mostramos como recuperar a ID de usuário de um usuário autenticado. Você pode restringir o acesso a dados e outros recursos com base nesse valor. Por exemplo, adicionar uma coluna userId às tabelas e filtrar os resultados da consulta segundo a ID de usuário é uma maneira simples de limitar os dados retornados apenas aos usuários autorizados. O código a seguir retorna linhas de dados somente quando o SID corresponde ao valor na coluna UserId na tabela TodoItem:

// Get the SID of the current user.
var claimsPrincipal = this.User as ClaimsPrincipal;
string sid = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value;

// Only return data rows that belong to the current user.
return Query().Where(t => t.UserId == sid);

O método Query() retorna um IQueryable que pode ser manipulado pelo LINQ para tratar da filtragem.

Depurar e solucionar problemas do SDK do .NET Server

O Serviço de Aplicativo do Azure fornece várias técnicas de depuração e de solução de problemas para aplicativos ASP.NET.

Registrando em log

É possível gravar em logs de diagnóstico do Serviço de Aplicativo usando a gravação de rastreamento padrão do ASP.NET. Para poder gravar nos logs, habilite o diagnóstico no back-end dos Aplicativos Móveis do Azure.

Para habilitar o diagnóstico e gravar logs:

  1. Siga as etapas em Habilitar o registro do aplicativo (Windows).

  2. Adicione a seguinte instrução de uso em seu arquivo de código:

    using System.Web.Http.Tracing;
    
  3. Crie um gravador de rastreamento para gravar de back-end do .NET para os logs de diagnóstico da seguinte maneira:

    ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
    traceWriter.Info("Hello, World");
    
  4. Republique o projeto de servidor e acesse o back-end dos Aplicativos Móveis do Azure para executar o caminho do código com o registro.

  5. Baixe e avalie os logs, conforme a descrição em Acessar arquivos de log.

Depuração local com autenticação

Você pode executar seu aplicativo localmente a fim de testar as alterações antes de publicá-lo na nuvem. Para a maioria dos back-ends dos Aplicativos Móveis do Azure, pressione F5 enquanto estiver no Visual Studio. No entanto, há algumas considerações adicionais ao usar a autenticação.

Você deve ter um aplicativo móvel baseado em nuvem com a Autenticação/Autorização do Serviço de Aplicativo configurado, e o cliente deve ter o ponto de extremidade de nuvem especificado como o host de logon alternativo. Confira a documentação da sua plataforma cliente para saber as etapas específicas necessárias.

Verifique se seu back-end móvel tem o Microsoft.Azure.Mobile.Server.Authentication instalado. Em seguida, na classe de inicialização OWIN do aplicativo, adicione o seguinte, após aplicar MobileAppConfiguration ao seu HttpConfiguration:

app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions()
{
    SigningKey = ConfigurationManager.AppSettings["authSigningKey"],
    ValidAudiences = new[] { ConfigurationManager.AppSettings["authAudience"] },
    ValidIssuers = new[] { ConfigurationManager.AppSettings["authIssuer"] },
    TokenHandler = config.GetAppServiceTokenHandler()
});

No exemplo anterior, você deve definir as configurações de aplicativo authAudience e authIssuer no arquivo Web.config para que cada uma seja a URL da raiz do aplicativo usando o esquema HTTPS. Da mesma forma, você deve definir authSigningKey como o valor da chave de autenticação de seu aplicativo.

Para obter a chave de assinatura:

  1. Navegue até o aplicativo no Portal do Azure
  2. Clique em Ferramentas>Kudu>Go.
  3. No site de gerenciamento do Kudu, clique em Ambiente.
  4. Encontre o valor de WEBSITE_AUTH_SIGNING_KEY.

Use a chave de assinatura do parâmetro authSigningKey na configuração do aplicativo local. O back-end móvel agora está equipado para validar tokens durante a execução local, em que o cliente obtém o token do ponto de extremidade baseado em nuvem.