Esercitazione: Chiamare un'API Web ASP.NET Core con JavaScript

Di Rick Anderson

Questa esercitazione illustra come chiamare un'API Web ASP.NET Core con JavaScript usando l'API Fetch.

Prerequisiti

Chiamare l'API Web con JavaScript

In questa sezione verrà aggiunta una pagina HTML contenente i moduli per la creazione e la gestione di elementi attività. Agli elementi della pagina vengono associati gestori eventi. I gestori eventi generano richieste HTTP ai metodi di azione dell'API Web. La funzione fetch dell'API Fetch avvia ogni richiesta HTTP.

La funzione fetch restituisce un oggetto Promise che contiene una risposta HTTP rappresentata come oggetto Response. Un modello comune consiste nell'estrarre il corpo della JSrisposta ON richiamando la json funzione sull'oggetto Response . JavaScript aggiorna la pagina con i dettagli della risposta dell'API Web.

La chiamata fetch più semplice accetta un solo parametro che rappresenta la route. Un secondo parametro, noto come oggetto init, è facoltativo. init viene usato per configurare la richiesta HTTP.

  1. Configurare l'app in modo che gestisca i file statici e consenta il mapping di file predefinito. Il codice evidenziato seguente è necessario in 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. Creare una cartella wwwroot nella radice del progetto.

  2. Creare una cartella css all'interno della cartella wwwroot .

  3. Creare una cartella js all'interno della cartella wwwroot .

  4. Aggiungere un file HTML denominato index.html alla cartella wwwroot . Sostituire il contenuto di index.html con il markup seguente:

    <!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. Aggiungere un file CSS denominato site.css alla cartella wwwroot/css . Sostituire il contenuto di site.css con gli stili seguenti:

    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. Aggiungere un file JavaScript denominato site.js alla cartella wwwroot/js . Sostituire il contenuto di site.js con il codice seguente:

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

Può essere necessario modificare le impostazioni di avvio del progetto ASP.NET Core per il test della pagina HTML in locale:

  1. Aprire Properties\launchSettings.json.
  2. Rimuovere la launchUrl proprietà per forzare l'apertura dell'app in , index.htmlovvero il file predefinito del progetto.

In questo esempio vengono chiamati tutti i metodi CRUD dell'API Web. Di seguito sono disponibili spiegazioni per le richieste dell'API Web.

Ottenere un elenco di elementi attività

Nel codice seguente viene inviata una richiesta HTTP GET alla route api/todoitems :

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

Quando l'API Web restituisce un codice di stato di esecuzione riuscita, viene chiamata la funzione _displayItems. Ogni elemento attività nel parametro matrice accettato da _displayItems viene aggiunto a una tabella con i pulsanti Edit (Modifica) e Delete (Elimina). Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiungere un elemento attività

Nel codice seguente:

  • Viene dichiarata una variabile item per costruire una rappresentazione letterale dell'oggetto dell'elemento attività.
  • Una richiesta di recupero viene configurata con le opzioni seguenti:
    • method: specifica il verbo di azione HTTP POST.
    • body— specifica la JSrappresentazione ON del corpo della richiesta. On JSviene generato passando il valore letterale oggetto archiviato in item alla JSfunzione ON.stringify .
    • headers: specifica le intestazioni di Accept richiesta HTTP e Content-Type . Entrambe le intestazioni vengono impostate su application/json per specificare rispettivamente il tipo di supporto ricevuto e inviato.
  • Una richiesta HTTP POST viene inviata alla route 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 l'API Web restituisce un codice di stato di esecuzione riuscita, viene richiamata la funzione getItems per aggiornare la tabella HTML. Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiornare un elemento attività

L'aggiornamento di un elemento attività è simile all'aggiunta di un elemento. Esistono tuttavia due differenze significative:

  • Alla route viene aggiunto come suffisso l'identificatore univoco dell'elemento da aggiornare. Ad esempio, api/todoitems/1.
  • Il verbo di azione HTTP è PUT, come indicato dall'opzione 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));

Eliminare un elemento attività

Per eliminare un elemento attività, impostare l'opzione method della richiesta su DELETE e specificare l'identificatore univoco dell'elemento nell'URL.

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

Passare all'esercitazione successiva per apprendere come generare pagine della Guida dell'API Web:

Questa esercitazione illustra come chiamare un'API Web ASP.NET Core con JavaScript usando l'API Fetch.

Prerequisiti

Chiamare l'API Web con JavaScript

In questa sezione verrà aggiunta una pagina HTML contenente i moduli per la creazione e la gestione di elementi attività. Agli elementi della pagina vengono associati gestori eventi. I gestori eventi generano richieste HTTP ai metodi di azione dell'API Web. La funzione fetch dell'API Fetch avvia ogni richiesta HTTP.

La funzione fetch restituisce un oggetto Promise che contiene una risposta HTTP rappresentata come oggetto Response. Un modello comune consiste nell'estrarre il corpo della JSrisposta ON richiamando la json funzione sull'oggetto Response . JavaScript aggiorna la pagina con i dettagli della risposta dell'API Web.

La chiamata fetch più semplice accetta un solo parametro che rappresenta la route. Un secondo parametro, noto come oggetto init, è facoltativo. init viene usato per configurare la richiesta HTTP.

  1. Configurare l'app in modo che gestisca i file statici e consenta il mapping di file predefinito. Il codice evidenziato seguente è necessario nel Configure metodo di 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. Creare una cartella wwwroot nella radice del progetto.

  3. Creare una cartella css all'interno della cartella wwwroot .

  4. Creare una cartella js all'interno della cartella wwwroot .

  5. Aggiungere un file HTML denominato index.html alla cartella wwwroot . Sostituire il contenuto di index.html con il markup seguente:

    <!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. Aggiungere un file CSS denominato site.css alla cartella wwwroot/css . Sostituire il contenuto di site.css con gli stili seguenti:

    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. Aggiungere un file JavaScript denominato site.js alla cartella wwwroot/js . Sostituire il contenuto di site.js con il codice seguente:

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

Può essere necessario modificare le impostazioni di avvio del progetto ASP.NET Core per il test della pagina HTML in locale:

  1. Aprire Properties\launchSettings.json.
  2. Rimuovere la launchUrl proprietà per forzare l'apertura dell'app in , index.htmlovvero il file predefinito del progetto.

In questo esempio vengono chiamati tutti i metodi CRUD dell'API Web. Di seguito sono disponibili spiegazioni per le richieste dell'API Web.

Ottenere un elenco di elementi attività

Nel codice seguente viene inviata una richiesta HTTP GET alla route api/todoitems :

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

Quando l'API Web restituisce un codice di stato di esecuzione riuscita, viene chiamata la funzione _displayItems. Ogni elemento attività nel parametro matrice accettato da _displayItems viene aggiunto a una tabella con i pulsanti Edit (Modifica) e Delete (Elimina). Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiungere un elemento attività

Nel codice seguente:

  • Viene dichiarata una variabile item per costruire una rappresentazione letterale dell'oggetto dell'elemento attività.
  • Una richiesta di recupero viene configurata con le opzioni seguenti:
    • method: specifica il verbo di azione HTTP POST.
    • body— specifica la JSrappresentazione ON del corpo della richiesta. On JSviene generato passando il valore letterale oggetto archiviato in item alla JSfunzione ON.stringify .
    • headers: specifica le intestazioni di Accept richiesta HTTP e Content-Type . Entrambe le intestazioni vengono impostate su application/json per specificare rispettivamente il tipo di supporto ricevuto e inviato.
  • Una richiesta HTTP POST viene inviata alla route 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 l'API Web restituisce un codice di stato di esecuzione riuscita, viene richiamata la funzione getItems per aggiornare la tabella HTML. Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiornare un elemento attività

L'aggiornamento di un elemento attività è simile all'aggiunta di un elemento. Esistono tuttavia due differenze significative:

  • Alla route viene aggiunto come suffisso l'identificatore univoco dell'elemento da aggiornare. Ad esempio, api/todoitems/1.
  • Il verbo di azione HTTP è PUT, come indicato dall'opzione 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));

Eliminare un elemento attività

Per eliminare un elemento attività, impostare l'opzione method della richiesta su DELETE e specificare l'identificatore univoco dell'elemento nell'URL.

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

Passare all'esercitazione successiva per apprendere come generare pagine della Guida dell'API Web:

Questa esercitazione illustra come chiamare un'API Web ASP.NET Core con JavaScript usando l'API Fetch.

Prerequisiti

Chiamare l'API Web con JavaScript

In questa sezione verrà aggiunta una pagina HTML contenente i moduli per la creazione e la gestione di elementi attività. Agli elementi della pagina vengono associati gestori eventi. I gestori eventi generano richieste HTTP ai metodi di azione dell'API Web. La funzione fetch dell'API Fetch avvia ogni richiesta HTTP.

La funzione fetch restituisce un oggetto Promise che contiene una risposta HTTP rappresentata come oggetto Response. Un modello comune consiste nell'estrarre il corpo della JSrisposta ON richiamando la json funzione sull'oggetto Response . JavaScript aggiorna la pagina con i dettagli della risposta dell'API Web.

La chiamata fetch più semplice accetta un solo parametro che rappresenta la route. Un secondo parametro, noto come oggetto init, è facoltativo. init viene usato per configurare la richiesta HTTP.

  1. Configurare l'app in modo che gestisca i file statici e consenta il mapping di file predefinito. Il codice evidenziato seguente è necessario in 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. Creare una cartella wwwroot nella radice del progetto.

  2. Creare una cartella css all'interno della cartella wwwroot .

  3. Creare una cartella js all'interno della cartella wwwroot .

  4. Aggiungere un file HTML denominato index.html alla cartella wwwroot . Sostituire il contenuto di index.html con il markup seguente:

    <!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. Aggiungere un file CSS denominato site.css alla cartella wwwroot/css . Sostituire il contenuto di site.css con gli stili seguenti:

    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. Aggiungere un file JavaScript denominato site.js alla cartella wwwroot/js . Sostituire il contenuto di site.js con il codice seguente:

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

Può essere necessario modificare le impostazioni di avvio del progetto ASP.NET Core per il test della pagina HTML in locale:

  1. Aprire Properties\launchSettings.json.
  2. Rimuovere la launchUrl proprietà per forzare l'apertura dell'app in , index.htmlovvero il file predefinito del progetto.

In questo esempio vengono chiamati tutti i metodi CRUD dell'API Web. Di seguito sono disponibili spiegazioni per le richieste dell'API Web.

Ottenere un elenco di elementi attività

Nel codice seguente viene inviata una richiesta HTTP GET alla route api/todoitems :

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

Quando l'API Web restituisce un codice di stato di esecuzione riuscita, viene chiamata la funzione _displayItems. Ogni elemento attività nel parametro matrice accettato da _displayItems viene aggiunto a una tabella con i pulsanti Edit (Modifica) e Delete (Elimina). Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiungere un elemento attività

Nel codice seguente:

  • Viene dichiarata una variabile item per costruire una rappresentazione letterale dell'oggetto dell'elemento attività.
  • Una richiesta di recupero viene configurata con le opzioni seguenti:
    • method: specifica il verbo di azione HTTP POST.
    • body— specifica la JSrappresentazione ON del corpo della richiesta. On JSviene generato passando il valore letterale oggetto archiviato in item alla JSfunzione ON.stringify .
    • headers: specifica le intestazioni di Accept richiesta HTTP e Content-Type . Entrambe le intestazioni vengono impostate su application/json per specificare rispettivamente il tipo di supporto ricevuto e inviato.
  • Una richiesta HTTP POST viene inviata alla route 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 l'API Web restituisce un codice di stato di esecuzione riuscita, viene richiamata la funzione getItems per aggiornare la tabella HTML. Se la richiesta dell'API Web ha esito negativo, viene registrato un errore nella console del browser.

Aggiornare un elemento attività

L'aggiornamento di un elemento attività è simile all'aggiunta di un elemento. Esistono tuttavia due differenze significative:

  • Alla route viene aggiunto come suffisso l'identificatore univoco dell'elemento da aggiornare. Ad esempio, api/todoitems/1.
  • Il verbo di azione HTTP è PUT, come indicato dall'opzione 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));

Eliminare un elemento attività

Per eliminare un elemento attività, impostare l'opzione method della richiesta su DELETE e specificare l'identificatore univoco dell'elemento nell'URL.

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

Passare all'esercitazione successiva per apprendere come generare pagine della Guida dell'API Web: