Tutorial: Llamada a una API web de ASP.NET Core con JavaScript

Por Rick Anderson

En este tutorial se muestra cómo llamar a una API web de ASP.NET Core con JavaScript mediante la API Fetch.

Requisitos previos

Llamar a la API web con JavaScript

En esta sección, agregará una página HTML que contiene formularios para crear y administrar las tareas pendientes. Los controladores de eventos se asocian a los elementos de la página. Los controladores de eventos producen solicitudes HTTP a los métodos de acción de la API web. La función fetch de la API Fetch inicia cada solicitud HTTP.

La función fetch devuelve un objeto Promise, que contiene una respuesta HTTP representada como un objeto Response. Un patrón común es extraer el cuerpo de la respuesta ResponseON invocando la función JS en el json objeto. JavaScript actualiza la página con los detalles de la respuesta de la API web.

La llamada fetch más simple acepta un único parámetro que representa la ruta. Un segundo parámetro, conocido como el objeto init, es opcional. init se utiliza para configurar la solicitud HTTP.

  1. Configure la aplicación para atender archivos estáticos y habilitar la asignación de archivos predeterminada. El siguiente código resaltado es necesario en Program.cs:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));

var app = builder.Build();

if (builder.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
  1. Cree una carpeta wwwroot en la raíz del proyecto.

  2. Cree una carpeta css dentro de la carpeta wwwroot.

  3. Cree una carpeta js dentro de la carpeta wwwroot.

  4. Agregue un archivo HTML denominado index.html a la carpeta wwwroot. Reemplace el contenido de index.html por el marcado siguiente:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>To-do CRUD</title>
        <link rel="stylesheet" href="css/site.css" />
    </head>
    <body>
        <h1>To-do CRUD</h1>
        <h3>Add</h3>
        <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
            <input type="text" id="add-name" placeholder="New to-do">
            <input type="submit" value="Add">
        </form>
    
        <div id="editForm">
            <h3>Edit</h3>
            <form action="javascript:void(0);" onsubmit="updateItem()">
                <input type="hidden" id="edit-id">
                <input type="checkbox" id="edit-isComplete">
                <input type="text" id="edit-name">
                <input type="submit" value="Save">
                <a onclick="closeInput()" aria-label="Close">&#10006;</a>
            </form>
        </div>
    
        <p id="counter"></p>
    
        <table>
            <tr>
                <th>Is Complete?</th>
                <th>Name</th>
                <th></th>
                <th></th>
            </tr>
            <tbody id="todos"></tbody>
        </table>
    
        <script src="js/site.js" asp-append-version="true"></script>
        <script type="text/javascript">
            getItems();
        </script>
    </body>
    </html>
    
  5. Agregue un archivo CSS denominado site.css a la carpeta wwwroot/css. Reemplace el contenido de site.css por los estilos siguientes:

    input[type='submit'], button, [aria-label] {
        cursor: pointer;
    }
    
    #editForm {
        display: none;
    }
    
    table {
        font-family: Arial, sans-serif;
        border: 1px solid;
        border-collapse: collapse;
    }
    
    th {
        background-color: #f8f8f8;
        padding: 5px;
    }
    
    td {
        border: 1px solid;
        padding: 5px;
    }
    
  6. Agregue un archivo de JavaScript denominado site.js, a la carpeta wwwroot/js. Reemplace el contenido de site.js por el código siguiente:

    const uri = 'api/todoitems';
    let todos = [];
    
    function getItems() {
      fetch(uri)
        .then(response => response.json())
        .then(data => _displayItems(data))
        .catch(error => console.error('Unable to get items.', error));
    }
    
    function addItem() {
      const addNameTextbox = document.getElementById('add-name');
    
      const item = {
        isComplete: false,
        name: addNameTextbox.value.trim()
      };
    
      fetch(uri, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
        .then(response => response.json())
        .then(() => {
          getItems();
          addNameTextbox.value = '';
        })
        .catch(error => console.error('Unable to add item.', error));
    }
    
    function deleteItem(id) {
      fetch(`${uri}/${id}`, {
        method: 'DELETE'
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to delete item.', error));
    }
    
    function displayEditForm(id) {
      const item = todos.find(item => item.id === id);
      
      document.getElementById('edit-name').value = item.name;
      document.getElementById('edit-id').value = item.id;
      document.getElementById('edit-isComplete').checked = item.isComplete;
      document.getElementById('editForm').style.display = 'block';
    }
    
    function updateItem() {
      const itemId = document.getElementById('edit-id').value;
      const item = {
        id: parseInt(itemId, 10),
        isComplete: document.getElementById('edit-isComplete').checked,
        name: document.getElementById('edit-name').value.trim()
      };
    
      fetch(`${uri}/${itemId}`, {
        method: 'PUT',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to update item.', error));
    
      closeInput();
    
      return false;
    }
    
    function closeInput() {
      document.getElementById('editForm').style.display = 'none';
    }
    
    function _displayCount(itemCount) {
      const name = (itemCount === 1) ? 'to-do' : 'to-dos';
    
      document.getElementById('counter').innerText = `${itemCount} ${name}`;
    }
    
    function _displayItems(data) {
      const tBody = document.getElementById('todos');
      tBody.innerHTML = '';
    
      _displayCount(data.length);
    
      const button = document.createElement('button');
    
      data.forEach(item => {
        let isCompleteCheckbox = document.createElement('input');
        isCompleteCheckbox.type = 'checkbox';
        isCompleteCheckbox.disabled = true;
        isCompleteCheckbox.checked = item.isComplete;
    
        let editButton = button.cloneNode(false);
        editButton.innerText = 'Edit';
        editButton.setAttribute('onclick', `displayEditForm(${item.id})`);
    
        let deleteButton = button.cloneNode(false);
        deleteButton.innerText = 'Delete';
        deleteButton.setAttribute('onclick', `deleteItem(${item.id})`);
    
        let tr = tBody.insertRow();
        
        let td1 = tr.insertCell(0);
        td1.appendChild(isCompleteCheckbox);
    
        let td2 = tr.insertCell(1);
        let textNode = document.createTextNode(item.name);
        td2.appendChild(textNode);
    
        let td3 = tr.insertCell(2);
        td3.appendChild(editButton);
    
        let td4 = tr.insertCell(3);
        td4.appendChild(deleteButton);
      });
    
      todos = data;
    }
    

Puede que sea necesario realizar un cambio en la configuración de inicio del proyecto de ASP.NET Core para probar la página HTML localmente:

  1. Abra Properties\launchSettings.json.
  2. Quite la propiedad launchUrl para forzar la aplicación a abrirse en index.html, es decir, el archivo predeterminado del proyecto.

En este ejemplo se llama a todos los métodos CRUD de la API web. A continuación, encontrará algunas explicaciones de las solicitudes de la API web.

Obtención de una lista de tareas pendientes

En el código siguiente, se envía una solicitud HTTP GET a la ruta api/todoitems:

fetch(uri)
  .then(response => response.json())
  .then(data => _displayItems(data))
  .catch(error => console.error('Unable to get items.', error));

Cuando la API web devuelve un código de estado correcto, se invoca la función _displayItems. Cada tarea pendiente en el parámetro de matriz aceptado por _displayItems se agrega a una tabla con los botones Editar y Eliminar. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Incorporación de una tarea pendiente

En el código siguiente:

  • Se declara una variable item para construir una representación literal de objeto de la tarea pendiente.
  • Una solicitud Fetch se configura con las siguientes opciones:
    • method: especifica el verbo de acción HTTP POST.
    • body: especifica la representación JSON del cuerpo de la solicitud. El JSON se genera pasando el literal de objeto almacenado en item a la función JSON.stringify.
    • headers: especifica los encabezados de solicitud HTTP Accept y Content-Type. Ambos encabezados se establecen en application/json para especificar el tipo de medio que se va a recibir y a enviar, respectivamente.
  • Se envía una solicitud HTTP POST a la ruta api/todoitems.
function addItem() {
  const addNameTextbox = document.getElementById('add-name');

  const item = {
    isComplete: false,
    name: addNameTextbox.value.trim()
  };

  fetch(uri, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(item)
  })
    .then(response => response.json())
    .then(() => {
      getItems();
      addNameTextbox.value = '';
    })
    .catch(error => console.error('Unable to add item.', error));
}

Cuando la API web devuelve un código de estado correcto, se invoca la función getItems para actualizar la tabla HTML. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Actualizar una tarea pendiente

Actualizar una tarea pendientes es similar a agregar una; sin embargo, hay dos diferencias importantes:

  • La ruta tiene como sufijo el identificador único del elemento que se va a actualizar. Por ejemplo, api/todoitems/1.
  • El verbo de acción HTTP es PUT, como se indica mediante la opción method.
fetch(`${uri}/${itemId}`, {
  method: 'PUT',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(item)
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));

Eliminar una tarea pendiente

Para eliminar una tarea pendiente, establezca la opción method de la solicitud en DELETE y especifique el identificador único de la tarea en la dirección URL.

fetch(`${uri}/${id}`, {
  method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));

Pase al siguiente tutorial para obtener información sobre cómo generar páginas de ayuda de API web:

En este tutorial se muestra cómo llamar a una API web de ASP.NET Core con JavaScript mediante la API Fetch.

Requisitos previos

Llamar a la API web con JavaScript

En esta sección, agregará una página HTML que contiene formularios para crear y administrar las tareas pendientes. Los controladores de eventos se asocian a los elementos de la página. Los controladores de eventos producen solicitudes HTTP a los métodos de acción de la API web. La función fetch de la API Fetch inicia cada solicitud HTTP.

La función fetch devuelve un objeto Promise, que contiene una respuesta HTTP representada como un objeto Response. Un patrón común es extraer el cuerpo de la respuesta ResponseON invocando la función JS en el json objeto. JavaScript actualiza la página con los detalles de la respuesta de la API web.

La llamada fetch más simple acepta un único parámetro que representa la ruta. Un segundo parámetro, conocido como el objeto init, es opcional. init se utiliza para configurar la solicitud HTTP.

  1. Configure la aplicación para atender archivos estáticos y habilitar la asignación de archivos predeterminada. El siguiente código resaltado es necesario en el método Configure de Startup.cs:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
    
        app.UseDefaultFiles();
        app.UseStaticFiles();
    
        app.UseHttpsRedirection();
    
        app.UseRouting();
    
        app.UseAuthorization();
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
    
  2. Cree una carpeta wwwroot en la raíz del proyecto.

  3. Cree una carpeta css dentro de la carpeta wwwroot.

  4. Cree una carpeta js dentro de la carpeta wwwroot.

  5. Agregue un archivo HTML denominado index.html a la carpeta wwwroot. Reemplace el contenido de index.html por el marcado siguiente:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>To-do CRUD</title>
        <link rel="stylesheet" href="css/site.css" />
    </head>
    <body>
        <h1>To-do CRUD</h1>
        <h3>Add</h3>
        <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
            <input type="text" id="add-name" placeholder="New to-do">
            <input type="submit" value="Add">
        </form>
    
        <div id="editForm">
            <h3>Edit</h3>
            <form action="javascript:void(0);" onsubmit="updateItem()">
                <input type="hidden" id="edit-id">
                <input type="checkbox" id="edit-isComplete">
                <input type="text" id="edit-name">
                <input type="submit" value="Save">
                <a onclick="closeInput()" aria-label="Close">&#10006;</a>
            </form>
        </div>
    
        <p id="counter"></p>
    
        <table>
            <tr>
                <th>Is Complete?</th>
                <th>Name</th>
                <th></th>
                <th></th>
            </tr>
            <tbody id="todos"></tbody>
        </table>
    
        <script src="js/site.js" asp-append-version="true"></script>
        <script type="text/javascript">
            getItems();
        </script>
    </body>
    </html>
    
  6. Agregue un archivo CSS denominado site.css a la carpeta wwwroot/css. Reemplace el contenido de site.css por los estilos siguientes:

    input[type='submit'], button, [aria-label] {
        cursor: pointer;
    }
    
    #editForm {
        display: none;
    }
    
    table {
        font-family: Arial, sans-serif;
        border: 1px solid;
        border-collapse: collapse;
    }
    
    th {
        background-color: #f8f8f8;
        padding: 5px;
    }
    
    td {
        border: 1px solid;
        padding: 5px;
    }
    
  7. Agregue un archivo de JavaScript denominado site.js, a la carpeta wwwroot/js. Reemplace el contenido de site.js por el código siguiente:

    const uri = 'api/todoitems';
    let todos = [];
    
    function getItems() {
      fetch(uri)
        .then(response => response.json())
        .then(data => _displayItems(data))
        .catch(error => console.error('Unable to get items.', error));
    }
    
    function addItem() {
      const addNameTextbox = document.getElementById('add-name');
    
      const item = {
        isComplete: false,
        name: addNameTextbox.value.trim()
      };
    
      fetch(uri, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
        .then(response => response.json())
        .then(() => {
          getItems();
          addNameTextbox.value = '';
        })
        .catch(error => console.error('Unable to add item.', error));
    }
    
    function deleteItem(id) {
      fetch(`${uri}/${id}`, {
        method: 'DELETE'
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to delete item.', error));
    }
    
    function displayEditForm(id) {
      const item = todos.find(item => item.id === id);
      
      document.getElementById('edit-name').value = item.name;
      document.getElementById('edit-id').value = item.id;
      document.getElementById('edit-isComplete').checked = item.isComplete;
      document.getElementById('editForm').style.display = 'block';
    }
    
    function updateItem() {
      const itemId = document.getElementById('edit-id').value;
      const item = {
        id: parseInt(itemId, 10),
        isComplete: document.getElementById('edit-isComplete').checked,
        name: document.getElementById('edit-name').value.trim()
      };
    
      fetch(`${uri}/${itemId}`, {
        method: 'PUT',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to update item.', error));
    
      closeInput();
    
      return false;
    }
    
    function closeInput() {
      document.getElementById('editForm').style.display = 'none';
    }
    
    function _displayCount(itemCount) {
      const name = (itemCount === 1) ? 'to-do' : 'to-dos';
    
      document.getElementById('counter').innerText = `${itemCount} ${name}`;
    }
    
    function _displayItems(data) {
      const tBody = document.getElementById('todos');
      tBody.innerHTML = '';
    
      _displayCount(data.length);
    
      const button = document.createElement('button');
    
      data.forEach(item => {
        let isCompleteCheckbox = document.createElement('input');
        isCompleteCheckbox.type = 'checkbox';
        isCompleteCheckbox.disabled = true;
        isCompleteCheckbox.checked = item.isComplete;
    
        let editButton = button.cloneNode(false);
        editButton.innerText = 'Edit';
        editButton.setAttribute('onclick', `displayEditForm(${item.id})`);
    
        let deleteButton = button.cloneNode(false);
        deleteButton.innerText = 'Delete';
        deleteButton.setAttribute('onclick', `deleteItem(${item.id})`);
    
        let tr = tBody.insertRow();
        
        let td1 = tr.insertCell(0);
        td1.appendChild(isCompleteCheckbox);
    
        let td2 = tr.insertCell(1);
        let textNode = document.createTextNode(item.name);
        td2.appendChild(textNode);
    
        let td3 = tr.insertCell(2);
        td3.appendChild(editButton);
    
        let td4 = tr.insertCell(3);
        td4.appendChild(deleteButton);
      });
    
      todos = data;
    }
    

Puede que sea necesario realizar un cambio en la configuración de inicio del proyecto de ASP.NET Core para probar la página HTML localmente:

  1. Abra Properties\launchSettings.json.
  2. Quite la propiedad launchUrl para forzar la aplicación a abrirse en index.html, es decir, el archivo predeterminado del proyecto.

En este ejemplo se llama a todos los métodos CRUD de la API web. A continuación, encontrará algunas explicaciones de las solicitudes de la API web.

Obtención de una lista de tareas pendientes

En el código siguiente, se envía una solicitud HTTP GET a la ruta api/todoitems:

fetch(uri)
  .then(response => response.json())
  .then(data => _displayItems(data))
  .catch(error => console.error('Unable to get items.', error));

Cuando la API web devuelve un código de estado correcto, se invoca la función _displayItems. Cada tarea pendiente en el parámetro de matriz aceptado por _displayItems se agrega a una tabla con los botones Editar y Eliminar. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Incorporación de una tarea pendiente

En el código siguiente:

  • Se declara una variable item para construir una representación literal de objeto de la tarea pendiente.
  • Una solicitud Fetch se configura con las siguientes opciones:
    • method: especifica el verbo de acción HTTP POST.
    • body: especifica la representación JSON del cuerpo de la solicitud. El JSON se genera pasando el literal de objeto almacenado en item a la función JSON.stringify.
    • headers: especifica los encabezados de solicitud HTTP Accept y Content-Type. Ambos encabezados se establecen en application/json para especificar el tipo de medio que se va a recibir y a enviar, respectivamente.
  • Se envía una solicitud HTTP POST a la ruta api/todoitems.
function addItem() {
  const addNameTextbox = document.getElementById('add-name');

  const item = {
    isComplete: false,
    name: addNameTextbox.value.trim()
  };

  fetch(uri, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(item)
  })
    .then(response => response.json())
    .then(() => {
      getItems();
      addNameTextbox.value = '';
    })
    .catch(error => console.error('Unable to add item.', error));
}

Cuando la API web devuelve un código de estado correcto, se invoca la función getItems para actualizar la tabla HTML. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Actualizar una tarea pendiente

Actualizar una tarea pendientes es similar a agregar una; sin embargo, hay dos diferencias importantes:

  • La ruta tiene como sufijo el identificador único del elemento que se va a actualizar. Por ejemplo, api/todoitems/1.
  • El verbo de acción HTTP es PUT, como se indica mediante la opción method.
fetch(`${uri}/${itemId}`, {
  method: 'PUT',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(item)
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));

Eliminar una tarea pendiente

Para eliminar una tarea pendiente, establezca la opción method de la solicitud en DELETE y especifique el identificador único de la tarea en la dirección URL.

fetch(`${uri}/${id}`, {
  method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));

Pase al siguiente tutorial para obtener información sobre cómo generar páginas de ayuda de API web:

En este tutorial se muestra cómo llamar a una API web de ASP.NET Core con JavaScript mediante la API Fetch.

Requisitos previos

Llamar a la API web con JavaScript

En esta sección, agregará una página HTML que contiene formularios para crear y administrar las tareas pendientes. Los controladores de eventos se asocian a los elementos de la página. Los controladores de eventos producen solicitudes HTTP a los métodos de acción de la API web. La función fetch de la API Fetch inicia cada solicitud HTTP.

La función fetch devuelve un objeto Promise, que contiene una respuesta HTTP representada como un objeto Response. Un patrón común es extraer el cuerpo de la respuesta ResponseON invocando la función JS en el json objeto. JavaScript actualiza la página con los detalles de la respuesta de la API web.

La llamada fetch más simple acepta un único parámetro que representa la ruta. Un segundo parámetro, conocido como el objeto init, es opcional. init se utiliza para configurar la solicitud HTTP.

  1. Configure la aplicación para atender archivos estáticos y habilitar la asignación de archivos predeterminada. El siguiente código resaltado es necesario en Program.cs:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
    opt.UseInMemoryDatabase("TodoList"));

var app = builder.Build();

if (builder.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseDefaultFiles();
app.UseStaticFiles();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
  1. Cree una carpeta wwwroot en la raíz del proyecto.

  2. Cree una carpeta css dentro de la carpeta wwwroot.

  3. Cree una carpeta js dentro de la carpeta wwwroot.

  4. Agregue un archivo HTML denominado index.html a la carpeta wwwroot. Reemplace el contenido de index.html por el marcado siguiente:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>To-do CRUD</title>
        <link rel="stylesheet" href="css/site.css" />
    </head>
    <body>
        <h1>To-do CRUD</h1>
        <h3>Add</h3>
        <form action="javascript:void(0);" method="POST" onsubmit="addItem()">
            <input type="text" id="add-name" placeholder="New to-do">
            <input type="submit" value="Add">
        </form>
    
        <div id="editForm">
            <h3>Edit</h3>
            <form action="javascript:void(0);" onsubmit="updateItem()">
                <input type="hidden" id="edit-id">
                <input type="checkbox" id="edit-isComplete">
                <input type="text" id="edit-name">
                <input type="submit" value="Save">
                <a onclick="closeInput()" aria-label="Close">&#10006;</a>
            </form>
        </div>
    
        <p id="counter"></p>
    
        <table>
            <tr>
                <th>Is Complete?</th>
                <th>Name</th>
                <th></th>
                <th></th>
            </tr>
            <tbody id="todos"></tbody>
        </table>
    
        <script src="js/site.js" asp-append-version="true"></script>
        <script type="text/javascript">
            getItems();
        </script>
    </body>
    </html>
    
  5. Agregue un archivo CSS denominado site.css a la carpeta wwwroot/css. Reemplace el contenido de site.css por los estilos siguientes:

    input[type='submit'], button, [aria-label] {
        cursor: pointer;
    }
    
    #editForm {
        display: none;
    }
    
    table {
        font-family: Arial, sans-serif;
        border: 1px solid;
        border-collapse: collapse;
    }
    
    th {
        background-color: #f8f8f8;
        padding: 5px;
    }
    
    td {
        border: 1px solid;
        padding: 5px;
    }
    
  6. Agregue un archivo de JavaScript denominado site.js, a la carpeta wwwroot/js. Reemplace el contenido de site.js por el código siguiente:

    const uri = 'api/todoitems';
    let todos = [];
    
    function getItems() {
      fetch(uri)
        .then(response => response.json())
        .then(data => _displayItems(data))
        .catch(error => console.error('Unable to get items.', error));
    }
    
    function addItem() {
      const addNameTextbox = document.getElementById('add-name');
    
      const item = {
        isComplete: false,
        name: addNameTextbox.value.trim()
      };
    
      fetch(uri, {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
        .then(response => response.json())
        .then(() => {
          getItems();
          addNameTextbox.value = '';
        })
        .catch(error => console.error('Unable to add item.', error));
    }
    
    function deleteItem(id) {
      fetch(`${uri}/${id}`, {
        method: 'DELETE'
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to delete item.', error));
    }
    
    function displayEditForm(id) {
      const item = todos.find(item => item.id === id);
      
      document.getElementById('edit-name').value = item.name;
      document.getElementById('edit-id').value = item.id;
      document.getElementById('edit-isComplete').checked = item.isComplete;
      document.getElementById('editForm').style.display = 'block';
    }
    
    function updateItem() {
      const itemId = document.getElementById('edit-id').value;
      const item = {
        id: parseInt(itemId, 10),
        isComplete: document.getElementById('edit-isComplete').checked,
        name: document.getElementById('edit-name').value.trim()
      };
    
      fetch(`${uri}/${itemId}`, {
        method: 'PUT',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(item)
      })
      .then(() => getItems())
      .catch(error => console.error('Unable to update item.', error));
    
      closeInput();
    
      return false;
    }
    
    function closeInput() {
      document.getElementById('editForm').style.display = 'none';
    }
    
    function _displayCount(itemCount) {
      const name = (itemCount === 1) ? 'to-do' : 'to-dos';
    
      document.getElementById('counter').innerText = `${itemCount} ${name}`;
    }
    
    function _displayItems(data) {
      const tBody = document.getElementById('todos');
      tBody.innerHTML = '';
    
      _displayCount(data.length);
    
      const button = document.createElement('button');
    
      data.forEach(item => {
        let isCompleteCheckbox = document.createElement('input');
        isCompleteCheckbox.type = 'checkbox';
        isCompleteCheckbox.disabled = true;
        isCompleteCheckbox.checked = item.isComplete;
    
        let editButton = button.cloneNode(false);
        editButton.innerText = 'Edit';
        editButton.setAttribute('onclick', `displayEditForm(${item.id})`);
    
        let deleteButton = button.cloneNode(false);
        deleteButton.innerText = 'Delete';
        deleteButton.setAttribute('onclick', `deleteItem(${item.id})`);
    
        let tr = tBody.insertRow();
        
        let td1 = tr.insertCell(0);
        td1.appendChild(isCompleteCheckbox);
    
        let td2 = tr.insertCell(1);
        let textNode = document.createTextNode(item.name);
        td2.appendChild(textNode);
    
        let td3 = tr.insertCell(2);
        td3.appendChild(editButton);
    
        let td4 = tr.insertCell(3);
        td4.appendChild(deleteButton);
      });
    
      todos = data;
    }
    

Puede que sea necesario realizar un cambio en la configuración de inicio del proyecto de ASP.NET Core para probar la página HTML localmente:

  1. Abra Properties\launchSettings.json.
  2. Quite la propiedad launchUrl para forzar la aplicación a abrirse en index.html, es decir, el archivo predeterminado del proyecto.

En este ejemplo se llama a todos los métodos CRUD de la API web. A continuación, encontrará algunas explicaciones de las solicitudes de la API web.

Obtención de una lista de tareas pendientes

En el código siguiente, se envía una solicitud HTTP GET a la ruta api/todoitems:

fetch(uri)
  .then(response => response.json())
  .then(data => _displayItems(data))
  .catch(error => console.error('Unable to get items.', error));

Cuando la API web devuelve un código de estado correcto, se invoca la función _displayItems. Cada tarea pendiente en el parámetro de matriz aceptado por _displayItems se agrega a una tabla con los botones Editar y Eliminar. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Incorporación de una tarea pendiente

En el código siguiente:

  • Se declara una variable item para construir una representación literal de objeto de la tarea pendiente.
  • Una solicitud Fetch se configura con las siguientes opciones:
    • method: especifica el verbo de acción HTTP POST.
    • body: especifica la representación JSON del cuerpo de la solicitud. El JSON se genera pasando el literal de objeto almacenado en item a la función JSON.stringify.
    • headers: especifica los encabezados de solicitud HTTP Accept y Content-Type. Ambos encabezados se establecen en application/json para especificar el tipo de medio que se va a recibir y a enviar, respectivamente.
  • Se envía una solicitud HTTP POST a la ruta api/todoitems.
function addItem() {
  const addNameTextbox = document.getElementById('add-name');

  const item = {
    isComplete: false,
    name: addNameTextbox.value.trim()
  };

  fetch(uri, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(item)
  })
    .then(response => response.json())
    .then(() => {
      getItems();
      addNameTextbox.value = '';
    })
    .catch(error => console.error('Unable to add item.', error));
}

Cuando la API web devuelve un código de estado correcto, se invoca la función getItems para actualizar la tabla HTML. Si se produce un error en la solicitud de la API web, dicho error se registra en la consola del explorador.

Actualizar una tarea pendiente

Actualizar una tarea pendientes es similar a agregar una; sin embargo, hay dos diferencias importantes:

  • La ruta tiene como sufijo el identificador único del elemento que se va a actualizar. Por ejemplo, api/todoitems/1.
  • El verbo de acción HTTP es PUT, como se indica mediante la opción method.
fetch(`${uri}/${itemId}`, {
  method: 'PUT',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(item)
})
.then(() => getItems())
.catch(error => console.error('Unable to update item.', error));

Eliminar una tarea pendiente

Para eliminar una tarea pendiente, establezca la opción method de la solicitud en DELETE y especifique el identificador único de la tarea en la dirección URL.

fetch(`${uri}/${id}`, {
  method: 'DELETE'
})
.then(() => getItems())
.catch(error => console.error('Unable to delete item.', error));

Pase al siguiente tutorial para obtener información sobre cómo generar páginas de ayuda de API web: