diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 0b6dbcf8b42d..5555c14fdf6f 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -879,6 +879,11 @@ "source_path": "aspnetcore/host-and-deploy/azure-apps/troubleshoot.md", "redirect_url": "/aspnet/core/test/troubleshoot-azure-iis", "redirect_document_id": false + }, + { + "source_path": "aspnetcore/tutorials/web-api-jquery.md", + "redirect_url": "/aspnet/core/tutorials/web-api-javascript", + "redirect_document_id": false } ] } diff --git a/aspnetcore/toc.yml b/aspnetcore/toc.yml index 47e5680c15b8..5c03f14cb40a 100644 --- a/aspnetcore/toc.yml +++ b/aspnetcore/toc.yml @@ -81,9 +81,9 @@ - name: Web API with MongoDB displayName: tutorial uid: tutorials/first-mongo-app - - name: Web API with jQuery + - name: Web API with JavaScript displayName: tutorial - uid: tutorials/web-api-jquery + uid: tutorials/web-api-javascript - name: Backend for mobile displayName: tutorial uid: mobile/native-mobile-backend diff --git a/aspnetcore/tutorials/first-web-api.md b/aspnetcore/tutorials/first-web-api.md index 4b7c61d1aa0d..b8b12a67a2f5 100644 --- a/aspnetcore/tutorials/first-web-api.md +++ b/aspnetcore/tutorials/first-web-api.md @@ -4,7 +4,7 @@ author: rick-anderson description: Learn how to build a web API with ASP.NET Core. ms.author: riande ms.custom: mvc -ms.date: 08/14/2019 +ms.date: 08/27/2019 uid: tutorials/first-web-api --- @@ -457,9 +457,9 @@ Use Postman to delete a to-do item: * Set the URI of the object to delete, for example `https://localhost:5001/api/TodoItems/1` * Select **Send** -## Call the API from jQuery +## Call the web API with JavaScript -See [Tutorial: Call an ASP.NET Core web API with jQuery](xref:tutorials/web-api-jquery). +See [Tutorial: Call an ASP.NET Core web API with JavaScript](xref:tutorials/web-api-javascript). ::: moniker-end @@ -475,9 +475,10 @@ In this tutorial, you learn how to: > * Configure routing and URL paths. > * Specify return values. > * Call the web API with Postman. -> * Call the web API with jQuery. +> * Call the web API with JavaScript. At the end, you have a web API that can manage "to-do" items stored in a relational database. + ## Overview This tutorial creates the following API: @@ -732,7 +733,6 @@ The return type of the `GetTodoItems` and `GetTodoItem` methods is [ActionResult * If no item matches the requested ID, the method returns a 404 [NotFound](/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.notfound) error code. * Otherwise, the method returns 200 with a JSON response body. Returning `item` results in an HTTP 200 response. - ## Test the GetTodoItems method This tutorial uses Postman to test the web API. @@ -858,9 +858,9 @@ Use Postman to delete a to-do item: The sample app allows you to delete all the items. However, when the last item is deleted, a new one is created by the model class constructor the next time the API is called. -## Call the API with jQuery +## Call the web API with JavaScript -In this section, an HTML page is added that uses jQuery to call the web api. jQuery initiates the request and updates the page with the details from the API's response. +In this section, an HTML page is added that uses JavaScript to call the web API. The Fetch API initiates the request. JavaScript updates the page with the details from the web API's response. Configure the app to [serve static files](/dotnet/api/microsoft.aspnetcore.builder.staticfileextensions.usestaticfiles#Microsoft_AspNetCore_Builder_StaticFileExtensions_UseStaticFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) and [enable default file mapping](/dotnet/api/microsoft.aspnetcore.builder.defaultfilesextensions.usedefaultfiles#Microsoft_AspNetCore_Builder_DefaultFilesExtensions_UseDefaultFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) by updating *Startup.cs* with the following highlighted code: @@ -881,19 +881,17 @@ A change to the ASP.NET Core project's launch settings may be required to test t * Open *Properties\launchSettings.json*. * Remove the `launchUrl` property to force the app to open at *index.html*—the project's default file. -There are several ways to get jQuery. In the preceding snippet, the library is loaded from a CDN. - -This sample calls all of the CRUD methods of the API. Following are explanations of the calls to the API. +This sample calls all of the CRUD methods of the web API. Following are explanations of the calls to the API. ### Get a list of to-do items -The jQuery [ajax](https://api.jquery.com/jquery.ajax/) function sends a `GET` request to the API, which returns JSON representing an array of to-do items. The `success` callback function is invoked if the request succeeds. In the callback, the DOM is updated with the to-do information. +Fetch sends an HTTP GET request to the web API, which returns JSON representing an array of to-do items. The `success` callback function is invoked if the request succeeds. In the callback, the DOM is updated with the to-do information. [!code-javascript[](first-web-api/samples/2.2/TodoApi/wwwroot/site.js?name=snippet_GetData)] ### Add a to-do item -The [ajax](https://api.jquery.com/jquery.ajax/) function sends a `POST` request with the to-do item in the request body. The `accepts` and `contentType` options are set to `application/json` to specify the media type being received and sent. The to-do item is converted to JSON by using [JSON.stringify](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). When the API returns a successful status code, the `getData` function is invoked to update the HTML table. +Fetch sends an HTTP POST request with the to-do item in the request body. The `accepts` and `contentType` options are set to `application/json` to specify the media type being received and sent. The to-do item is converted to JSON by using [JSON.stringify](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). When the API returns a successful status code, the `getData` function is invoked to update the HTML table. [!code-javascript[](first-web-api/samples/2.2/TodoApi/wwwroot/site.js?name=snippet_AddItem)] diff --git a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJquery.cs b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJavaScript.cs similarity index 91% rename from aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJquery.cs rename to aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJavaScript.cs index 7a71bbefb770..eacc870ae5fc 100644 --- a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJquery.cs +++ b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/StartupJavaScript.cs @@ -9,9 +9,9 @@ namespace TodoApi { - public class StartupJquery + public class StartupJavaScript { - public StartupJquery(IConfiguration configuration) + public StartupJavaScript(IConfiguration configuration) { Configuration = configuration; } diff --git a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/css/site.css b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/css/site.css new file mode 100644 index 000000000000..2cf9f828712a --- /dev/null +++ b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/css/site.css @@ -0,0 +1,23 @@ +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; +} diff --git a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/index.html b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/index.html index 41fe2ca3fb7e..546c41bc3ed0 100644 --- a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/index.html +++ b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/index.html @@ -3,31 +3,7 @@ To-do CRUD - +

To-do CRUD

@@ -37,9 +13,9 @@

Add

-
+

Edit

-
+ @@ -52,7 +28,7 @@

Edit

- + @@ -60,9 +36,9 @@

Edit

Is CompleteIs Complete? Name
- - + + diff --git a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js new file mode 100644 index 000000000000..ccb35bf1e67f --- /dev/null +++ b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js @@ -0,0 +1,135 @@ +// +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 delete 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; +} +// diff --git a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/site.js b/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/site.js deleted file mode 100644 index f5721a3918f0..000000000000 --- a/aspnetcore/tutorials/first-web-api/samples/3.0/TodoApi/wwwroot/site.js +++ /dev/null @@ -1,144 +0,0 @@ -// -const uri = 'api/TodoItems'; -let todos = null; -function getCount(data) { - const el = $('#counter'); - let name = 'to-do'; - if (data) { - if (data > 1) { - name = 'to-dos'; - } - el.text(data + ' ' + name); - } else { - el.text('No ' + name); - } -} - -// -$(document).ready(function() { - getData(); -}); - -function getData() { - $.ajax({ - type: 'GET', - url: uri, - cache: false, - success: function(data) { - const tBody = $('#todos'); - - $(tBody).empty(); - - getCount(data.length); - - $.each(data, function(key, item) { - const tr = $('') - .append( - $('').append( - $('', { - type: 'checkbox', - disabled: true, - checked: item.isComplete - }) - ) - ) - .append($('').text(item.name)) - .append( - $('').append( - $('').on('click', function() { - editItem(item.id); - }) - ) - ) - .append( - $('').append( - $('').on('click', function() { - deleteItem(item.id); - }) - ) - ); - - tr.appendTo(tBody); - }); - - todos = data; - } - }); -} -// - -// -function addItem() { - const item = { - name: $('#add-name').val(), - isComplete: false - }; - - $.ajax({ - type: 'POST', - accepts: 'application/json', - url: uri, - contentType: 'application/json', - data: JSON.stringify(item), - error: function(jqXHR, textStatus, errorThrown) { - alert('Something went wrong!'); - }, - success: function(result) { - getData(); - $('#add-name').val(''); - } - }); -} -// - -function deleteItem(id) { - // - $.ajax({ - url: uri + '/' + id, - type: 'DELETE', - success: function(result) { - getData(); - } - }); - // -} - -function editItem(id) { - $.each(todos, function(key, item) { - if (item.id === id) { - $('#edit-name').val(item.name); - $('#edit-id').val(item.id); - $('#edit-isComplete')[0].checked = item.isComplete; - } - }); - $('#spoiler').css({ display: 'block' }); -} - -$('.my-form').on('submit', function() { - const item = { - name: $('#edit-name').val(), - isComplete: $('#edit-isComplete').is(':checked'), - id: parseInt($('#edit-id').val(), 10) - }; - - // - $.ajax({ - url: uri + '/' + $('#edit-id').val(), - type: 'PUT', - accepts: 'application/json', - contentType: 'application/json', - data: JSON.stringify(item), - success: function(result) { - getData(); - } - }); - // - - closeInput(); - return false; -}); - -function closeInput() { - $('#spoiler').css({ display: 'none' }); -} -// diff --git a/aspnetcore/tutorials/web-api-javascript.md b/aspnetcore/tutorials/web-api-javascript.md new file mode 100644 index 000000000000..9d0a8bb943a6 --- /dev/null +++ b/aspnetcore/tutorials/web-api-javascript.md @@ -0,0 +1,101 @@ +--- +title: "Tutorial: Call an ASP.NET Core web API with JavaScript" +author: rick-anderson +description: Learn how to call an ASP.NET Core web API with JavaScript. +ms.author: riande +ms.custom: mvc +ms.date: 08/27/2019 +uid: tutorials/web-api-javascript +--- +# Tutorial: Call an ASP.NET Core web API with JavaScript + +By [Rick Anderson](https://twitter.com/RickAndMSFT) + +This tutorial shows how to call an ASP.NET Core web API with JavaScript, using the [Fetch API](https://developer.mozilla.org/docs/Web/API/Fetch_API). + +::: moniker range="< aspnetcore-3.0" + +For ASP.NET Core 2.2, see the 2.2 version of [Call the web API with JavaScript](xref:tutorials/first-web-api#call-the-web-api-with-javascript). + +::: moniker-end + +::: moniker range=">= aspnetcore-3.0" + +## Prerequisites + +* Complete [Tutorial: Create a web API](xref:tutorials/first-web-api) +* Familiarity with CSS, HTML, and JavaScript + +## Call the web API with JavaScript + +In this section, you'll add an HTML page containing forms for creating and managing to-do items. Event handlers are attached to elements on the page. The event handlers result in HTTP requests to the web API's action methods. The Fetch API's `fetch` function initiates each HTTP request. + +The `fetch` function returns a `Promise` object, which contains an HTTP response represented as a `Response` object. A common pattern is to extract the JSON response body by invoking the `json` function on the `Response` object. JavaScript updates the page with the details from the web API's response. + +The simplest `fetch` call accepts a single parameter representing the route. A second parameter, known as the `init` object, is optional. `init` is used to configure the HTTP request. + +1. Configure the app to [serve static files](/dotnet/api/microsoft.aspnetcore.builder.staticfileextensions.usestaticfiles#Microsoft_AspNetCore_Builder_StaticFileExtensions_UseStaticFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) and [enable default file mapping](/dotnet/api/microsoft.aspnetcore.builder.defaultfilesextensions.usedefaultfiles#Microsoft_AspNetCore_Builder_DefaultFilesExtensions_UseDefaultFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_). The following highlighted code is needed in the `Configure` method of *Startup.cs*: + + [!code-csharp[](first-web-api/samples/3.0/TodoApi/StartupJavaScript.cs?highlight=8-9&name=snippet_configure)] + +1. Create a *wwwroot* directory in the project root. + +1. Add an HTML file named *index.html* to the *wwwroot* directory. Replace its contents with the following markup: + + [!code-html[](first-web-api/samples/3.0/TodoApi/wwwroot/index.html)] + +1. Add a JavaScript file named *site.js* to the *wwwroot* directory. Replace its contents with the following code: + + [!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js?name=snippet_SiteJs)] + +A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally: + +1. Open *Properties\launchSettings.json*. +1. Remove the `launchUrl` property to force the app to open at *index.html*—the project's default file. + +This sample calls all of the CRUD methods of the web API. Following are explanations of the web API requests. + +### Get a list of to-do items + +In the following code, an HTTP GET request is sent to the *api/TodoItems* route: + +[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js?name=snippet_GetItems)] + +When the web API returns a successful status code, the `_displayItems` function is invoked. Each to-do item in the array parameter accepted by `_displayItems` is added to a table with **Edit** and **Delete** buttons. If the web API request fails, an error is logged to the browser's console. + +### Add a to-do item + +In the following code: + +* An `item` variable is declared to construct an object literal representation of the to-do item. +* A Fetch request is configured with the following options: + * `method`—specifies the POST HTTP action verb. + * `body`—specifies the JSON representation of the request body. The JSON is produced by passing the object literal stored in `item` to the [JSON.stringify](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) function. + * `headers`—specifies the `Accept` and `Content-Type` HTTP request headers. Both headers are set to `application/json` to specify the media type being received and sent, respectively. +* An HTTP POST request is sent to the *api/TodoItems* route. + +[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js?name=snippet_AddItem)] + +When the web API returns a successful status code, the `getItems` function is invoked to update the HTML table. If the web API request fails, an error is logged to the browser's console. + +### Update a to-do item + +Updating a to-do item is similar to adding one; however, there are two significant differences: + +* The route is suffixed with the unique identifier of the item to update. For example, *api/TodoItems/1*. +* The HTTP action verb is PUT, as indicated by the `method` option. + +[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js?name=snippet_UpdateItem)] + +### Delete a to-do item + +To delete a to-do item, set the request's `method` option to `DELETE` and specify the item's unique identifier in the URL. + +[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/js/site.js?name=snippet_DeleteItem)] + +Advance to the next tutorial to learn how to generate web API help pages: + +> [!div class="nextstepaction"] +> + +::: moniker-end diff --git a/aspnetcore/tutorials/web-api-jquery.md b/aspnetcore/tutorials/web-api-jquery.md deleted file mode 100644 index 0dad0fefd005..000000000000 --- a/aspnetcore/tutorials/web-api-jquery.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: "Tutorial: Call a web API with jQuery using ASP.NET Core" -author: rick-anderson -description: Learn how to call an ASP.NET Core web API with jQuery. -ms.author: riande -ms.custom: mvc -ms.date: 07/20/2019 -uid: tutorials/web-api-jquery ---- - -# Tutorial: Call an ASP.NET Core web API with jQuery - -By [Rick Anderson](https://twitter.com/RickAndMSFT) - -This tutorial shows how to call an ASP.NET Core web API with jQuery - -::: moniker range="< aspnetcore-3.0" - -For ASP.NET Core 2.2, see the 2.2 version of [Call the Web API with jQuery](xref:tutorials/first-web-api#call-the-api-with-jquery). - -::: moniker-end - -::: moniker range=">= aspnetcore-3.0" - -## Prerequisites - -* Complete [Tutorial: Create a web API](xref:tutorials/first-web-api) -* Familiarity with CSS, HTML, JavaScript, and jQuery - -## Call the API with jQuery - -In this section, an HTML page is added that uses jQuery to call the web api. jQuery initiates the request and updates the page with the details from the API's response. - -Configure the app to [serve static files](/dotnet/api/microsoft.aspnetcore.builder.staticfileextensions.usestaticfiles#Microsoft_AspNetCore_Builder_StaticFileExtensions_UseStaticFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) and [enable default file mapping](/dotnet/api/microsoft.aspnetcore.builder.defaultfilesextensions.usedefaultfiles#Microsoft_AspNetCore_Builder_DefaultFilesExtensions_UseDefaultFiles_Microsoft_AspNetCore_Builder_IApplicationBuilder_) by updating *Startup.cs* with the following highlighted code: - -[!code-csharp[](first-web-api/samples/3.0/TodoApi/StartupJquery.cs?highlight=8-9&name=snippet_configure)] - -Create a *wwwroot* folder in the project directory. - -Add an HTML file named *index.html* to the *wwwroot* directory. Replace its contents with the following markup: - -[!code-html[](first-web-api/samples/3.0/TodoApi/wwwroot/index.html)] - -Add a JavaScript file named *site.js* to the *wwwroot* directory. Replace its contents with the following code: - -[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/site.js?name=snippet_SiteJs)] - -A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally: - -* Open *Properties\launchSettings.json*. -* Remove the `launchUrl` property to force the app to open at *index.html*—the project's default file. - -There are several ways to get jQuery. In the preceding snippet, the library is loaded from a CDN. - -This sample calls all of the CRUD methods of the API. Following are explanations of the calls to the API. - -### Get a list of to-do items - -The jQuery [ajax](https://api.jquery.com/jquery.ajax/) function sends a `GET` request to the API, which returns JSON representing an array of to-do items. The `success` callback function is invoked if the request succeeds. In the callback, the DOM is updated with the to-do information. - -[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/site.js?name=snippet_GetData)] - -### Add a to-do item - -The [ajax](https://api.jquery.com/jquery.ajax/) function sends a `POST` request with the to-do item in the request body. The `accepts` and `contentType` options are set to `application/json` to specify the media type being received and sent. The to-do item is converted to JSON by using [JSON.stringify](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). When the API returns a successful status code, the `getData` function is invoked to update the HTML table. - -[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/site.js?name=snippet_AddItem)] - -### Update a to-do item - -Updating a to-do item is similar to adding one. The `url` changes to add the unique identifier of the item, and the `type` is `PUT`. - -[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/site.js?name=snippet_AjaxPut)] - -### Delete a to-do item - -Deleting a to-do item is accomplished by setting the `type` on the AJAX call to `DELETE` and specifying the item's unique identifier in the URL. - -[!code-javascript[](first-web-api/samples/3.0/TodoApi/wwwroot/site.js?name=snippet_AjaxDelete)] - -Advance to the next tutorial to learn how to generate API help pages: - -> [!div class="nextstepaction"] -> -::: moniker-end