Uso del SDK de ASP.NET Framework para Azure Mobile Apps

En este tema se muestra cómo usar el SDK del servidor back-end de .NET en escenarios clave de Azure App Service Mobile Apps. El SDK de Azure Mobile Apps le permite trabajar con clientes móviles de su aplicación ASP.NET.

Advertencia

En este artículo se describe la información de la versión de biblioteca v4.2.0, que se superpone a la biblioteca v5.0.0. Para obtener la información más actualizada, consulte el artículo para obtener la versión más reciente.

Creación de un backend de ASP.NET Framework de para Azure Mobile Apps

Las aplicaciones de ASP.NET Framework se pueden crear mediante Visual Studio 2019.

  • Elija la plantilla Aplicación web ASP.NET (.NET Framework). Si tiene problemas para encontrar esta plantilla, seleccione C#,Todas las plataformas y Web.
  • Después de seleccionar el nombre y la ubicación de la aplicación, seleccione la plantilla de proyecto API web. Se instalará la colección correcta de servicios base para la aplicación.

Descarga e inicialización del SDK

El SDK está disponible en NuGet.orgy proporciona la funcionalidad base necesaria para empezar a usar Azure Mobile Apps. Para instalar el paquete:

  1. Haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet...
  2. En la pestaña Examinar, escriba Microsoft.Azure.Mobile.Server en el cuadro de búsqueda y presione Entrar.
  3. Seleccione el paquete Microsoft.Azure.Mobile.Server.Quickstart.
  4. Haga clic en Instalar.
  5. Siga las instrucciones que aparecen para completar la instalación.

Repita el proceso para instalar Microsoft.Owin.Host.SystemWeb también.

Nota:

No actualice los paquetes que se usan como dependencias, como Newtonsoft.JSON o System.IdentityModel.Jwt. En muchos casos, las API de estos paquetes han cambiado y ahora son incompatibles con Azure Mobile Apps para ASP.NET Framework.

Inicialización del proyecto de servidor

Un proyecto de servidor Azure Mobile Apps se inicializa de manera similar a otros proyectos de ASP.NET Network, mediante la inclusión de una clase de inicio OWIN. Para una clase de inicio OWIN:

  1. Haga clic con el botón derecho en el proyecto y seleccione Agregar>Nuevo elemento.

  2. Seleccione Web>General y, después, seleccione la plantilla Clase de inicio OWIN.

  3. Escriba el nombre Startup.cs como nombre de inicio.

  4. El contenido del archivo Startup.cs debe ser similar al siguiente 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);
            }
        }
    }
    

    OwinStartup, el espacio de nombres y el nombre de clase serán diferentes en función del proyecto. En concreto, debe reemplazar el contenido del método Configuration() y ajustar las directivas using en consecuencia.

Para habilitar características individuales, debe llamar a los métodos de extensión del objeto MobileAppConfiguration antes de llamar a ApplyTo. Por ejemplo, el siguiente código agrega las rutas predeterminadas a todos los controladores de API que tengan el atributo [MobileAppController] durante la inicialización:

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

La siguiente configuración se considera un uso "normal" que permite que los controladores de tabla y de API que usan Entity Framework accedan a un SQL servicio.

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

Los métodos de extensión utilizados son:

  • AddMobileAppHomeController() proporciona la página principal predeterminada de Azure Mobile Apps.
  • MapApiControllers() proporciona funcionalidades de API personalizadas para controladores de WebAPI que contienen el atributo [MobileAppController].
  • AddTables() proporciona una asignación de los puntos de conexión /tables a los controladores de la tabla.
  • AddTablesWithEntityFramework() es un elemento abreviado para la asignación de los puntos de conexión /tables mediante controladores basados en Entity Framework.
  • MapLegacyCrossDomainController() proporciona los encabezados de CORS estándar para el desarrollo local.

Extensiones de SDK

Los siguientes paquetes de extensión basados en NuGet proporcionan diversas características móviles que puede usar la aplicación. Las extensiones se habilitan durante la inicialización mediante el objeto MobileAppConfiguration .

  • Microsoft.Azure.Mobile.Server.Quickstart admite la configuración básica de Mobile Apps. Se agrega a la configuración mediante una llamada al método de extensión UseDefaultConfiguration durante la inicialización. Esta extensión incluye las siguientes extensiones: paquetes de notificaciones, autenticación, entidad, tablas, entre dominios y principal.
  • Microsoft.Azure.Mobile.Server.Home: implementa el elemento this mobile app is up and running page predeterminado para la raíz del sitio web. Se agrega a la configuración mediante una llamada al método de extensión AddMobileAppHomeController .
  • Microsoft.Azure.Mobile.Server.Tables: incluye clases para trabajar con datos y configura la canalización de datos. Se agrega a la configuración mediante una llamada al método de extensión AddTables .
  • Microsoft.Azure.Mobile.Server.Entity: permite a Entity Framework acceder a los datos de SQL Database. Se agrega a la configuración mediante una llamada al método de extensión AddTablesWithEntityFramework .
  • Microsoft.Azure.Mobile.Server.Authentication habilita la autenticación y configura el middleware OWIN que se usa para validar los tokens. Se agrega a la configuración mediante una llamada a los métodos de extensión AddAppServiceAuthentication e IAppBuilder.UseAppServiceAuthentication.
  • Microsoft.Azure.Mobile.Server.Notifications habilita las notificaciones push y define un punto de conexión de registro de inserción. Se agrega a la configuración mediante una llamada al método de extensión AddPushNotifications .
  • Microsoft.Azure.Mobile.Server.CrossDomain crea un controlador que sirve datos de la aplicación móvil a los exploradores web heredados. Se agrega a la configuración mediante una llamada al método de extensión MapLegacyCrossDomainController .
  • Microsoft.Azure.Mobile.Server.Login Proporciona AppServiceLoginHandler.CreateToken(), que es un método estático que se usa durante los escenarios de autenticación.

Publicación del proyecto de servidor

En esta sección se muestra cómo publicar el proyecto de back-end de .NET desde Visual Studio. Hay otros métodos por los que puede publicar una aplicación. Para más información, consulte la documentación de Azure App Service.

  1. En Visual Studio, vuelva a generar el proyecto para restaurar los paquetes de NuGet.
  2. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y luego haga clic en Publicar.
  3. Si no ha publicado el proyecto antes, configurará la publicación.
    • Seleccione Azure como destino.
    • Seleccione Azure App Service (Windows) como destino específico.
    • Seleccione la instancia de App Service en la que desea realizar la implementación. Si no tiene ninguna, use + para crearla.
    • Haga clic en Finalizar
  4. Si no ha vinculado una base de datos SQL antes, haga clic en Configurar junto a SQL Database.
    • Seleccione Azure SQL Database
    • Seleccione la base de datos. Si no tiene ninguna o desea usar otra diferente, haga clic en + para crear una base de datos y un servidor.
    • Escriba MS_TableConnectionString como nombre de la cadena de conexión de base de datos. Rellene el nombre de usuario y la contraseña en los cuadros proporcionados.
    • Haga clic en Finish (Finalizar).
  5. Haga clic en Publicar.

La publicación en Azure tarda algún tiempo en realizarse. Para más información, consulte la documentación de Visual Studio.

Definición de un controlador de tabla

Defina un controlador de tabla para exponer una tabla de SQL para clientes móviles. La configuración de un controlador de tabla requiere tres pasos:

  1. Creación de una clase Data Transfer Object (DTO).
  2. Configuración de una referencia de tabla en la clase Mobile DbContext.
  3. Creación de un controlador de tabla.

Un objeto de transferencia de datos (DTO) es un objeto de C# simple heredado de EntityData. Por ejemplo:

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

El objeto DTO se utiliza para definir la tabla en SQL Database. Para crear la entrada de la base de datos, agregue una propiedad DbSet<> a la instancia de DbContext que utilice:

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 último, cree un controlador:

  1. Haga clic con el botón derecho en la carpeta Controllers.

  2. Seleccione API web>Controlador de Web API 2 - en blanco

  3. Escriba un nombre para el controlador.

  4. Reemplace el contenido del nuevo controlador por el código siguiente:

    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);
        }
    }
    

Cómo ajustar el tamaño de paginación de la tabla

De forma predeterminada, Azure Mobile Apps devuelve 50 registros por solicitud. La paginación garantiza que el cliente no mantenga ocupado su subproceso de interfaz de usuario ni el servidor durante mucho tiempo, con lo que se asegura una buena experiencia del usuario. Para cambiar el tamaño de paginación de la tabla, aumente el "tamaño de consulta permitido" del lado del servidor y cambie el tamaño de la página de lado del cliente. El "tamaño de consulta permitido" del lado del servidor se ajusta con el atributo EnableQuery:

[EnableQuery(PageSize = 500)]

Asegúrese de que el valor de PageSize sea igual o mayor que el tamaño solicitado por el cliente. Consulte la documentación de procedimientos para obtener más información sobre cómo cambiar el tamaño de página de cliente.

Cómo definir un controlador de API personalizada

El controlador de API personalizada proporciona la funcionalidad más básica al back-end de la aplicación móvil mediante la exposición de un extremo. Puede registrar un controlador de API específico de dispositivos móviles con el atributo [MobileAppController]. El atributo MobileAppController registra la ruta, configura el serializador JSON de Mobile Apps y activa la comprobación de la versión del cliente.

Este es el contenido del controlador de API personalizada:

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

Una vez configurado con el atributo MobileAppController, puede definir la API personalizada de la misma manera que cualquier otra API web.

Trabajar con la autenticación

Azure Mobile Apps usa la autenticación o autorización de App Service para proteger su back-end móvil. En esta sección se muestra cómo realizar las siguientes tareas relacionadas con la autenticación en el proyecto de servidor back-end. NET:

Adición de autenticación a un proyecto de servidor

Para agregar autenticación al proyecto de servidor, extienda el objeto MobileAppConfiguration y configure el middleware OWIN.

  1. En Visual Studio, instale el paquete Microsoft.Azure.Mobile.Server.Authentication .

  2. En el archivo de proyecto Startup.cs, agregue la siguiente línea de código al principio del método Configuration:

    app.UseAppServiceAuthentication(config);
    

    Este componente del middleware OWIN valida los tokens emitidos por la puerta de enlace de App Service asociada.

  3. Agregue el atributo [Authorize] a cualquier controlador o método que requiera autenticación.

Uso de autenticación personalizada para una aplicación

Importante

Con el fin de habilitar la autenticación personalizada, primero debe habilitar la autenticación de App Service sin seleccionar un proveedor para la instancia en Azure Portal. Así se habilitará la variable de entorno WEBSITE_AUTH_SIGNING_KEY cuando se hospede.

Si no desea usar uno de los proveedores de autenticación y autorización de App Service, puede implementar su propio sistema de inicio de sesión. Instale el paquete Microsoft.Azure.Mobile.Server.Login para ayudar a la generación de tokens de autenticación. Proporcione su propio código para validar las credenciales del usuario. Por ejemplo, podría comprobar las contraseñas con sal y hash de una base de datos. En el ejemplo siguiente, el método isValidAssertion() (definido en otra parte) es responsable de estas comprobaciones.

La autenticación personalizada se expone mediante la creación de un controlador ApiController y la exposición de las acciones register y login. El cliente debe utilizar una interfaz de usuario personalizada para recopilar la información del usuario. A continuación, la información se envía a la API con una llamada HTTP POST estándar. Una vez que el servidor valida la aserción, se emite un token con el método AppServiceLoginHandler.CreateToken() . El controlador ApiController no debería utilizar el atributo [MobileAppController].

Ejemplo de la acción login :

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();
    }
}

En el ejemplo anterior, LoginResult y LoginResultUser son objetos serializables que exponen las propiedades necesarias. El cliente espera que las repuestas de inicio de sesión se devuelvan como objetos JSON con este formato:

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

El método AppServiceLoginHandler.CreateToken() incluye un parámetro audience y un parámetro issuer. Ambos parámetros se establecen en la dirección URL de la raíz de la aplicación, mediante el esquema HTTPS. De igual modo, debe establecer secretKey como el valor de la clave de firma de la aplicación. No distribuya la clave de firma en un cliente, ya que se puede usar para inventar claves y suplantar a los usuarios. Puede obtener la clave de firma mientras se hospeda en App Service mediante la referencia a la variable de entorno WEBSITE_AUTH_SIGNING_KEY. Si es necesario en un contexto de depuración local, siga las instrucciones de la sección Depuración local con autenticación para recuperar la clave y almacenarla como un valor de configuración de la aplicación.

El token emitido también puede incluir otras notificaciones y una fecha de expiración. Como mínimo, el token emitido debe incluir una notificación de asunto (sub).

Puede admitir el método loginAsync() del cliente estándar mediante la sobrecarga de la ruta de autenticación. Si el cliente llama a client.loginAsync('custom'); para iniciar sesión, la ruta debe ser /.auth/login/custom. Puede establecer la ruta para el controlador de autenticación personalizada con MapHttpRoute():

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

Sugerencia

Con el enfoque loginAsync() se garantiza que el token de autenticación se asocia a cada llamada posterior al servicio.

Recuperación de la información del usuario autenticado

Cuando un usuario se autentica mediante App Service, se puede tener acceso al id. de usuario asignado y otra información en el código del back-end. NET. La información de usuario se puede utilizar para tomar decisiones de autorización en el back-end. El código siguiente obtiene el identificador de usuario asociado a una solicitud:

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

El SID se deriva del identificador de usuario específico del proveedor y es estático para un usuario y un proveedor de inicio de sesión dados. El SID es nulo para los tokens de autenticación no válidos.

App Service también le permite solicitar notificaciones específicas de su proveedor de inicio de sesión. Cada proveedor de identidades puede proporcionar más información mediante el SDK del proveedor de identidades. Por ejemplo, puede usar Graph API de Facebook para la información de los amigos. Puede especificar notificaciones solicitadas en la hoja del proveedor en Azure Portal. Algunas notificaciones requieren más configuración con el proveedor de identidades.

El código siguiente llama al método de extensión GetAppServiceIdentityAsync para obtener las credenciales de inicio de sesión, que incluyen el token de acceso necesario para realizar solicitudes en la API Graph de 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();
}

Agregue una instrucción de uso para que System.Security.Principal proporcione el método de extensión GetAppServiceIdentityAsync .

Restricción del acceso a los datos a los usuarios autorizados

En la sección anterior, hemos mostrado cómo recuperar el identificador de usuario de un usuario autenticado. Puede restringir el acceso a datos y otros recursos basándose en este valor. Por ejemplo, agregar una columna de identificador de usuario (userId) a las tablas y filtrar los resultados de la consulta por el identificador de usuario es una manera sencilla de limitar los datos devueltos únicamente a los usuarios autorizados. El código siguiente solo devuelve filas de datos cuando el SID coincide con el valor de la columna UserId de la tabla 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);

El método Query() devuelve un IQueryable que LINQ puede manipular para controlar el filtrado.

Depuración y solución de problemas del SDK de .NET Server

Azure App Service proporciona varias técnicas de depuración y solución de problemas para las aplicaciones ASP.NET.

Registro

Puede escribir en registros de diagnóstico de App Service mediante la escritura de seguimiento estándar de ASP.NET. Para poder escribir en los registros, debe habilitar los diagnósticos en el backend de Azure Mobile Apps.

Para habilitar los diagnósticos y escribir en los registros:

  1. Siga los pasos que se indican en Habilitar el registro de aplicaciones (Windows).

  2. Agregue la siguiente instrucción using en el archivo de código:

    using System.Web.Http.Tracing;
    
  3. Cree un escritor de seguimiento para escribir desde el back-end de .NET en los registros de diagnóstico, de la manera siguiente:

    ITraceWriter traceWriter = this.Configuration.Services.GetTraceWriter();
    traceWriter.Info("Hello, World");
    
  4. Vuelva a publicar el proyecto de servidor y acceda al backend de Azure Mobile Apps para ejecutar la ruta de acceso del código con el registro.

  5. Descargue y evalúe los registros, como se describe en Acceso a los archivos de registro.

Depuración local con autenticación

Puede ejecutar la aplicación localmente para probar los cambios antes de publicarlos en la nube. Para la mayoría de los servidores back-end de Azure Mobile Apps, presione F5 mientras está en Visual Studio. Sin embargo, hay algunas consideraciones adicionales que se deben tener en cuenta cuando se usa la autenticación.

Debe tener una aplicación móvil basada en la nube que tenga configurada la característica Autenticación/autorización de App Service, y su cliente debe haber especificado el punto de conexión de nube como host de inicio de sesión alternativo. Consulte la documentación de la plataforma cliente para los pasos específicos requeridos.

Asegúrese de que el back-end tenga instalado Microsoft.Azure.Mobile.Server.Authentication . Después, en la clase de inicio OWIN de la aplicación, agregue lo siguiente, después de aplicar MobileAppConfiguration a HttpConfiguration:

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

En el ejemplo anterior, debe configurar los parámetros de la aplicación authAudience y authIssuer en el archivo Web.config para que cada uno sea la dirección URL de la raíz de la aplicación; para ello, usará el esquema HTTPS. De igual modo, debe establecer authSigningKey como el valor de la clave de firma de la aplicación.

Para obtener la clave de firma:

  1. Vaya a la aplicación en Portal de Azure
  2. Haga clic en Herramientas>Kudu>Ir.
  3. En el sitio de administración de Kudu, haga clic en Entorno.
  4. Busque el valor de WEBSITE_AUTH_SIGNING_KEY.

Use la clave de firma para el parámetro authSigningKey en la configuración de la aplicación local. El back-end para dispositivos móviles ahora está equipado para validar los tokens cuando se ejecutan localmente, el cliente obtiene el token del punto de conexión basado en la nube.