Tutorial: Aufrufen einer ASP.NET Core-Web-API mit JavaScriptTutorial: Call an ASP.NET Core web API with JavaScript

Von Rick AndersonBy Rick Anderson

In diesem Tutorial erfahren Sie, wie Sie eine ASP.NET Core-Web-API über die Fetch-API mit JavaScript aufrufen.This tutorial shows how to call an ASP.NET Core web API with JavaScript, using the Fetch API.

Informationen zur Verwendung von ASP.NET Core 2.2 finden Sie im Artikel Aufrufen einer Web-API mit JavaScript (Version für 2.2).For ASP.NET Core 2.2, see the 2.2 version of Call the web API with JavaScript.

VoraussetzungenPrerequisites

Aufrufen der Web-API mit JavaScriptCall the web API with JavaScript

In diesem Abschnitt fügen Sie eine HTML-Seite hinzu, die Formulare zum Erstellen und Verwalten von To-Do-Elementen enthält.In this section, you'll add an HTML page containing forms for creating and managing to-do items. An die Elemente auf der Seite sind Ereignishandler angefügt.Event handlers are attached to elements on the page. Die Ereignishandler führen zu HTTP-Anforderungen an die Aktionsmethoden der Web-API.The event handlers result in HTTP requests to the web API's action methods. Die Funktion fetch der Fetch-API initiiert jede HTTP-Anforderung.The Fetch API's fetch function initiates each HTTP request.

Die Funktion fetch gibt ein Promise-Objekt zurück, das eine HTTP-Antwort in Form eines Response-Objekts enthält.The fetch function returns a Promise object, which contains an HTTP response represented as a Response object. Ein gängiges Muster besteht darin, den JSON-Antworttext durch Aufrufen der json-Funktion im Response-Objekt zu extrahieren.A common pattern is to extract the JSON response body by invoking the json function on the Response object. JavaScript aktualisiert die Seite mit den Details aus der Antwort der Web-API.JavaScript updates the page with the details from the web API's response.

Ein sehr einfacher fetch-Aufruf akzeptiert einen einzelnen Parameter, der die Route darstellt.The simplest fetch call accepts a single parameter representing the route. Ein zweiter Parameter, der als init-Objekt bezeichnet wird, ist optional.A second parameter, known as the init object, is optional. init wird zum Konfigurieren der HTTP-Anforderung verwendet.init is used to configure the HTTP request.

  1. Konfigurieren Sie die App so, dass statische Dateien unterstützt werden und die Standarddateizuordnung aktiviert wird.Configure the app to serve static files and enable default file mapping. Der folgende markierte Code wird in der Configure-Methode von Startup.cs benötigt:The following highlighted code is needed in the Configure method of 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. Erstellen Sie im Stammverzeichnis den Ordner wwwroot.Create a wwwroot folder in the project root.

  3. Erstellen Sie einen js-Ordner im wwwroot-Ordner.Create a js folder inside of the wwwroot folder.

  4. Fügen Sie eine HTML-Datei namens index.html zum wwwroot-Ordner hinzu.Add an HTML file named index.html to the wwwroot folder. Ersetzen Sie den Inhalt von index.html durch folgendes Markup:Replace the contents of index.html with the following 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>
    
  5. Fügen Sie eine CSS-Datei namens site.css zum Ordner wwwroot/css hinzu.Add a CSS file named site.css to the wwwroot/css folder. Ersetzen Sie den Inhalt der Datei site.css durch die folgenden Formatvorlagen:Replace the contents of site.css with the following styles:

    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. Fügen Sie eine JavaScript-Datei namens site.js zum Ordner wwwroot/js hinzu.Add a JavaScript file named site.js to the wwwroot/js folder. Ersetzen Sie den Inhalt der Datei site.js durch den folgenden Code:Replace the contents of site.js with the following 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:A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally:

  1. Öffnen Sie Properties\launchSettings.json.Open 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.Remove the launchUrl property to force the app to open at index.html—the project's default file.

Dieses Beispiel ruft alle CRUD-Methoden der Web-API auf.This sample calls all of the CRUD methods of the web API. Im Folgenden werden die Web-API-Aufrufe erläutert.Following are explanations of the web API requests.

Abrufen einer Liste von To-Do-ElementenGet a list of to-do items

Im folgenden Code wird eine HTTP GET-Anforderung an die Route api/TodoItems gesendet:In the following code, an HTTP GET request is sent to the api/TodoItems route:

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.When the web API returns a successful status code, the _displayItems function is invoked. 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.Each to-do item in the array parameter accepted by _displayItems is added to a table with Edit and Delete buttons. Wenn die Web-API-Anforderung nicht erfolgreich ausgeführt wird, wird in der Browserkonsole ein Fehler protokolliert.If the web API request fails, an error is logged to the browser's console.

Hinzufügen eines To-Do-ElementsAdd a to-do item

Im folgenden Code wird Folgendes ausgeführt:In the following code:

  • Eine item-Variable wird deklariert, um eine Objektliteraldarstellung des To-Do-Elements zu erstellen.An item variable is declared to construct an object literal representation of the to-do item.
  • Eine Fetch-Anforderung wird mit den folgenden Optionen konfiguriert:A Fetch request is configured with the following options:
    • method – gibt das POST HTTP-Aktionsverb an.method—specifies the POST HTTP action verb.
    • body – gibt die JSON-Darstellung des Anforderungstexts an.body—specifies the JSON representation of the request body. Die JSON wird erzeugt, indem das in item gespeicherte Objektliteral an die Funktion JSON.stringify übergeben wird.The JSON is produced by passing the object literal stored in item to the JSON.stringify function.
    • headers – gibt die HTTP-Anforderungsheader Accept und Content-Type an.headers—specifies the Accept and Content-Type HTTP request headers. Beide Header sind auf application/json festgelegt, um den gesendeten und empfangenen Medientyp anzugeben.Both headers are set to application/json to specify the media type being received and sent, respectively.
  • Eine HTTP POST-Anforderung wird an die Route api/TodoItems gesendet.An HTTP POST request is sent to the api/TodoItems route.
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.When the web API returns a successful status code, the getItems function is invoked to update the HTML table. Wenn die Web-API-Anforderung nicht erfolgreich ausgeführt wird, wird in der Browserkonsole ein Fehler protokolliert.If the web API request fails, an error is logged to the browser's console.

Aktualisieren eines To-Do-ElementsUpdate a to-do item

Das Aktualisieren eines To-Do-Elements funktioniert sehr ähnlich wie das Hinzufügen. Allerdings gibt es zwei wesentliche Unterschiede:Updating a to-do item is similar to adding one; however, there are two significant differences:

  • Die Route erhält den eindeutigen Bezeichner des zu aktualisierenden Elements als Suffix.The route is suffixed with the unique identifier of the item to update. Beispiel: api/TodoItems/1.For example, api/TodoItems/1.
  • Das HTTP-Aktionsverb ist PUT, wie durch die Option method angegeben.The HTTP action verb is PUT, as indicated by the method option.
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-ElementsDelete a to-do item

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.To delete a to-do item, set the request's method option to DELETE and specify the item's unique identifier in the URL.

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:Advance to the next tutorial to learn how to generate web API help pages: