Tutorial: Aufrufen einer ASP.NET Core-Web-API mit JavaScript

Von Rick Anderson

In diesem Tutorial erfahren Sie, wie Sie eine ASP.NET Core-Web-API über die Fetch-API mit JavaScript aufrufen.

Informationen zur Verwendung von ASP.NET Core 2.2 finden Sie im Artikel Aufrufen einer Web-API mit JavaScript (Version für 2.2).

Voraussetzungen

Aufrufen der Web-API mit JavaScript

In diesem Abschnitt fügen Sie eine HTML-Seite hinzu, die Formulare zum Erstellen und Verwalten von To-Do-Elementen enthält. An die Elemente auf der Seite sind Ereignishandler angefügt. Die Ereignishandler führen zu HTTP-Anforderungen an die Aktionsmethoden der Web-API. Die Funktion fetch der Fetch-API initiiert jede HTTP-Anforderung.

Die Funktion fetch gibt ein Promise-Objekt zurück, das eine HTTP-Antwort in Form eines Response-Objekts enthält. Ein gängiges Muster besteht darin, den JSON-Antworttext durch Aufrufen der json-Funktion im Response-Objekt zu extrahieren. JavaScript aktualisiert die Seite mit den Details aus der Antwort der Web-API.

Ein sehr einfacher fetch-Aufruf akzeptiert einen einzelnen Parameter, der die Route darstellt. Ein zweiter Parameter, der als init-Objekt bezeichnet wird, ist optional. init wird zum Konfigurieren der HTTP-Anforderung verwendet.

  1. Konfigurieren Sie die App so, dass statische Dateien unterstützt werden und die Standarddateizuordnung aktiviert wird. Der folgende markierte Code wird in der Configure-Methode von Startup.cs benötigt:

    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. Erstellen Sie im Stammverzeichnis den Ordner wwwroot.

  3. Erstellen Sie einen css-Ordner im wwwroot-Ordner.

  4. Erstellen Sie einen js-Ordner im wwwroot-Ordner.

  5. Fügen Sie eine HTML-Datei namens index.html zum wwwroot-Ordner hinzu. Ersetzen Sie den Inhalt von index.html durch folgendes Markup:

    <!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. Fügen Sie eine CSS-Datei namens site.css zum Ordner wwwroot/css hinzu. Ersetzen Sie den Inhalt der Datei site.css durch die folgenden Formatvorlagen:

    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. Fügen Sie eine JavaScript-Datei namens site.js zum Ordner wwwroot/js hinzu. Ersetzen Sie den Inhalt der Datei site.js durch den folgenden Code:

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

Möglicherweise ist eine Änderung an den Starteinstellungen des ASP.NET Core-Projekts erforderlich, um die HTML-Seite lokal zu testen:

  1. Öffnen Sie Properties\launchSettings.json.
  2. Entfernen Sie die launchUrl-Eigenschaft, um zu erzwingen, dass die App mit index.html als Startseite geöffnet wird. Dies ist die Standarddatei des Projekts.

Dieses Beispiel ruft alle CRUD-Methoden der Web-API auf. Im Folgenden werden die Web-API-Aufrufe erläutert.

Abrufen einer Liste von To-Do-Elementen

Im folgenden Code wird eine HTTP GET-Anforderung an die Route api/todoitems gesendet:

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

Wenn die Web-API den Statuscode „Erfolgreich“ zurückgibt, wird die Funktion _displayItems aufgerufen. Jedes To-Do-Element im array-Parameter, das von _displayItems akzeptiert wird, wird der Tabelle mit den Schaltflächen Bearbeiten und Löschen hinzugefügt. Wenn die Web-API-Anforderung nicht erfolgreich ausgeführt wird, wird in der Browserkonsole ein Fehler protokolliert.

Hinzufügen eines To-Do-Elements

Im folgenden Code wird Folgendes ausgeführt:

  • Eine item-Variable wird deklariert, um eine Objektliteraldarstellung des To-Do-Elements zu erstellen.
  • Eine Fetch-Anforderung wird mit den folgenden Optionen konfiguriert:
    • method – gibt das POST HTTP-Aktionsverb an.
    • body – gibt die JSON-Darstellung des Anforderungstexts an. Die JSON wird erzeugt, indem das in item gespeicherte Objektliteral an die Funktion JSON.stringify übergeben wird.
    • headers – gibt die HTTP-Anforderungsheader Accept und Content-Type an. Beide Header sind auf application/json festgelegt, um den gesendeten und empfangenen Medientyp anzugeben.
  • Eine HTTP POST-Anforderung wird an die Route api/todoitems gesendet.
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));
}

Wenn die Web-API den Statuscode „Erfolgreich“ zurückgibt, wird die Funktion getItems aufgerufen, um die HTML-Tabelle zu aktualisieren. Wenn die Web-API-Anforderung nicht erfolgreich ausgeführt wird, wird in der Browserkonsole ein Fehler protokolliert.

Aktualisieren eines To-Do-Elements

Das Aktualisieren eines To-Do-Elements funktioniert sehr ähnlich wie das Hinzufügen. Allerdings gibt es zwei wesentliche Unterschiede:

  • Die Route erhält den eindeutigen Bezeichner des zu aktualisierenden Elements als Suffix. Beispiel: api/todoitems/1
  • Das HTTP-Aktionsverb ist PUT, wie durch die Option method angegeben.
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));

Löschen eines To-Do-Elements

Um ein To-Do-Element zu löschen, legen Sie die method-Option der Anforderung auf DELETE fest, und geben Sie den eindeutigen Bezeichner des Elements in der URL an.

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

Fahren Sie mit dem nächsten Tutorial fort, um zu erfahren, wie Sie Web-API-Hilfeseiten generieren: