Servicios REST con .NET Core
  • Servicios REST con ASP.NET Core y Entity Framework Core
  • 1. Introducción
    • 1.1 Instalación Visual Studio Community
    • 1.2 Instalación de SQL Server en Mac
    • 1.3 Extensión Intellicode
    • 1.4 Aplicación de ejemplo
  • 2. Explicación de Conceptos
    • 2.1 Servicios REST
      • 2.1.1 OData
      • 2.1.2 GraphQL
    • 2.2 Entity Framework para versiones de tu base de datos
    • 2.3 Paquetes Nuget
    • 2.4 Archivo de recursos
    • 2.5 Estructura de los Proyectos .Net Core
    • 2.6 Código Limpio
    • 2.7 Programación asíncrona
    • 2.8 Git
    • 2.9 ¿Qué es Scrum?
      • 2.9.1 Personas
      • 2.9.2 Roles Scrum
      • 2.9.3 Backlog
      • 2.9.4 Reuniones del Scrum
  • 3. Control de código fuente y Scrum con Azure DevOps
    • 3.1 Introducción a Azure DevOps
      • 3.1.1 Crear un nuevo Proyecto en Azure DevOps
      • 3.1.2 Agregando personas al equipo de trabajo
      • 3.1.3 Agregando los sprints y la capacidad de trabajo
      • 3.1.4 Crear el Backlog y asignar User Stories al Sprint
      • 3.1.5 Crear Prototipos
      • 3.1.6 Conectar a Azure DevOps desde Visual Studio
        • 3.1.6.1 Crear tu proyecto con Visual Studio Community y sincronizarlo a Azure DevOps
      • 3.1.7 Consultar tus tareas pendientes
        • 3.1.7.1 Tareas y Dashboards con Azure DevOps
        • 3.1.7.2 Consultar tus tareas desde Visual Studio Community
      • 3.1.8 Trabajando con Ramas (Branches)
        • 3.1.8.1 Crear la rama desarrollo desde Azure DevOps
          • 3.1.8.1 Crear una rama(branch) desde tu tarea en Azure DevOps
        • 3.1.8.2 Como trabajar con ramas (branches) desde Visual Studio Community
        • 3.1.8.3 Crear el Pull Request con Azure DevOps
      • 3.1.9 Retrospectiva del Sprint
      • 3.1.10 Agregando una Wiki
    • 3.2 Integrando tu código fuente a GitHub
      • 3.2.1 Trabajando con ramas en GitHub
      • 3.2.2 Sincronizar los cambios del código con GitHub y Visual Studio
      • 3.3 Trabajando con Branches (Ramas) con Visual Studio
        • 3.3.1 Branches con Visual Studio
        • 3.3.2 Creando un template para tus PR (Pull Request)
        • 3.3.3 Protegiendo tu branch
  • 4. Creando tu primer servicio
    • 4.1 Crear las base de datos y los usuarios en MySQL
    • 4.2 Crear la tabla Categoría y sus validaciones
    • 4.3 Creando el servicio Categorias
    • 4.4 Probando tus servicios con POSTMAN
    • 4.5 Documentar y Probar tus servicios con Swagger
      • 4.5.1 Configurar Swagger
      • 4.5.2 Comentarios XML
      • 4.5.3 Generando la página de documentación
    • 4.6 Agregando índices
    • 4.7 Mejorando tu código
      • 4.7.1 Creando Objetos de Accesos a Datos
      • 4.7.2 Creando tus mensajes de error en diferentes idiomas
      • 4.7.3 Cambiando el formato del Json de los servicios
  • 5. Agregando el servicio para los productos
    • 5.1 Crear la tabla de Productos
    • 5.2 Formas de cargar información de tablas relacionadas
    • 5.3 Crear llaves fóraneas e índices
    • 5.4 Creando el servicio Productos
    • 5.5 Validar Reglas Mejorando tu código
      • 5.5.1 Agregando una excepción a todos nuestros servicios
      • 5.5.2 Agregando clases genéricas para validar y/o consultar información
      • 5.5.3 Alternativa para validar reglas con ef core
  • 6. Cambiar de base de datos a SQL Server
    • 6.1 Cambiar la base de datos a SQL Server
    • 6.2 Cambiar a SQL Server en Azure
  • 7. Crear servicios con OData
    • 7.1.1 Creando el modelo Clientes
    • 7.1.2 Creando el modelo ClienteCategoría
    • 7.1.3 Agregando paquete Nuget para OData
    • 7.1.4 Configurar el EDM Model
    • 7.1.5 Configurar el servicio OData y llaves foráneas
    • 7.1.6 Creando el Controller para clientes
    • 7.1.7 Configurar y probar los servicios con OData
    • 7.1.8 Práctica Crear el servicio para ClientesCategorias
    • 7.1.9 Recomendaciones de seguridad y rendimiento a tomar en cuenta con OData
  • 8. GraphQL
    • 8.1.1 Creando la tabla Caducidad
    • 8.1.2 Creando el query
    • 8.1.3 Configurando y probando graphQL
    • 8.1.4 Creando la Mutation
    • 8.1.5 Probando nuestros servicios con Postman
  • 9. Seguridad
    • 9.1 Json Web Tokens
    • 9.2 Seguridad basada en roles y usuarios
      • 9.2.1 Creando nuestra tabla roles e insertando los roles principales
      • 9.2.2 Consideraciones de seguridad para almacenar tus passwords
      • 9.2.3 Creando las tablas para manejar la seguridad
      • 9.2.4 Agregando usuarios y roles
    • 9.3 Agregando seguridad a nuestros servicios
    • 9.4 Creando nuestro servicio de login y generar el token
    • 9.5 ¿Cómo agregar seguridad basada en roles a los Servicios REST?
      • 9.5.1 Seguridad basada en claims
      • 9.5.2 Creando las tablas para validar permisos por cada tabla
      • 9.5.3 Seguridad basada en directivas
      • 9.5.4 Seguridad con Action Filters
    • 9.6 Guardando el historial de cambios
    • 9.7 Refrescando tu token
    • 9.8 Seguridad Mejorando tu código
      • 9.8.1 ¿Cómo limitar el número de intentos incorrectos en el login?
      • 9.8.2 ¿Cómo obtener la ciudad del usuario por medio de la IP?
      • 9.8.3 Habilitando CORS
  • 10. Pruebas Unitarias
    • 10.1 Agregando el proyecto de pruebas unitarias
    • 10.2 Crear una prueba unitaria
      • 10.2.1 Ejecutando las pruebas unitarias
    • 10.3 Agregando una base de datos en memoria para nuestras pruebas unitarias
    • 10.4 Agregando la referencia de nuestro proyecto CaducaRest
      • 10.4.1 Agregando paquetes nuget necesarios
    • 10.5 Configurando Clases para Objetos Sustitutos
      • 10.5.1 Configurando el Contexto para utilizar la base de datos en Memoria
      • 10.5.2 Configurando el objeto para sustituir mensajes de Error por idioma
    • 10.6 Agregando pruebas para las Categorías
  • 11. Integración continua
    • 11.1 ¿Qué es la integración continua?
    • 11.2 Subir tu código fuente a BitBucket
      • 11.2.1 Integración continua y pruebas automáticas con Bitbucket
    • 11.3 Integración continua y pruebas automáticas en Azure DevOps
  • 12. Pruebas de integración
    • 12.1 ¿Qué es SpecFlow?
    • 12.2 Agregando el proyecto de pruebas de integración
    • 12.3 Configurando Specflow
    • 12.4 Creando pruebas para el login
    • 12.5 Agregando las pruebas de Integración a Azure Devops
    • 12.6 Specflow Mejorando tu código
      • 12.6.1 Cambiando las pruebas a español
      • 12.6.2 Pasando tablas a nuestras pruebas
      • 12.6.3 Agregar los passwords como variables de ambiente
      • 12.6.4 Probando con SQLite
      • 12.6.5 Agregando diferentes parámetros con MSTest
      • 12.6.6 Generando el reporte living doc de specflow
  • 13. Integración continua con Postman
    • 13.1 Recomendaciones para probar tus servicios
    • 13.2 Instrucciones básicas para probar con Postman
    • 13.3 Crear colecciones en Postman
    • 13.4 Agregar pruebas a tus servicios
    • 13.5 Crear environments
    • 13.6 Agregando datos de prueba con archivos .csv
    • 13.7 Exportando tus colecciones y ejecutarlas con Newman.
    • 13.8 Agregando las colecciones de postman al pipeline
  • 14. Pruebas de usuario
    • 14.1 Page Object Model
    • 14.2 ¿Qué es Selenium?
      • 14.2.1 Selenium Instrucciones básicas
      • 14.2.2 Agregando el proyecto de pruebas de usuario
    • 14.3 ¿Qué es Cypress?
      • 14.3.1 Cypress Instrucciones básicas
    • 14.4 ¿Qué es Playwright?
      • 14.4.1 Playwright Instrucciones básicas
  • 15. Despliegue Continuo con Azure DevOps y Azure
    • 15.1 Crear un App Service en Azure
    • 15.2 Generando Artifacts en Azure Pipelines
    • 15.3 Generando el Release en Azure Pipelines al App Service de Azure
    • 15.4 Ejecutando las colecciones de Postman después del release
    • 15.5 Agregando las pruebas de usuario en Azure Pipelines
  • 16. Instalación en Windows Server e IIS
    • 16.1 Instalar IIS en Windows Server
    • 16.2 Instalación del ASP.NET Core Module/Hosting Bundle
    • 16.3 Crea el Sitio Web en IIS
  • 17. Instalación en Linux
    • 17.1 Creando una máquina virtual linux en Azure
    • 17.2 Habilitando el acceso remoto
    • 17.3 Configura linux para .Net Core
    • 17.4 Instalando mysql
    • 17.5 Instalando Nginx y configurando tu servicio
    • 17.6 Instalando un certificado SSL gratuito con CertBot
    • 17.7 Agregando diferentes subdominios
  • 18. Docker
Powered by GitBook
On this page
  • Comentando el Modelo
  • Comentando los servicios

Was this helpful?

  1. 4. Creando tu primer servicio
  2. 4.5 Documentar y Probar tus servicios con Swagger

4.5.2 Comentarios XML

Previous4.5.1 Configurar SwaggerNext4.5.3 Generando la página de documentación

Last updated 2 years ago

Was this helpful?

Los comentarios XML se agregan arriba de funciones o propiedades de una clase para proporcionar la explicación de la función y sus parámetros. Cuando compilas tu aplicación todos los comentarios se guardan en un archivo XML.

Los comentarios XML utilizan 3 diagonales /// seguido de una etiqueta que indica el tipo de comentario.

Los tipos de etiquetas más comunes son:

Etiqueta

Descripción

<summary>

Aquí describimos brevemente la clase o servicio.

<remarks>

Aquí puedes describir las reglas de negocio o información importante para utilizar la clase o función

<returns>

Indicas lo que regresa la función. Por ejemplo para el método GET/Categorías indicas que regresa la lista de todas las categorías

<param name="nombre">

Describes para que es necesario el parámetro. Donde a es el nombre del parámetro que estas describiendo

<para>

Dentro de la etiqueta <remarks> o <summary> te permite separar el texto en párrafos

<value>

Indica que es lo que contiene una propiedad pública de una clase

<example>

Puedes escribir ejemplos de cómo se utiliza la función.

<code>

Aquí podemos incluir código de ejemplo

Puedes ver la documentación oficial y ejemplos aquí

Comentando el Modelo

Primero vamos a agregar comentarios al modelo.

  1. Abre el archivo Categoria de la carpeta Models

  2. Arriba del nombre de la clase agregamos /// automáticamente te agrega la etiqueta <summary>. Dentro de la etiqueta <summary> escribimos lo siguiente: Permite registrar las categorías de los productos que vende la empresa

Categoria.cs
 /// <summary>
 /// Permite registrar las categorías de los productos
 /// que vende la empresa
 /// </summary>
 public class Categoria
 {

3. Comentamos cada propiedad del modelo. Tecleando /// arriba de cada atributo. Ejemplo:

Categoria.cs
 /// <summary>
 /// Id de la categoria
 /// </summary>
 /// <value>El Id se incrementa automáticamente</value>
 [Key]
 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
 public int Id { get; set; }

/// <summary>
/// Obtiene o establece la clave de la categoría
/// </summary>
/// <value>La clave de la categoria</value>
[Required(ErrorMessage = "Por favor teclea el campo Clave")]
[Range(1,999)]
public int Clave { get; set; }

/// <summary>
/// Obtiene o establece el nombre de la categoría
/// </summary>
/// <value>El nombre de la categoría</value>
[Required(ErrorMessage = "Por favor teclea el campo Nombre")]
[Column(TypeName = "VARCHAR(80)")]
public string Nombre { get; set; }

Comentando los servicios

Documentamos los servicios de la misma manera.

  1. Dentro de la carpeta Controllers abrimos el archivo CategoriasController.cs

  2. Arriba del nombre de la clase y de [Route("api/[controller]")] tecleamos /// y dentro de <summary> tecleamos Servicios para guardar, modificar o borrar las categorías de los productos

/// <summary>
/// Servicios para guardar, modificar o borrar las categorías
/// de los productos
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class CategoriasController : ControllerBase

3. Arriba de cada método tecleamos igual /// y comentamos el summary, los parámetros y en return especificamos que es lo que regresa el servicio de los servicios que cuentan con parámetros. Ejemplo:

CategoriasController.cs
/// <summary>
/// Obtiene todas las categorías registradas
/// </summary>
/// <returns>Todas las categorías</returns>
// GET: api/Categorias
[HttpGet]
public IEnumerable<Categoria> GetCategoria()

Como el método obtener por Id regresa un action result si queremos documentar el objeto Categoría podemos agregar [ProducesResponseType(200, Type = typeof(Categoria))]

CategoriasController.cs
/// <summary>
/// Obtiene una categoría de acuerdo a su Id
/// </summary>
/// <returns>Los datos de la categoría</returns>
/// <param name="id">Id de la categoría</param>
// GET: api/Categorias/5
[HttpGet("{id}")]
[ProducesResponseType(200, Type = typeof(Categoria))]
public async Task<IActionResult> GetCategoria([FromRoute] int id)
CategoriasController.cs
/// <summary>
/// Modifica una categoría
/// </summary>
/// <returns>No Content si se modifico correctamente</returns>
/// <param name="id">Id de la categoría a Modificar</param>
/// <param name="categoria">Datos de la Categoria.</param>
// PUT: api/Categorias/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCategoria([FromRoute] int id, 
                                     [FromBody] Categoria categoria)
CategoriasController.cs
/// <summary>
/// Permite registrar una nueva categoría de productos
/// </summary>
/// <returns>Los datos de la categoría agregada</returns>
/// <param name="categoria">Datos de la categoría</param>
// POST: api/Categorias
[HttpPost]
public async Task<IActionResult> PostCategoria(
                                      [FromBody] Categoria categoria)
CategoriasController.cs
/// <summary>
/// Permite borrar una categoría
/// </summary>
/// <returns>Los datos de la categoría eliminada</returns>
/// <param name="id">Id de la categoría a borrar</param>
// DELETE: api/Categorias/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCategoria([FromRoute] int id)

Aqui esta el código final

CategoriasController.cs
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using CaducaRest.Models;
using CaducaRest.DAO;

namespace CaducaRest.Controllers
{
    /// <summary>
    /// Servicios para guardar, modificar o borrar las categorías de los productos
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    public class CategoriasController : ControllerBase
    {
        private readonly CaducaContext _context;
        private CategoriaDAO categoriaDAO;

        public CategoriasController(CaducaContext context)
        {
            _context = context;
            categoriaDAO = new CategoriaDAO(_context);
        }

        /// <summary>
        /// Obtiene todas las categorías registradas
        /// </summary>
        /// <returns>Todas las categorías</returns>
        // GET: api/Categorias
        [HttpGet]
        public async Task<IEnumerable<Categoria>> GetCategoriaAsync()
        {           
            return await categoriaDAO.ObtenerTodoAsync();
        }

        /// <summary>
        /// Obtiene una categoría de acuerdo a su Id
        /// </summary>
        /// <returns>Los datos de la categoría</returns>
        /// <param name="id">Id de la categoría</param>
        // GET: api/Categorias/5
        [HttpGet("{id}")]
        public async Task<IActionResult> GetCategoria([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var categoria = await categoriaDAO.ObtenerPorIdAsync(id);

            if (categoria == null)
            {
                return NotFound();
            }

            return Ok(categoria);
        }

        /// <summary>
        /// Modifica una categoría
        /// </summary>
        /// <returns>No Content si se modifico correctamente</returns>
        /// <param name="id">Id de la categoría a Modificar</param>
        /// <param name="categoria">Datos de la Categoria.</param>
        // PUT: api/Categorias/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutCategoria([FromRoute] int id, [FromBody] Categoria categoria)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (id != categoria.Id)
            {
                return BadRequest();
            }

            _context.Entry(categoria).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!CategoriaExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        /// <summary>
        /// Permite registrar una nueva categoría de productos
        /// </summary>
        /// <returns>Los datos de la categoría agregada</returns>
        /// <param name="categoria">Datos de la categoría</param>
        // POST: api/Categorias
        [HttpPost]
        public async Task<IActionResult> PostCategoria([FromBody] Categoria categoria)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            _context.Categoria.Add(categoria);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetCategoria", new { id = categoria.Id }, categoria);
        }

        /// <summary>
        /// Permite borrar una categoría
        /// </summary>
        /// <returns>Los datos de la categoría eliminada</returns>
        /// <param name="id">Id de la categoría a borrar</param>
        // DELETE: api/Categorias/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteCategoria([FromRoute] int id)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var categoria = await _context.Categoria.FindAsync(id);
            if (categoria == null)
            {
                return NotFound();
            }

            _context.Categoria.Remove(categoria);
            await _context.SaveChangesAsync();

            return Ok(categoria);
        }

        private bool CategoriaExists(int id)
        {
            return _context.Categoria.Any(e => e.Id == id);
        }
    }
}
LogoEtiquetas de documentación XML recomendadas para una clase y sus miembrosdocsmsft