Samouczek: wywoływanie interfejsu API sieci Web ASP.NET Core przy użyciu języka JavaScriptTutorial: Call an ASP.NET Core web API with JavaScript

Autor: Rick AndersonBy Rick Anderson

W tym samouczku pokazano, jak wywołać interfejs API sieci Web ASP.NET Core przy użyciu interfejsu API pobierania.This tutorial shows how to call an ASP.NET Core web API with JavaScript, using the Fetch API.

Aby uzyskać ASP.NET Core 2,2, zobacz wersja 2,2 wywołania interfejsu API sieci Web przy użyciu języka JavaScript.For ASP.NET Core 2.2, see the 2.2 version of Call the web API with JavaScript.

Wymagania wstępnePrerequisites

Wywoływanie interfejsu API sieci Web przy użyciu języka JavaScriptCall the web API with JavaScript

W tej sekcji dodasz stronę HTML zawierającą formularze do tworzenia elementów do wykonania i zarządzania nimi.In this section, you'll add an HTML page containing forms for creating and managing to-do items. Programy obsługi zdarzeń są dołączone do elementów na stronie.Event handlers are attached to elements on the page. Programy obsługi zdarzeń powodują żądania HTTP do metod akcji internetowego interfejsu API.The event handlers result in HTTP requests to the web API's action methods. Funkcja pobierania interfejsu API fetch inicjuje każde żądanie HTTP.The Fetch API's fetch function initiates each HTTP request.

fetchFunkcja zwraca obiekt obietnicy , który zawiera odpowiedź HTTP reprezentowane jako Response obiekt.The fetch function returns a Promise object, which contains an HTTP response represented as a Response object. Typowym wzorcem jest wyodrębnienie treści odpowiedzi JSON przez wywołanie json funkcji w Response obiekcie.A common pattern is to extract the JSON response body by invoking the json function on the Response object. Język JavaScript aktualizuje stronę ze szczegółowymi informacjami z odpowiedzi internetowego interfejsu API.JavaScript updates the page with the details from the web API's response.

Najprostsze fetch wywołanie akceptuje pojedynczy parametr reprezentujący trasę.The simplest fetch call accepts a single parameter representing the route. Drugi parametr, znany jako init obiekt, jest opcjonalny.A second parameter, known as the init object, is optional. init służy do konfigurowania żądania HTTP.init is used to configure the HTTP request.

  1. Skonfiguruj aplikację do obsługi plików statycznych i Włącz domyślne mapowanie plików.Configure the app to serve static files and enable default file mapping. Następujący wyróżniony kod jest wymagany w Configure metodzie Startup.cs: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. Utwórz folder wwwroot w katalogu głównym projektu.Create a wwwroot folder in the project root.

  3. Utwórz folder js w folderze wwwroot .Create a js folder inside of the wwwroot folder.

  4. Dodaj plik HTML o nazwie index.html do folderu wwwroot .Add an HTML file named index.html to the wwwroot folder. Zastąp zawartość index.html następującym znacznikiem: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. Dodaj plik CSS o nazwie site. css do folderu wwwroot/CSS .Add a CSS file named site.css to the wwwroot/css folder. Zastąp zawartość pliku site. css następującymi stylami: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. Dodaj plik języka JavaScript o nazwie site.js do folderu wwwroot/js .Add a JavaScript file named site.js to the wwwroot/js folder. Zastąp zawartość site.js następującym kodem: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;
    }
    

Zmiana ustawień uruchamiania projektu ASP.NET Core może być wymagana do lokalnego przetestowania strony HTML:A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally:

  1. Otwórz Properties\launchSettings.jsna.Open Properties\launchSettings.json.
  2. Usuń launchUrl Właściwość, aby wymusić otwieranie przez aplikację w index.html — domyślnego pliku projektu.Remove the launchUrl property to force the app to open at index.html—the project's default file.

Ten przykład wywołuje wszystkie metody CRUD internetowego interfejsu API.This sample calls all of the CRUD methods of the web API. Poniżej znajdują się wyjaśnienia żądań interfejsu API sieci Web.Following are explanations of the web API requests.

Pobierz listę elementów do wykonaniaGet a list of to-do items

W poniższym kodzie żądanie HTTP GET jest wysyłane do trasy API/TodoItems :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));

Gdy internetowy interfejs API zwraca kod stanu pomyślnego, _displayItems Funkcja jest wywoływana.When the web API returns a successful status code, the _displayItems function is invoked. Każdy element do wykonania w parametrze tablicy akceptowane przez _displayItems jest dodawany do tabeli za pomocą przycisków Edytuj i Usuń .Each to-do item in the array parameter accepted by _displayItems is added to a table with Edit and Delete buttons. Jeśli żądanie internetowego interfejsu API nie powiedzie się, zostanie zarejestrowany błąd w konsoli przeglądarki.If the web API request fails, an error is logged to the browser's console.

Dodaj element do wykonaniaAdd a to-do item

W poniższym kodzie:In the following code:

  • itemZmienna jest zadeklarowana do konstruowania reprezentacji literału obiektu elementu do wykonania.An item variable is declared to construct an object literal representation of the to-do item.
  • Żądanie pobrania jest konfigurowane z następującymi opcjami:A Fetch request is configured with the following options:
    • method—Określa czasownik akcji POST protokołu HTTP.method—specifies the POST HTTP action verb.
    • body—Określa reprezentację treści żądania w formacie JSON.body—specifies the JSON representation of the request body. KOD JSON jest generowany przez przekazanie literału obiektu przechowywanego w item funkcji JSON. stringify .The JSON is produced by passing the object literal stored in item to the JSON.stringify function.
    • headers—Określa Accept Content-Type nagłówki żądań HTTP i.headers—specifies the Accept and Content-Type HTTP request headers. Oba nagłówki są ustawione na application/json , aby określić typ nośnika, który jest odbierany i wysyłany odpowiednio.Both headers are set to application/json to specify the media type being received and sent, respectively.
  • Żądanie HTTP POST jest wysyłane do trasy API/TodoItems .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));
}

Gdy internetowy interfejs API zwraca kod stanu pomyślnego, getItems Funkcja jest wywoływana w celu zaktualizowania tabeli HTML.When the web API returns a successful status code, the getItems function is invoked to update the HTML table. Jeśli żądanie internetowego interfejsu API nie powiedzie się, zostanie zarejestrowany błąd w konsoli przeglądarki.If the web API request fails, an error is logged to the browser's console.

Aktualizowanie elementu do wykonaniaUpdate a to-do item

Aktualizowanie elementu do wykonania jest podobne do dodawania jednego z nich; Istnieją jednak dwie znaczące różnice:Updating a to-do item is similar to adding one; however, there are two significant differences:

  • Trasa ma sufiks z unikatowym identyfikatorem elementu do zaktualizowania.The route is suffixed with the unique identifier of the item to update. Na przykład API/TodoItems/1.For example, api/TodoItems/1.
  • Zlecenie akcji HTTP jest UMIESZCZAne zgodnie z method opcją.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));

Usuń element do wykonaniaDelete a to-do item

Aby usunąć element do wykonania, ustaw method opcję żądania na DELETE i określ unikatowy identyfikator elementu w adresie URL.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));

Przejdź do następnego samouczka, aby dowiedzieć się, jak generować strony pomocy interfejsu API sieci Web:Advance to the next tutorial to learn how to generate web API help pages: