教學課程:使用 JavaScript 呼叫 ASP.NET Core Web API

作者:Rick Anderson

此教學課程會示範如何使用 JavaScript (使用 Fetch API) 呼叫 ASP.NET Core Web API。

必要條件

使用 JavaScript 呼叫 Web API

在此節中,您會新增一個 HTML 網頁,其中包含用於建立及管理待辦事項的表單。 事件處理常式會附加至頁面上的元素。 事件處理常式會產生對 Web API 的動作方法發出的 HTTP 要求。 Fetch API 的 fetch 函式會起始每個 HTTP 要求。

fetch 函式會傳回 Promise 物件,其中包含以 Response 物件代表的 HTTP 回應。 常見的模式是叫用 Response 物件上的 json 函式,以擷取 JSON 回應主體。 JavaScript 會使用來自 Web API 回應的詳細資料來更新頁面。

最簡單 fetch 呼叫會接受代表路由的單一參數。 第二個參數 (稱為 init 物件) 是選擇性的。 init 是用來設定 HTTP 要求。

  1. 請設定應用程式來提供靜態檔案,並啟用預設檔案對應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. 在專案根中建立 [wwwroot] 資料夾。

  2. 在 [wwwroot] 資料夾內建立 [css] 資料夾。

  3. 在 [wwwroot] 資料夾內建立 [js] 資料夾。

  4. 將名為 index.html 的 HTML 檔案新增至 [wwwroot] 資料夾。 以下列標記取代 index.html 的內容:

    <!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. 將名為 site.css 的 CSS 檔案新增至 [wwwroot/css] 資料夾。 以下列樣式取代 site.css 的內容:

    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. 將名為 site.js 的 JavaScript 檔案新增至 [wwwroot\js] 資料夾。 以下列程式碼取代 site.js 的內容:

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

若要在本機測試 HTML 網頁,可能需要變更 ASP.NET Core 專案的啟動設定:

  1. 開啟 Properties\launchSettings.json
  2. 移除 launchUrl 屬性,以強制應用程式於 index.html 處開啟—專案的預設檔案。

此範例會呼叫 Web API 的所有 CRUD 方法。 以下是關於 Web API 要求的說明。

取得待辦事項的清單

在下列程式碼中,會將 HTTP GET 要求傳送至 [api/todoitems] 路由:

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

當 Web API 傳回成功狀態碼時,會叫用 _displayItems 函式。 _displayItems 所接受之陣列參數中的每個待辦事項,都會加入具有 [編輯] 和 [刪除] 按鈕的表格。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

新增待辦事項

在下列程式碼中:

  • 系統會宣告 item 變數來建構待辦事項的物件常值表示法。
  • 您可以使用下列選項來設定 Fetch 要求:
    • method—指定 POST HTTP 動作動詞。
    • body—指定要求本文的 JSON 表示法。 JSON 是透過將儲存在 item 中的物件常值傳遞至 JSON.stringify 函式來產生。
    • headers—指定 AcceptContent-Type HTTP 要求標頭。 這兩個標題都設定為 application/json,以分別指定接收和傳送的媒體類型。
  • HTTP POST 要求會傳送至 [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));
}

當 Web API 傳回成功狀態碼時,會叫用 getItems 函式來更新 HTML 表格 。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

更新待辦事項

更新待辦事項類似於新增待辦事項;不過,有兩個重大差異:

  • 路由的尾碼為要更新之項目的唯一識別碼。 例如,[api/todoitems/1]
  • HTTP 動作動詞命令是 PUT,如 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));

刪除待辦事項

若要刪除待辦事項,請將要求的 method 選項設定為 DELETE,並在 URL 中指定項目的唯一識別碼。

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

前進到下一個教學課程來了解如何產生 Web API 說明頁面:

此教學課程會示範如何使用 JavaScript (使用 Fetch API) 呼叫 ASP.NET Core Web API。

必要條件

使用 JavaScript 呼叫 Web API

在此節中,您會新增一個 HTML 網頁,其中包含用於建立及管理待辦事項的表單。 事件處理常式會附加至頁面上的元素。 事件處理常式會產生對 Web API 的動作方法發出的 HTTP 要求。 Fetch API 的 fetch 函式會起始每個 HTTP 要求。

fetch 函式會傳回 Promise 物件,其中包含以 Response 物件代表的 HTTP 回應。 常見的模式是叫用 Response 物件上的 json 函式,以擷取 JSON 回應主體。 JavaScript 會使用來自 Web API 回應的詳細資料來更新頁面。

最簡單 fetch 呼叫會接受代表路由的單一參數。 第二個參數 (稱為 init 物件) 是選擇性的。 init 是用來設定 HTTP 要求。

  1. 請設定應用程式來提供靜態檔案,並啟用預設檔案對應Startup.csConfigure 方法中需要下列醒目提示的程式碼:

    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. 在專案根中建立 [wwwroot] 資料夾。

  3. 在 [wwwroot] 資料夾內建立 [css] 資料夾。

  4. 在 [wwwroot] 資料夾內建立 [js] 資料夾。

  5. 將名為 index.html 的 HTML 檔案新增至 [wwwroot] 資料夾。 以下列標記取代 index.html 的內容:

    <!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. 將名為 site.css 的 CSS 檔案新增至 [wwwroot/css] 資料夾。 以下列樣式取代 site.css 的內容:

    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. 將名為 site.js 的 JavaScript 檔案新增至 [wwwroot\js] 資料夾。 以下列程式碼取代 site.js 的內容:

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

若要在本機測試 HTML 網頁,可能需要變更 ASP.NET Core 專案的啟動設定:

  1. 開啟 Properties\launchSettings.json
  2. 移除 launchUrl 屬性,以強制應用程式於 index.html 處開啟—專案的預設檔案。

此範例會呼叫 Web API 的所有 CRUD 方法。 以下是關於 Web API 要求的說明。

取得待辦事項的清單

在下列程式碼中,會將 HTTP GET 要求傳送至 [api/todoitems] 路由:

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

當 Web API 傳回成功狀態碼時,會叫用 _displayItems 函式。 _displayItems 所接受之陣列參數中的每個待辦事項,都會加入具有 [編輯] 和 [刪除] 按鈕的表格。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

新增待辦事項

在下列程式碼中:

  • 系統會宣告 item 變數來建構待辦事項的物件常值表示法。
  • 您可以使用下列選項來設定 Fetch 要求:
    • method—指定 POST HTTP 動作動詞。
    • body—指定要求本文的 JSON 表示法。 JSON 是透過將儲存在 item 中的物件常值傳遞至 JSON.stringify 函式來產生。
    • headers—指定 AcceptContent-Type HTTP 要求標頭。 這兩個標題都設定為 application/json,以分別指定接收和傳送的媒體類型。
  • HTTP POST 要求會傳送至 [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));
}

當 Web API 傳回成功狀態碼時,會叫用 getItems 函式來更新 HTML 表格 。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

更新待辦事項

更新待辦事項類似於新增待辦事項;不過,有兩個重大差異:

  • 路由的尾碼為要更新之項目的唯一識別碼。 例如,[api/todoitems/1]
  • HTTP 動作動詞命令是 PUT,如 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));

刪除待辦事項

若要刪除待辦事項,請將要求的 method 選項設定為 DELETE,並在 URL 中指定項目的唯一識別碼。

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

前進到下一個教學課程來了解如何產生 Web API 說明頁面:

此教學課程會示範如何使用 JavaScript (使用 Fetch API) 呼叫 ASP.NET Core Web API。

必要條件

使用 JavaScript 呼叫 Web API

在此節中,您會新增一個 HTML 網頁,其中包含用於建立及管理待辦事項的表單。 事件處理常式會附加至頁面上的元素。 事件處理常式會產生對 Web API 的動作方法發出的 HTTP 要求。 Fetch API 的 fetch 函式會起始每個 HTTP 要求。

fetch 函式會傳回 Promise 物件,其中包含以 Response 物件代表的 HTTP 回應。 常見的模式是叫用 Response 物件上的 json 函式,以擷取 JSON 回應主體。 JavaScript 會使用來自 Web API 回應的詳細資料來更新頁面。

最簡單 fetch 呼叫會接受代表路由的單一參數。 第二個參數 (稱為 init 物件) 是選擇性的。 init 是用來設定 HTTP 要求。

  1. 請設定應用程式來提供靜態檔案,並啟用預設檔案對應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. 在專案根中建立 [wwwroot] 資料夾。

  2. 在 [wwwroot] 資料夾內建立 [css] 資料夾。

  3. 在 [wwwroot] 資料夾內建立 [js] 資料夾。

  4. 將名為 index.html 的 HTML 檔案新增至 [wwwroot] 資料夾。 以下列標記取代 index.html 的內容:

    <!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. 將名為 site.css 的 CSS 檔案新增至 [wwwroot/css] 資料夾。 以下列樣式取代 site.css 的內容:

    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. 將名為 site.js 的 JavaScript 檔案新增至 [wwwroot\js] 資料夾。 以下列程式碼取代 site.js 的內容:

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

若要在本機測試 HTML 網頁,可能需要變更 ASP.NET Core 專案的啟動設定:

  1. 開啟 Properties\launchSettings.json
  2. 移除 launchUrl 屬性,以強制應用程式於 index.html 處開啟—專案的預設檔案。

此範例會呼叫 Web API 的所有 CRUD 方法。 以下是關於 Web API 要求的說明。

取得待辦事項的清單

在下列程式碼中,會將 HTTP GET 要求傳送至 [api/todoitems] 路由:

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

當 Web API 傳回成功狀態碼時,會叫用 _displayItems 函式。 _displayItems 所接受之陣列參數中的每個待辦事項,都會加入具有 [編輯] 和 [刪除] 按鈕的表格。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

新增待辦事項

在下列程式碼中:

  • 系統會宣告 item 變數來建構待辦事項的物件常值表示法。
  • 您可以使用下列選項來設定 Fetch 要求:
    • method—指定 POST HTTP 動作動詞。
    • body—指定要求本文的 JSON 表示法。 JSON 是透過將儲存在 item 中的物件常值傳遞至 JSON.stringify 函式來產生。
    • headers—指定 AcceptContent-Type HTTP 要求標頭。 這兩個標題都設定為 application/json,以分別指定接收和傳送的媒體類型。
  • HTTP POST 要求會傳送至 [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));
}

當 Web API 傳回成功狀態碼時,會叫用 getItems 函式來更新 HTML 表格 。 如果 Web API 要求失敗,則會在瀏覽器的主控台中記錄錯誤。

更新待辦事項

更新待辦事項類似於新增待辦事項;不過,有兩個重大差異:

  • 路由的尾碼為要更新之項目的唯一識別碼。 例如,[api/todoitems/1]
  • HTTP 動作動詞命令是 PUT,如 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));

刪除待辦事項

若要刪除待辦事項,請將要求的 method 選項設定為 DELETE,並在 URL 中指定項目的唯一識別碼。

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

前進到下一個教學課程來了解如何產生 Web API 說明頁面: