Documentación automática de servicios WebAPI

ASP.NETCuando trabajábamos con los Servicios Web de toda la vida, las herramientas de desarrollo incluían sistemas para generar la documentación básica de los servicios que implementábamos. El estándar WSDL (Web Services Description Language), era un lenguaje basado en XML que permitía describir las funcionalidades de un servicio web aportando gran cantidad de detalles sobre las operaciones, tipos de datos, o direcciones de acceso a las mismas.

Gracias a esto, los desarrolladores podíamos conectarnos fácilmente a un servicio para consultar sus especificaciones técnicas, o incluso generar de forma automática código cliente o proxies que facilitaran el acceso remoto a las funciones publicadas en la red.

Y para los que venimos de esos tiempos, una de las primeras dudas que surgen al comenzar a trabajar con WebAPI es si existe algo similar. Y la respuesta es sí, pero no ;-P

De momento no existe ningún estándar ni especificación que permita describir los servicios WebAPI con la riqueza y formalización que permite WSDL. Esta tecnología se basa únicamente en HTTP, por lo que, a lo sumo, podríamos intuir el comportamiento de los sistemas partiendo de las direcciones de los recursos y los verbos HTTP utilizados, siempre que estén diseñados conformes al estilo REST, por supuesto.

Lo que sí tenemos es un paquete, descargable a través de Nuget, que nos puede ayudar bastante a generar páginas de ayuda y documentación para nuestros API partiendo de la documentación XML que incluyamos en el código. A diferencia de WSDL, en este caso no tendremos una definición formal de las operaciones que pueda ser consumida por otros sistemas debido a la ausencia de un estándar para ello, pero sí podremos conseguir un documento bastante razonable para que un desarrollador ser haga una idea clara de cómo usar nuestros servicios.

1. Empezando por el final…

Para que os hagáis una idea del resultado antes de ver cómo conseguirlo, ahí van un par de capturas de pantalla de la página de ayuda generada para un controlador WebAPI como el siguiente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class CustomerController: ApiController
{
    /// <summary>
    /// Gets a Customer
    /// </summary>
    /// <param name="id">Customer's Id</param>
    /// <returns>The Customer</returns>
    public Customer Get(int id)
    {
        // Code
    }
    /// <summary>
    /// Creates a new Customer
    /// </summary>
    /// <param name="customer">The customer</param>
    /// <returns>HTTP response with the result of this operation</returns>
    public HttpResponseMessage Post(Customer customer)
    {
        // Code
    }
    /// <summary>
    /// Updates a Customer
    /// </summary>
    /// <param name="customer">The customer</param>
    /// <returns>HTTP response with the result of this operation</returns>
    public HttpResponseMessage Put(int id, Customer customer)
    {
        // Code
    }
    /// <summary>
    /// Deletes a customer
    /// </summary>
    /// <param name="id">Customer's id</param>
    /// <returns>HTTP response with the result of this operation</returns>
    public HttpResponseMessage Delete(int id)
    {
        // Code
    }
}

Las páginas de ayuda generada tienen esta pinta:

Página de ayuda de WebAPI

Página de ayuda de WebAPI
Veamos ahora cómo conseguirlo.

2. Instalación del paquete

El componente que incluye la magia necesaria para generar la documentación se distribuye a través de Nuget, en el paquete Microsoft.AspNet.WebApi.Help. Su instalación, como siempre, es inmediata:

Install-Package Microsoft.AspNet.WebApi.HelpPage –Pre

La única particularidad que podéis ver en la línea anterior es la inclusión del parámetro “–pre”. Esto es necesario en la actualidad porque se trata de un componente en versión preliminar, pero una vez se publique la versión final ya no será necesario. Por tanto, si lo hacéis desde el IDE de Nuget, tenéis que recordar seleccionar la opción de permitir prereleases para que os aparezca el paquete y podáis descargarlo.

imageEn cualquier caso, tras descargar e instalar este paquete, el principal cambio que notaremos en el proyecto es la inclusión de un Área (MVC) llamada HelpPage, tal y como se muestra en la captura de pantalla adjunta.

El código incluido en este área es el responsable de registrar la ruta de acceso a las páginas de ayuda (por defecto en /help), y de procesar las peticiones de consulta. Internamente se usa ApiExplorer, una característica incluida en la última versión de System.Net.Http, que implementa todos los mecanismos de introspección necesarios para obtener las descripciones de las clases y métodos que componen nuestro API.

Dentro de la misma podemos encontrar también el código de la clase XmlDocumentationProvider, que será la encargada de extraer la documentación partiendo de los archivos XML generados durante la compilación a partir de los comentarios incluidos en el código.

3. Activación de comentarios XML

Por tanto, lo siguiente que debemos hacer es activar la generación del archivo XML de documentación en las propiedades del proyecto, indicando su nombre y ubicación:

Activar la documentación XML

Hecho esto, como podremos comprobar la primera vez que compilemos, los comentarios sobre las clases y métodos del proyecto sean incluidos en el archivo XML. Sin embargo, también veremos que tiene un pequeño efecto colateral bastante molesto: Visual Studio mostrará un warning por cada miembro o tipo público que no describamos.

Warning: falta comentario XML

Para solucionarlo, de nuevo sobre la pestaña “Build” de las propiedades del proyecto, podemos desactivar el aviso de warning 1591, que es el que nos está mostrando:

image

4. Registrar y configurar el proveedor de documentación basado en comentarios XML

El siguiente paso es registrar el proveedor XmlDocumentationProvider e informarlo de la ruta donde se encuentra el archivo de documentación generado. Esto lo hacemos descomentando una línea en el archivo /Areas/HelpPage/App_Start/HelpPageConfig.cs y estableciendo la ruta configurada anteriormente:

1
2
3
4
5
6
7
8
9
10
11
12
public static class HelpPageConfig
{
    public static void Register(HttpConfiguration config)
    {
        //// Uncomment the following to use the documentation from XML documentation file.
        config.SetDocumentationProvider(
            new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/bin/WebApiDemo.xml"))
        );
 
        [...] // Code ommited for brevity
    }
}

¡Y esto es todo lo que hay que hacer! 🙂 A partir de este momento, ya podremos acceder a la URL /help (o la indicada en la ruta del área) y consultar las ayudas generadas. Por defecto el sistema incluirá documentación para todos los controladores WebAPI del proyecto, salvo aquellos que sean decorados con el atributo ApiExplorerSettings de la siguiente forma:

1
2
3
4
5
6
// This controller will be ignored
[ApiExplorerSettings(IgnoreApi = true)]
public class MyController : ApiController
{
   [...]
}

5. Personalizar la apariencia y comportamiento

El hecho de que este paquete se distribuya en forma de área tiene como ventaja que su código fuente se introducirá en nuestro proyecto, permitiéndonos modificar con bastante libertad la forma en que estas páginas son generadas.

En el mismo archivo /Areas/HelpPage/App_Start/HelpPageConfig.cs que ya hemos modificado anteriormente es posible modificar diversos aspectos de la documentación, como los valores a usar para los distintos tipos de dato cuando se muestran ejemplos o en acciones concretas, entre otros. Vale la pena echarle un vistazo y jugar con las distintas opciones, que vienen comentadas sobre el código fuente del archivo.

También en la carpeta de vistas del área, ubicada en /Areas/HelpPage/Views encontraremos los archivos .cshtml utilizados para visualizar el índice general y la página de detalle de una acción (index.cshtml y api.cshtml respectivamente), así como las vistas parciales usadas para mostrar cada uno de los elementos mostrados al usuario (controladores o grupos de API, parámetros de las acciones, etc.). También encontraremos un Layout básico en la carpeta /Views/Shared, que por supuesto podemos ignorar completamente si cambiamos la referencia al mismo en el archivo _ViewStart.cshtml que encontramos sobre la misma carpeta de vistas del área. En este artículo podéis encontrar información sobre el contenido de cada archivo y ejemplos de personalizaciones.

Por último, es posible modificar la forma en que se genera el código de ejemplo, que encontraremos implementados en la carpeta /SampleGeneration del área, lo que puede resultar muy útil cuando existe algún motivo que impide que el sistema infiera correctamente los tipos de datos usados para serializarlos (por ejemplo, esto ocurre cuando nuestras acciones retornan un objeto HttpResponseMessage). Podéis ver algunos ejemplos de uso de generadores personalizados en este post.
 
Publicado en Variable not found.

Actualizar todos los paquetes Nuget de un proyecto

NugetAunque a muchos pueda parecer simple, hay gran cantidad de desarrolladores que para actualizar los paquetes Nuget de un proyecto acuden a la herramienta de gestión incluida en el IDE y van actualizando uno por uno los componentes instalados.

Pues bien, resulta que desde hace algún tiempo, Nuget soporta la actualización automática de todos los paquetes de una solución. Para ello, basta con acudir a la consola de administración de paquetes (Tools > Library Package Manager > Package Manager Console) e introducir el comando update-package:

Consola de administración de paquetes
Por ejemplo, sobre una aplicación MVC 4 recién creada, el resultado es el siguiente:

PM> update-package
Updating 'Modernizr' from version '2.5.3' to '2.6.2' in project 'MyMvcProject'.
Successfully removed 'Modernizr 2.5.3' from MyMvcProject.
Successfully installed 'Modernizr 2.6.2'.
Successfully added 'Modernizr 2.6.2' to MyMvcProject.
Successfully uninstalled 'Modernizr 2.5.3'.
No updates available for 'Microsoft.jQuery.Unobtrusive.Validation' in project 'MyMvcProject'.
No updates available for 'Microsoft.jQuery.Unobtrusive.Ajax' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebPages.OAuth' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebPages.WebData' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebPages.Data' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebApi' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebApi.WebHost' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebApi.Core' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebApi.Client' in project 'MyMvcProject'.
Updating 'Newtonsoft.Json' from version '4.5.6' to '4.5.11' in project 'MyMvcProject'.
Successfully removed 'Newtonsoft.Json 4.5.6' from MyMvcProject.
Successfully installed 'Newtonsoft.Json 4.5.11'.
Successfully added 'Newtonsoft.Json 4.5.11' to MyMvcProject.
Successfully uninstalled 'Newtonsoft.Json 4.5.6'.
No updates available for 'Microsoft.Net.Http' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.Web.Optimization' in project 'MyMvcProject'.
Updating 'WebGrease' from version '1.1.0' to '1.3.0' in project 'MyMvcProject'.
Successfully removed 'WebGrease 1.1.0' from MyMvcProject.
You are downloading WebGrease from webgrease@microsoft.com, the license agreement to which is available at http://www.microsoft.com/web/webpi/eula/msn_webgrease_eula.htm. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'WebGrease 1.3.0'.
Successfully added 'WebGrease 1.3.0' to MyMvcProject.
Successfully uninstalled 'WebGrease 1.1.0'.
No updates available for 'Microsoft.AspNet.Mvc' in project 'MyMvcProject'.
No updates available for 'Microsoft.AspNet.WebPages' in project 'MyMvcProject'.
Updating 'Microsoft.AspNet.Razor' from version '2.0.20710.0' to '2.0.20715.0' in project 'MyMvcProject'.
Successfully removed 'Microsoft.AspNet.Razor 2.0.20710.0' from MyMvcProject.
You are downloading Microsoft.AspNet.Razor from Microsoft, the license agreement to which is available at http://www.microsoft.com/web/webpi/eula/WebPages_2_eula_ENU.htm. Check the package for additional dependencies, which may come with their own license agreement(s). Your use of the package and dependencies constitutes your acceptance of their license agreements. If you do not accept the license agreement(s), then delete the relevant components from your device.
Successfully installed 'Microsoft.AspNet.Razor 2.0.20715.0'.
Successfully added 'Microsoft.AspNet.Razor 2.0.20715.0' to MyMvcProject.
Successfully uninstalled 'Microsoft.AspNet.Razor 2.0.20710.0'.
No updates available for 'Microsoft.Web.Infrastructure' in project 'MyMvcProject'.
Updating 'knockoutjs' from version '2.1.0' to '2.2.0' in project 'MyMvcProject'.
Successfully removed 'knockoutjs 2.1.0' from MyMvcProject.
Successfully installed 'knockoutjs 2.2.0'.
Successfully added 'knockoutjs 2.2.0' to MyMvcProject.
Successfully uninstalled 'knockoutjs 2.1.0'.
Updating 'jQuery.Validation' from version '1.9.0.1' to '1.10.0' in project 'MyMvcProject'.
Successfully removed 'jQuery.Validation 1.9.0.1' from MyMvcProject.
Successfully installed 'jQuery.Validation 1.10.0'.
Successfully added 'jQuery.Validation 1.10.0' to MyMvcProject.
Successfully uninstalled 'jQuery.Validation 1.9.0.1'.
Updating 'jQuery.UI.Combined' from version '1.8.20.1' to '1.9.0' in project 'MyMvcProject'.
Successfully removed 'jQuery.UI.Combined 1.8.20.1' from MyMvcProject.
Successfully installed 'jQuery.UI.Combined 1.9.0'.
Successfully added 'jQuery.UI.Combined 1.9.0' to MyMvcProject.
Successfully uninstalled 'jQuery.UI.Combined 1.8.20.1'.
Updating 'jQuery' from version '1.7.1.1' to '1.8.2' in project 'MyMvcProject'.
Successfully removed 'jQuery 1.7.1.1' from MyMvcProject.
Successfully installed 'jQuery 1.8.2'.
Successfully added 'jQuery 1.8.2' to MyMvcProject.
Successfully uninstalled 'jQuery 1.7.1.1'.
No updates available for 'EntityFramework' in project 'MyMvcProject'.
Updating 'DotNetOpenAuth.AspNet' from version '4.0.3.12153' to '4.1.3.12303' in project 'MyMvcProject'.
Successfully removed 'DotNetOpenAuth.AspNet 4.0.3.12153' from MyMvcProject.
Successfully removed 'DotNetOpenAuth.OAuth.Consumer 4.0.3.12153' from MyMvcProject.
Successfully removed 'DotNetOpenAuth.OAuth.Core 4.0.3.12153' from MyMvcProject.
Successfully removed 'DotNetOpenAuth.OpenId.RelyingParty 4.0.3.12153' from MyMvcProject.
Successfully removed 'DotNetOpenAuth.OpenId.Core 4.0.3.12153' from MyMvcProject.
Successfully removed 'DotNetOpenAuth.Core 4.0.3.12153' from MyMvcProject.
Successfully installed 'DotNetOpenAuth.Core 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.Core 4.1.3.12303' to MyMvcProject.
Successfully installed 'DotNetOpenAuth.OpenId.Core 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.OpenId.Core 4.1.3.12303' to MyMvcProject.
Successfully installed 'DotNetOpenAuth.OpenId.RelyingParty 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.OpenId.RelyingParty 4.1.3.12303' to MyMvcProject.
Successfully installed 'DotNetOpenAuth.OAuth.Core 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.OAuth.Core 4.1.3.12303' to MyMvcProject.
Successfully installed 'DotNetOpenAuth.OAuth.Consumer 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.OAuth.Consumer 4.1.3.12303' to MyMvcProject.
Successfully installed 'DotNetOpenAuth.AspNet 4.1.3.12303'.
Successfully added 'DotNetOpenAuth.AspNet 4.1.3.12303' to MyMvcProject.
Successfully uninstalled 'DotNetOpenAuth.AspNet 4.0.3.12153'.
Successfully uninstalled 'DotNetOpenAuth.OAuth.Consumer 4.0.3.12153'.
Successfully uninstalled 'DotNetOpenAuth.OAuth.Core 4.0.3.12153'.
Successfully uninstalled 'DotNetOpenAuth.OpenId.RelyingParty 4.0.3.12153'.
Successfully uninstalled 'DotNetOpenAuth.OpenId.Core 4.0.3.12153'.
Successfully uninstalled 'DotNetOpenAuth.Core 4.0.3.12153'.
No updates available for 'DotNetOpenAuth.OAuth.Consumer' in project 'MyMvcProject'.
No updates available for 'DotNetOpenAuth.OAuth.Core' in project 'MyMvcProject'.
No updates available for 'DotNetOpenAuth.OpenId.RelyingParty' in project 'MyMvcProject'.
No updates available for 'DotNetOpenAuth.OpenId.Core' in project 'MyMvcProject'.
No updates available for 'DotNetOpenAuth.Core' in project 'MyMvcProject'.
PM> 

De esta forma, acabamos de ahorrarnos un buen rato buscando e instalando actualizaciones manualmente sobre el proyecto 🙂

La instrucción anterior realiza la actualización sobre una solución completa, pero podemos hilar un poco más fino. El siguiente comando restringe la instalación de actualizaciones al proyecto cuyo nombre especificamos como parámetro:

PM> update-package -ProjectName ProjectToUpdate

También podemos actuar de forma algo más prudente. Por defecto, Nuget instalará las versiones más recientes de todos los paquetes usados en el proyecto o solución, pero a veces, esto podría introducir errores en la aplicación, sobre todo si el salto de versiones es demasiado grande.

Por ello, podemos indicar que las actualizaciones se realicen en “modo seguro” añadiendo el switch -safe al comando, como se observa en el siguiente ejemplo:

PM> update-package -ProjectName AnotherProject –Safe

De esta forma conseguiremos que las actualizaciones no se realicen a la última versión disponible, sino a la última build dentro de la misma versión usada del componente. Es decir, una biblioteca que use un código de versionado del tipo major.minor.build.revision, sólo será actualizado hasta la versión major.minor.maxbuild de la misma.

Por ejemplo, si en un proyecto usamos un componente versión 1.0.1 y en el feed de Nuget existen las versiones 1.0.4, 1.1, y 2.0 de este componente, tras llamar a update-package a secas, este componente será actualizado a la versión 2.0. En cambio, si usamos –safe , se actualizará a la 1.0.4.

En definitiva, una característica de lo más útil y que espero que os ahorre bastante tiempo a los que aún no la conocíais.

Publicado en: Variable not found.