# 4.5.2 Comentarios XML

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.

&#x20;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í

{% embed url="<https://docs.microsoft.com/es-es/dotnet/csharp/codedoc>" %}

### Comentando el Modelo

Primero vamos a agregar comentarios al modelo.&#x20;

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**

{% code title="Categoria.cs" %}

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

{% endcode %}

&#x20; 3\. Comentamos cada propiedad del modelo. Tecleando /// arriba de cada atributo.  Ejemplo:

{% code title="Categoria.cs" %}

```csharp
 /// <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; }
```

{% endcode %}

### 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**

```csharp
/// <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:

{% code title="CategoriasController.cs" %}

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

{% endcode %}

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))]**

{% code title="CategoriasController.cs" %}

```csharp
/// <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)
```

{% endcode %}

{% code title="CategoriasController.cs" %}

```csharp
/// <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)
```

{% endcode %}

{% code title="CategoriasController.cs" %}

```csharp
/// <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)

```

{% endcode %}

{% code title="CategoriasController.cs" %}

```csharp
/// <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)
```

{% endcode %}

Aqui esta el código final

{% code title="CategoriasController.cs" %}

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

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://abi.gitbook.io/net-core/4.-creando-tu-primer-servicio/4.5-documentar-y-probar-tus-servicios-con-swagger/4.5.2-comentarios-xml.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
