Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Aprende a escribir una aplicación para UWP que usa el Portal de dispositivos Windows (WDP) para hospedar una página web y proporcionar información de diagnóstico.
A partir de Windows 10 Creators Update (versión 1703, compilación 15063), puedes usar Device Portal para hospedar las interfaces de diagnóstico de la aplicación. En este artículo se describen las tres partes necesarias para crear un DevicePortalProvider para la aplicación: el manifiesto del paquete de aplicación cambia, la configuración de la conexión de la aplicación al servicio Device Portal y el control de una solicitud entrante.
Crear un nuevo proyecto de aplicación para UWP
En Microsoft Visual Studio, cree un nuevo proyecto de aplicación para UWP. Vaya a Archivo > Nuevo proyecto de > y seleccione Aplicación en blanco (Windows Universal) para C#y haga clic en Siguiente. En el cuadro de diálogo Configura tu nuevo proyecto. Asigne al proyecto el nombre "DevicePortalProvider" y haga clic en Crear. Esta será la aplicación que contiene el servicio de aplicaciones. Es posible que tenga que actualizar Visual Studio o instalar el SDK de Windows más reciente.
Adición de la extensión devicePortalProvider al manifiesto del paquete de aplicación
Tendrás que agregar código al archivo package.appxmanifest para que la aplicación funcione como complemento de Device Portal. En primer lugar, agregue las siguientes definiciones de espacio de nombres en la parte superior del archivo. Agréguelos también al IgnorableNamespaces
atributo .
<Package
...
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
IgnorableNamespaces="uap mp rescap uap4">
...
Para declarar que su aplicación es un Proveedor de Portal de Dispositivos, debe crear un servicio de aplicaciones y una nueva extensión de Proveedor de Portal de Dispositivos que lo use. Agregue las extensiones windows.appService y windows.devicePortalProvider en el elemento Extensions
bajo Application
. Asegúrese de que los AppServiceName
atributos coinciden en cada extensión. Esto indica al servicio Device Portal que este servicio de aplicación se puede iniciar para gestionar las solicitudes en el espacio de nombres del controlador.
...
<Application
Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="DevicePortalProvider.App">
...
<Extensions>
<uap:Extension Category="windows.appService" EntryPoint="MySampleProvider.SampleProvider">
<uap:AppService Name="com.sampleProvider.wdp" />
</uap:Extension>
<uap4:Extension Category="windows.devicePortalProvider">
<uap4:DevicePortalProvider
DisplayName="My Device Portal Provider Sample App"
AppServiceName="com.sampleProvider.wdp"
HandlerRoute="/MyNamespace/api/" />
</uap4:Extension>
</Extensions>
</Application>
...
El HandlerRoute
atributo hace referencia al espacio de nombres REST reclamado por la aplicación. Las solicitudes HTTP en ese espacio de nombres (seguido implícitamente de un carácter comodín) recibidos por el servicio Device Portal se enviarán a la aplicación para que sea gestionada. En este caso, cualquier solicitud HTTP autenticada correctamente a <ip_address>/MyNamespace/api/*
se enviará a tu aplicación. Los conflictos entre las rutas de controlador se resuelven mediante una comprobación de "la coincidencia más extensa": se selecciona la ruta que coincida con más peticiones, lo que significa que una solicitud a "/MyNamespace/api/foo" coincidirá con un proveedor con "/MyNamespace/api" en lugar de "/MyNamespace".
Se requieren dos nuevas funcionalidades para esta funcionalidad. también deben agregarse al archivo package.appxmanifest.
...
<Capabilities>
...
<Capability Name="privateNetworkClientServer" />
<rescap:Capability Name="devicePortalProvider" />
</Capabilities>
...
Nota:
La funcionalidad "devicePortalProvider" está restringida ("rescap"), lo que significa que debes obtener la aprobación previa de la Tienda para que la aplicación se pueda publicar allí. Sin embargo, esto no te impide probar tu aplicación localmente a través de la carga lateral. Para obtener más información sobre las funcionalidades restringidas, consulte Declaraciones de funcionalidad de la aplicación.
Configura tu tarea en segundo plano y el componente WinRT
Para configurar la conexión con el Portal de Dispositivos, tu aplicación debe establecer una conexión de servicio de aplicación desde el servicio del Portal de Dispositivos con la instancia del Portal de Dispositivos que se ejecuta dentro de tu aplicación. Para ello, agregue un nuevo componente winRT a la aplicación con una clase que implemente IBackgroundTask.
using Windows.System.Diagnostics.DevicePortal;
using Windows.ApplicationModel.Background;
namespace MySampleProvider {
// Implementing a DevicePortalConnection in a background task
public sealed class SampleProvider : IBackgroundTask {
BackgroundTaskDeferral taskDeferral;
DevicePortalConnection devicePortalConnection;
//...
}
Asegúrese de que su nombre coincide con el espacio de nombres y el nombre de clase configurados por AppService EntryPoint ("MySampleProvider.SampleProvider"). Al hacer su primera solicitud al proveedor de Device Portal, Device Portal guardará la solicitud, iniciará la tarea en segundo plano de su aplicación, llamará a su método Run y pasará un IBackgroundTaskInstance. A continuación, la aplicación la usa para configurar una instancia de DevicePortalConnection .
// Implement background task handler with a DevicePortalConnection
public void Run(IBackgroundTaskInstance taskInstance) {
// Take a deferral to allow the background task to continue executing
this.taskDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += TaskInstance_Canceled;
// Create a DevicePortal client from an AppServiceConnection
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
var appServiceConnection = details.AppServiceConnection;
this.devicePortalConnection = DevicePortalConnection.GetForAppServiceConnection(appServiceConnection);
// Add Closed, RequestReceived handlers
devicePortalConnection.Closed += DevicePortalConnection_Closed;
devicePortalConnection.RequestReceived += DevicePortalConnection_RequestReceived;
}
Hay dos eventos que la aplicación debe controlar para completar el bucle de control de solicitudes: Closed, para cada vez que el servicio Device Portal se cierra y RequestReceived, que muestra las solicitudes HTTP entrantes y proporciona la funcionalidad principal del proveedor de Device Portal.
Control del evento RequestReceived
El evento RequestReceived se generará una vez para cada solicitud HTTP que se realice en la ruta de controlador especificada del complemento. El bucle de control de solicitudes para los proveedores de Device Portal es similar al de NodeJS Express: los objetos de solicitud y respuesta se proporcionan junto con el evento y el controlador responde rellenando el objeto de respuesta. En los proveedores de Device Portal, el evento RequestReceived y sus controladores usan objetos Windows.Web.Http.HttpRequestMessage y HttpResponseMessage.
// Sample RequestReceived echo handler: respond with an HTML page including the query and some additional process information.
private void DevicePortalConnection_RequestReceived(DevicePortalConnection sender, DevicePortalConnectionRequestReceivedEventArgs args)
{
var req = args.RequestMessage;
var res = args.ResponseMessage;
if (req.RequestUri.AbsolutePath.EndsWith("/echo"))
{
// construct an html response message
string con = "<h1>" + req.RequestUri.AbsoluteUri + "</h1><br/>";
var proc = Windows.System.Diagnostics.ProcessDiagnosticInfo.GetForCurrentProcess();
con += String.Format("This process is consuming {0} bytes (Working Set)<br/>", proc.MemoryUsage.GetReport().WorkingSetSizeInBytes);
con += String.Format("The process PID is {0}<br/>", proc.ProcessId);
con += String.Format("The executable filename is {0}", proc.ExecutableFileName);
res.Content = new Windows.Web.HttpStringContent(con);
res.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("text/html");
res.StatusCode = Windows.Web.Http.HttpStatusCode.Ok;
}
//...
}
En este controlador de solicitudes de ejemplo, primero extraemos los objetos de solicitud y respuesta del parámetro args y, a continuación, creamos una cadena con la dirección URL de la solicitud y algún formato HTML adicional. Esto se agrega al objeto Response como una instancia httpStringContent . También se permiten otras clases IHttpContent , como las de "String" y "Buffer".
A continuación, la respuesta se establece como una respuesta HTTP y se proporciona un código de estado 200 (CORRECTO). Debe representarse según lo previsto en el explorador que realizó la llamada original. Tenga en cuenta que cuando el controlador de eventos RequestReceived devuelve, el mensaje de respuesta se devuelve automáticamente al agente de usuario: no es necesario un método "send" adicional.
Proporcionar contenido estático
El contenido estático se puede servir directamente desde una carpeta dentro del paquete, lo que facilita la adición de una interfaz de usuario al proveedor. La manera más fácil de servir contenido estático es crear una carpeta de contenido en el proyecto que se pueda asignar a una dirección URL.
A continuación, agregue un controlador de rutas en el controlador de eventos RequestReceived, que detecte rutas de contenido estático y asigne correctamente una solicitud.
if (req.RequestUri.LocalPath.ToLower().Contains("/www/")) {
var filePath = req.RequestUri.AbsolutePath.Replace('/', '\\').ToLower();
filePath = filePath.Replace("\\backgroundprovider", "")
try {
var fileStream = Windows.ApplicationModel.Package.Current.InstalledLocation.OpenStreamForReadAsync(filePath).GetAwaiter().GetResult();
res.StatusCode = HttpStatusCode.Ok;
res.Content = new HttpStreamContent(fileStream.AsInputStream());
res.Content.Headers.ContentType = new HttpMediaTypeHeaderValue("text/html");
} catch(FileNotFoundException e) {
string con = String.Format("<h1>{0} - not found</h1>\r\n", filePath);
con += "Exception: " + e.ToString();
res.Content = new Windows.Web.Http.HttpStringContent(con);
res.StatusCode = Windows.Web.Http.HttpStatusCode.NotFound;
res.Content.Headers.ContentType = new Windows.Web.Http.Headers.HttpMediaTypeHeaderValue("text/html");
}
}
Asegúrese de que todos los archivos dentro de la carpeta de contenido estén marcados como "Contenido" y establezca en "Copiar si es más reciente" o "Copiar siempre" en el menú Propiedades de Visual Studio. Esto garantiza que los archivos estarán dentro del paquete AppX al implementarlos.
Uso de recursos y API existentes del Portal de dispositivos
El contenido estático servido por un proveedor de Device Portal se sirve en el mismo puerto que el servicio principal del Portal de dispositivos. Esto significa que puede hacer referencia a los JS y CSS existentes incluidos en Device Portal con etiquetas simples <link>
y <script>
en su HTML. En general, se recomienda el uso de rest.js, que encapsula todas las API REST principales del Portal de dispositivos en un práctico objeto webbRest y el archivo common.css , que le permitirá aplicar estilo al contenido para que se ajuste al resto de la interfaz de usuario del Portal de dispositivos. Puede ver un ejemplo de esto en la página index.html incluida en el ejemplo. Usa rest.js para recuperar el nombre del dispositivo y ejecutar procesos desde Device Portal.
Es importante que el uso de los métodos HttpPost/DeleteExpect200 en webbRest realice automáticamente el control de CSRF, lo que permite que la página web realice llamadas a las APIs REST que cambian de estado.
Nota:
El contenido estático incluido en Device Portal no viene con una garantía contra cambios disruptivos. Aunque no se espera que las API cambien a menudo, pueden, especialmente en los archivoscommon.js y controls.js , que el proveedor no debe usar.
Solución de problemas de la conexión del portal de dispositivos
Para depurar su tarea en segundo plano, debe cambiar la forma en que Visual Studio ejecuta su código. Siga los siguientes pasos para depurar una conexión al Servicio de Aplicaciones y así inspeccionar cómo maneja el proveedor las solicitudes HTTP.
- En el menú Depurar, seleccione las propiedades de DevicePortalProvider.
- En la pestaña Depuración, en la sección Iniciar acción, seleccione "No iniciar, pero depurar mi código cuando se inicie".
- Establezca un punto de interrupción en la función de controlador RequestReceived.
Nota:
Asegúrese de que la arquitectura de compilación coincide exactamente con la arquitectura del objetivo. Si usa un equipo de 64 bits, debe implementar con una compilación AMD64. 4. Presione F5 para implementar la aplicación 5. Desactive Device Portal y, a continuación, vuelva a activarlo para que encuentre la aplicación (solo es necesario cuando cambie el manifiesto de la aplicación, el resto del tiempo que puede volver a implementar y omitir este paso). 6. En el navegador, acceda al espacio de nombres del proveedor y el punto de interrupción se activará.