Tutorial: Chamar uma API web ASP.NET Core com JavaScript

Por Rick Anderson

Este tutorial mostra como chamar uma API web ASP.NET Core com JavaScript, usando a API Fetch.

Pré-requisitos

Chamar a API da Web com JavaScript

Nesta secção, vai adicionar uma página HTML com formulários para criar e gerir itens de tarefas. Os gestores de eventos estão associados a elementos na página. Os gestores de eventos resultam em pedidos HTTP para os métodos de ação da API web. A função da fetch API Fetch inicia cada pedido HTTP.

A fetch função devolve um Promise objeto, que contém uma resposta HTTP representada como um Response objeto. Um padrão comum é extrair o corpo de resposta JSON invocando a json função no Response objeto. O JavaScript atualiza a página com os detalhes da resposta da API web.

A chamada mais fetch simples aceita um único parâmetro que representa a rota. Um segundo parâmetro, conhecido como init objeto, é opcional. init é usado para configurar o pedido HTTP.

  1. Configura a aplicação para servir ficheiros estáticos e ativa o mapeamento de ficheiros por defeito. O seguinte código destacado é necessário em 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. Crie uma pasta wwwroot na raiz do projeto.

  2. Cria uma pasta css dentro da pasta wwwroot .

  3. Cria uma pasta js dentro da pasta wwwroot .

  4. Adicione um ficheiro HTML nomeado index.html à pasta wwwroot . Substitua o conteúdo de index.html pela seguinte marcação:

    <!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. Adicione um ficheiro CSS nomeado site.css à pasta wwwroot/css. Substitua o conteúdo de site.css pelos seguintes estilos:

    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. Adicione um ficheiro JavaScript nomeado site.js à pasta wwwroot/js . Substitua o conteúdo de site.js pelo seguinte código:

    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;
    }
    

Pode ser necessária uma alteração às definições de lançamento do projeto ASP.NET Core para testar localmente a página HTML:

  1. Abra Propriedades\launchSettings.json.
  2. Remova a launchUrl propriedade para forçar a aplicação a abrir em index.html—o ficheiro padrão do projeto.

Este exemplo chama todos os métodos CRUD da API web. Seguem-se explicações dos pedidos da API web.

Obtenha uma lista de itens por fazer

No código seguinte, um pedido HTTP GET é enviado para a rota api/todoitems :

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

Quando a API web devolve um código de estado bem-sucedido, a _displayItems função é invocada. Cada item de tarefa no parâmetro de matriz aceite por _displayItems é adicionado a uma tabela com os botões Editar e Eliminar. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Adicionar uma tarefa

No seguinte código:

  • É declarada uma variável item para construir uma representação literal de um objeto da tarefa.
  • Um pedido de busca é configurado com as seguintes opções:
    • method—especifica o verbo de ação POST HTTP.
    • body—especifica a representação JSON do corpo do pedido. O JSON é gerado ao passar o literal de objeto armazenado em item para a função JSON.stringify.
    • headers—especifica os cabeçalhos de pedido HTTP Accept e Content-Type. Ambos os cabeçalhos são definidos como application/json, para especificar o tipo de suporte multimédia que está a ser recebido e enviado, respetivamente.
  • Um pedido POST HTTP é enviado para a rota 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));
}

Quando a API web devolve um código de estado bem-sucedido, a getItems função é invocada para atualizar a tabela HTML. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Atualizar um item de tarefa

Atualizar um item to-do é semelhante a adicionar um; No entanto, existem duas diferenças significativas:

  • A rota tem como sufixo o identificador único do item a atualizar. Por exemplo, api/todoitems/1.
  • O verbo de ação HTTP é PUT, conforme indicado pela method opção.
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 um item de tarefas

Para eliminar um item de tarefa, defina a opção method do pedido como DELETE e especifique o identificador único do item no URL.

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

Avance para o próximo tutorial para aprender a gerar páginas de ajuda para APIs web:

Este tutorial mostra como chamar uma API web ASP.NET Core com JavaScript, usando a API Fetch.

Pré-requisitos

Chamar a API da Web com JavaScript

Nesta secção, vai adicionar uma página HTML com formulários para criar e gerir itens de tarefas. Os gestores de eventos estão associados a elementos na página. Os gestores de eventos resultam em pedidos HTTP para os métodos de ação da API web. A função da fetch API Fetch inicia cada pedido HTTP.

A fetch função devolve um Promise objeto, que contém uma resposta HTTP representada como um Response objeto. Um padrão comum é extrair o corpo de resposta JSON invocando a json função no Response objeto. O JavaScript atualiza a página com os detalhes da resposta da API web.

A chamada mais fetch simples aceita um único parâmetro que representa a rota. Um segundo parâmetro, conhecido como init objeto, é opcional. init é usado para configurar o pedido HTTP.

  1. Configura a aplicação para servir ficheiros estáticos e ativa o mapeamento de ficheiros por defeito. O seguinte código destacado é necessário no Configure método 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. Crie uma pasta wwwroot na raiz do projeto.

  3. Cria uma pasta css dentro da pasta wwwroot .

  4. Cria uma pasta js dentro da pasta wwwroot .

  5. Adicione um ficheiro HTML nomeado index.html à pasta wwwroot . Substitua o conteúdo de index.html pela seguinte marcação:

    <!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. Adicione um ficheiro CSS nomeado site.css à pasta wwwroot/css. Substitua o conteúdo de site.css pelos seguintes estilos:

    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. Adicione um ficheiro JavaScript nomeado site.js à pasta wwwroot/js . Substitua o conteúdo de site.js pelo seguinte código:

    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;
    }
    

Pode ser necessária uma alteração às definições de lançamento do projeto ASP.NET Core para testar localmente a página HTML:

  1. Abra Propriedades\launchSettings.json.
  2. Remova a launchUrl propriedade para forçar a aplicação a abrir em index.html—o ficheiro padrão do projeto.

Este exemplo chama todos os métodos CRUD da API web. Seguem-se explicações dos pedidos da API web.

Obtenha uma lista de itens por fazer

No código seguinte, um pedido HTTP GET é enviado para a rota api/todoitems :

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

Quando a API web devolve um código de estado bem-sucedido, a _displayItems função é invocada. Cada item de tarefa no parâmetro de matriz aceite por _displayItems é adicionado a uma tabela com os botões Editar e Eliminar. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Adicionar uma tarefa

No seguinte código:

  • É declarada uma variável item para construir uma representação literal de um objeto da tarefa.
  • Um pedido de busca é configurado com as seguintes opções:
    • method—especifica o verbo de ação POST HTTP.
    • body—especifica a representação JSON do corpo do pedido. O JSON é gerado ao passar o literal de objeto armazenado em item para a função JSON.stringify.
    • headers—especifica os cabeçalhos de pedido HTTP Accept e Content-Type. Ambos os cabeçalhos são definidos como application/json, para especificar o tipo de suporte multimédia que está a ser recebido e enviado, respetivamente.
  • Um pedido POST HTTP é enviado para a rota 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));
}

Quando a API web devolve um código de estado bem-sucedido, a getItems função é invocada para atualizar a tabela HTML. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Atualizar um item de tarefa

Atualizar um item to-do é semelhante a adicionar um; No entanto, existem duas diferenças significativas:

  • A rota tem como sufixo o identificador único do item a atualizar. Por exemplo, api/todoitems/1.
  • O verbo de ação do HTTP é PUT, conforme indicado na opção 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 um item de tarefas

Para apagar uma tarefa, defina a opção method do pedido como DELETE e especifique o identificador único do item no URL.

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

Avance para o próximo tutorial para aprender a gerar páginas de ajuda para APIs web:

Este tutorial mostra como chamar uma API web ASP.NET Core com JavaScript, usando a API Fetch.

Pré-requisitos

Chamar a API da Web com JavaScript

Nesta secção, vai adicionar uma página HTML com formulários para criar e gerir tarefas. Os gestores de eventos estão associados a elementos na página. Os gestores de eventos resultam em pedidos HTTP para os métodos de ação da API web. A função da fetch API Fetch inicia cada pedido HTTP.

A fetch função devolve um Promise objeto, que contém uma resposta HTTP representada como um Response objeto. Um padrão comum é extrair o corpo de resposta JSON invocando a json função no Response objeto. O JavaScript atualiza a página com os detalhes da resposta da API web.

A chamada mais fetch simples aceita um único parâmetro que representa a rota. Um segundo parâmetro, conhecido como init objeto, é opcional. init é usado para configurar o pedido HTTP.

  1. Configura a aplicação para servir ficheiros estáticos e ativa o mapeamento de ficheiros por defeito. O seguinte código destacado é necessário em 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. Crie uma pasta wwwroot na raiz do projeto.

  2. Cria uma pasta css dentro da pasta wwwroot .

  3. Cria uma pasta js dentro da pasta wwwroot .

  4. Adicione um ficheiro HTML nomeado index.html à pasta wwwroot . Substitua o conteúdo de index.html pela seguinte marcação:

    <!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. Adicione um ficheiro CSS nomeado site.css à pasta wwwroot/css. Substitua o conteúdo de site.css pelos seguintes estilos:

    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. Adicione um ficheiro JavaScript nomeado site.js à pasta wwwroot/js . Substitua o conteúdo de site.js pelo seguinte código:

    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;
    }
    

Pode ser necessária uma alteração às definições de lançamento do projeto ASP.NET Core para testar localmente a página HTML:

  1. Abra Propriedades\launchSettings.json.
  2. Remova a launchUrl propriedade para forçar a aplicação a abrir em index.html—o ficheiro padrão do projeto.

Este exemplo chama todos os métodos CRUD da API web. Seguem-se explicações dos pedidos da API web.

Obtenha uma lista de tarefas

No código seguinte, um pedido HTTP GET é enviado para a rota api/todoitems :

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

Quando a API web devolve um código de estado bem-sucedido, a _displayItems função é invocada. Cada item de tarefas no parâmetro de matriz recebido por _displayItems é adicionado a uma tabela com os botões para Editar e Eliminar. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Adicionar uma tarefa

No seguinte código:

  • É declarada uma variável item para construir uma representação literal do objeto do item da lista de tarefas.
  • Um pedido de busca é configurado com as seguintes opções:
    • method—especifica o verbo de ação POST HTTP.
    • body—especifica a representação JSON do corpo do pedido. O JSON é gerado ao passar o literal de objeto armazenado em item à função JSON.stringify.
    • headers—especifica os cabeçalhos HTTP do pedido Accept e Content-Type. Ambos os cabeçalhos são definidos para application/json para especificar o tipo de suporte multimédia recebido e enviado, respetivamente.
  • É enviado um pedido HTTP POST para a rota 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));
}

Quando a API web devolve um código de estado bem-sucedido, a getItems função é invocada para atualizar a tabela HTML. Se o pedido da API web falhar, um erro é registado na consola do navegador.

Atualizar um item de tarefa

Atualizar um item to-do é semelhante a adicionar um; No entanto, existem duas diferenças significativas:

  • A rota tem como sufixo o identificador único do item a atualizar. Por exemplo, api/todoitems/1.
  • O verbo de ação HTTP é PUT, conforme indicado pela method opção.
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 um item de tarefas

Para eliminar um item de tarefa, defina a opção method do pedido como DELETE e especifique o identificador único do item no URL.

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

Avance para o próximo tutorial para aprender a gerar páginas de ajuda para APIs web: