Учебник. Создание веб-API с помощью ASP.NET CoreTutorial: Create a web API with ASP.NET Core

Авторы: Рик Андерсон и Майк УоссонBy Rick Anderson and Mike Wasson

В этом учебнике приводятся основные сведения о создании веб-API с помощью ASP.NET Core.This tutorial teaches the basics of building a web API with ASP.NET Core.

В этом руководстве вы узнаете, как:In this tutorial, you learn how to:

  • Создание проекта веб-API.Create a web API project.
  • Добавление класса модели и контекста базы данных.Add a model class and a database context.
  • Формирование шаблонов контроллера с использованием методов CRUD.Scaffold a controller with CRUD methods.
  • Настройка маршрутизации, URL-пути и возвращаемых значений.Configure routing, URL paths, and return values.
  • Вызов веб-API с помощью Postman.Call the web API with Postman.

В итоге вы получите веб-API, позволяющий работать с элементами списка дел, хранимыми в базе данных.At the end, you have a web API that can manage "to-do" items stored in a database.

ОбзорOverview

В этом руководстве создается следующий API-интерфейс:This tutorial creates the following API:

APIAPI ОПИСАНИЕDescription Текст запросаRequest body Текст ответаResponse body
GET /api/TodoItemsGET /api/TodoItems Получение всех элементов задачGet all to-do items НетNone Массив элементов задачArray of to-do items
GET /api/TodoItems/{id}GET /api/TodoItems/{id} Получение объекта по идентификаторуGet an item by ID НетNone Элемент задачиTo-do item
POST /api/TodoItemsPOST /api/TodoItems Добавление нового элементаAdd a new item Элемент задачиTo-do item Элемент задачиTo-do item
PUT /api/TodoItems/{id}PUT /api/TodoItems/{id} Обновление существующего элемента  Update an existing item   Элемент задачиTo-do item НетNone
DELETE /api/TodoItems/{id}    DELETE /api/TodoItems/{id}     Удаление элемента    Delete an item     НетNone НетNone

На следующем рисунке показана структура приложения.The following diagram shows the design of the app.

Клиент представлен прямоугольником слева.

Предварительные требованияPrerequisites

Создайте веб-проект.Create a web project

  • В меню Файл выберите Создать > Проект.From the File menu, select New > Project.
  • Выберите шаблон Веб-приложение ASP.NET Core и нажмите Далее.Select the ASP.NET Core Web Application template and click Next.
  • Назовите проект TodoApi и нажмите Создать.Name the project TodoApi and click Create.
  • В диалоговом окне Создание веб-приложения ASP.NET Core убедитесь в том, что выбраны платформы .NET Core и ASP.NET Core 3.0.In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 3.0 are selected. Выберите шаблон API и нажмите кнопку Создать.Select the API template and click Create. Не выбирайте Включение поддержки Docker.Don't select Enable Docker Support.

Диалоговое окно создания проекта VS

Тестирование APITest the API

Шаблон проекта создает API WeatherForecast.The project template creates a WeatherForecast API. Вызовите метод Get из браузера для тестирования приложения.Call the Get method from a browser to test the app.

Нажмите клавиши CTRL+F5, чтобы запустить приложение.Press Ctrl+F5 to run the app. Visual Studio запустит браузер и перейдет к https://localhost:<port>/WeatherForecast, где <port> — это номер порта, выбранный случайным образом.Visual Studio launches a browser and navigates to https://localhost:<port>/WeatherForecast, where <port> is a randomly chosen port number.

Если появится диалоговое окно с запросом о необходимости доверять сертификату IIS Express, выберите Да.If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. В появляющемся следом диалоговом окне Предупреждение системы безопасности выберите Да.In the Security Warning dialog that appears next, select Yes.

Возвращаемые данные JSON будут выглядеть примерно так:JSON similar to the following is returned:

[
    {
        "date": "2019-07-16T19:04:05.7257911-06:00",
        "temperatureC": 52,
        "temperatureF": 125,
        "summary": "Mild"
    },
    {
        "date": "2019-07-17T19:04:05.7258461-06:00",
        "temperatureC": 36,
        "temperatureF": 96,
        "summary": "Warm"
    },
    {
        "date": "2019-07-18T19:04:05.7258467-06:00",
        "temperatureC": 39,
        "temperatureF": 102,
        "summary": "Cool"
    },
    {
        "date": "2019-07-19T19:04:05.7258471-06:00",
        "temperatureC": 10,
        "temperatureF": 49,
        "summary": "Bracing"
    },
    {
        "date": "2019-07-20T19:04:05.7258474-06:00",
        "temperatureC": -1,
        "temperatureF": 31,
        "summary": "Chilly"
    }
]

Добавление класса моделиAdd a model class

Модель — это набор классов, представляющих данные, которыми управляет приложение.A model is a set of classes that represent the data that the app manages. Модель этого приложения содержит единственный класс TodoItem.The model for this app is a single TodoItem class.

  • В обозревателе решений щелкните проект правой кнопкой мыши.In Solution Explorer, right-click the project. Выберите Добавить > Новая папка.Select Add > New Folder. Присвойте папке имя Models.Name the folder Models.

  • Щелкните папку Models правой кнопкой мыши и выберите Добавить > Класс.Right-click the Models folder and select Add > Class. Присвойте классу имя TodoItem и выберите Добавить.Name the class TodoItem and select Add.

  • Замените код шаблона следующим кодом:Replace the template code with the following code:

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

Свойство Id выступает в качестве уникального ключа реляционной базы данных.The Id property functions as the unique key in a relational database.

Классы моделей можно размещать в любом месте проекта, но обычно для этого используется папка Models.Model classes can go anywhere in the project, but the Models folder is used by convention.

Добавление контекста базы данныхAdd a database context

Контекст базы данных —это основной класс, который координирует функциональные возможности Entity Framework для модели данных.The database context is the main class that coordinates Entity Framework functionality for a data model. Этот класс является производным от класса Microsoft.EntityFrameworkCore.DbContext.This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.

Добавление Microsoft.EntityFrameworkCore.SqlServerAdd Microsoft.EntityFrameworkCore.SqlServer

  • В меню Сервис выберите Диспетчер пакетов NuGet > Управление пакетами NuGet для решения.From the Tools menu, select NuGet Package Manager > Manage NuGet Packages for Solution.
  • Установите флажок Включить предварительные выпуски.Select the Include prerelease checkbox.
  • Перейдите на вкладку Обзор и введите Microsoft.EntityFrameworkCore.SqlServer в поле поиска.Select the Browse tab, and then enter Microsoft.EntityFrameworkCore.SqlServer in the search box.
  • В панели слева выберите Microsoft.EntityFrameworkCore.SqlServer V3.0.0-preview.Select Microsoft.EntityFrameworkCore.SqlServer V3.0.0-preview in the left pane.
  • Установите флажок Проект на правой панели и выберите Установить.Select the Project check box in the right pane and then select Install.
  • Добавьте пакет NuGet Microsoft.EntityFrameworkCore.InMemory согласно инструкциям выше.Use the preceding instructions to add the Microsoft.EntityFrameworkCore.InMemory NuGet package.

Диспетчер пакетов NuGet

Добавление контекста базы данных TodoContextAdd the TodoContext database context

  • Щелкните папку Models правой кнопкой мыши и выберите Добавить > Класс.Right-click the Models folder and select Add > Class. Назовите класс TodoContext и нажмите Добавить.Name the class TodoContext and click Add.
  • Введите следующий код:Enter the following code:

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Регистрация контекста базы данныхRegister the database context

В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей.In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. Контейнер предоставляет службу контроллерам.The container provides the service to controllers.

Обновите файл Startup.cs, используя следующий выделенный код:Update Startup.cs with the following highlighted code:

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
               opt.UseInMemoryDatabase("TodoList"));
            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

Предыдущий код:The preceding code:

  • Удалите неиспользуемые объявления using.Removes unused using declarations.
  • Добавляет контекст базы данных в контейнер внедрения зависимостей.Adds the database context to the DI container.
  • Указывает, что контекст базы данных будет использовать базу данных в памяти.Specifies that the database context will use an in-memory database.

Формирование шаблонов контроллераScaffold a controller

  • Щелкните папку Controllers правой кнопкой мыши.Right-click the Controllers folder.

  • Выберите Добавить > Создать шаблонный элемент.Select Add > New Scaffolded Item.

  • Выберите Контроллер API с действиями, использующий Entity Framework, а затем выберите Добавить.Select API Controller with actions, using Entity Framework, and then select Add.

  • В диалоговом окне Контроллер API с действиями, использующий Entity Framework сделайте следующее:In the Add API Controller with actions, using Entity Framework dialog:

    • Выберите TodoItem (TodoAPI.Models) в поле Класс модели.Select TodoItem (TodoAPI.Models) in the Model class.
    • Выберите TodoContext (TodoAPI.Models) в поле Класс контекста данных.Select TodoContext (TodoAPI.Models) in the Data context class.
    • Нажмите ДобавитьSelect Add

Сформированный код:The generated code:

  • Определяет класс контроллера API без методов.Defines an API controller class without methods.
  • Добавляет в класс атрибут [ApiController].Decorates the class with the [ApiController] attribute. Этот атрибут указывает, что контроллер отвечает на запросы веб-API.This attribute indicates that the controller responds to web API requests. Дополнительные сведения о поведении, которое реализует этот атрибут, см. в Создание веб-API с помощью ASP.NET Core.For information about specific behaviors that the attribute enables, see Создание веб-API с помощью ASP.NET Core.
  • Использует внедрение зависимостей для внедрения контекста базы данных (TodoContext) в контроллер.Uses DI to inject the database context (TodoContext) into the controller. Контекст базы данных используется в каждом методе создания, чтения, обновления и удаления в контроллере.The database context is used in each of the CRUD methods in the controller.

Знакомство с методом создания PostTodoItemExamine the PostTodoItem create method

Измените инструкцию возврата в PostTodoItem и используйте оператор nameof:Replace the return statement in the PostTodoItem to use the nameof operator:

// POST: api/TodoItems
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
    _context.TodoItems.Add(todoItem);
    await _context.SaveChangesAsync();

    //return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
    return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}

Предыдущий код является методом HTTP POST, как указывает атрибут [HttpPost].The preceding code is an HTTP POST method, as indicated by the [HttpPost] attribute. Этот метод получает значение элемента списка дел из текста HTTP-запроса.The method gets the value of the to-do item from the body of the HTTP request.

Метод CreatedAtAction:The CreatedAtAction method:

  • В случае успеха возвращает код состояния HTTP 201.Returns an HTTP 201 status code if successful. HTTP 201 представляет собой стандартный ответ для метода HTTP POST, создающий ресурс на сервере.HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.
  • Добавляет в ответ заголовок Location.Adds a Location header to the response. Заголовок Location указывает URI новой созданной задачи.The Location header specifies the URI of the newly created to-do item. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс".For more information, see 10.2.2 201 Created.
  • Указывает действие GetTodoItem для создания URI заголовка Location.References the GetTodoItem action to create the Location header's URI. Ключевое слово nameof C# используется для предотвращения жесткого программирования имени действия в вызове CreatedAtAction.The C# nameof keyword is used to avoid hard-coding the action name in the CreatedAtAction call.

Установка PostmanInstall Postman

В этом учебнике для тестирования веб-API используется Postman.This tutorial uses Postman to test the web API.

  • Установка PostmanInstall Postman
  • Запустите веб-приложение.Start the web app.
  • Запустите Postman.Start Postman.
  • Отключение параметра Проверка SSL-сертификатаDisable SSL certificate verification
  • В меню Файл > Параметры (вкладка *Общие) отключите параметр Проверка SSL-сертификата.From File > Settings (*General tab), disable SSL certificate verification.

    Предупреждение

    После тестирования контроллера снова включите проверку SSL-сертификата.Re-enable SSL certificate verification after testing the controller.

Тестирование PostTodoItem с использованием PostmanTest PostTodoItem with Postman

  • Создайте новый запрос.Create a new request.

  • Установите HTTP-метод POST.Set the HTTP method to POST.

  • Откройте вкладку Тело.Select the Body tab.

  • Установите переключатель без обработки.Select the raw radio button.

  • Задайте тип JSON (приложение/json) .Set the type to JSON (application/json).

  • В теле запроса введите код JSON для элемента списка дел:In the request body enter JSON for a to-do item:

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Нажмите кнопку Отправить.Select Send.

    Postman с запросом Create

Тестирование URI заголовка расположенияTest the location header URI

  • Перейдите на вкладку Заголовки в области Ответ.Select the Headers tab in the Response pane.

  • Скопируйте значение заголовка Расположение:Copy the Location header value:

    Вкладка "Заголовки" в консоли Postman

  • Укажите метод GET.Set the method to GET.

  • Вставьте URI (например, https://localhost:5001/api/TodoItems/1)Paste the URI (for example, https://localhost:5001/api/TodoItems/1)

  • Нажмите кнопку Отправить.Select Send.

Знакомство с методами GETExamine the GET methods

Эти методы реализуют две конечные точки GET:These methods implement two GET endpoints:

  • GET /api/TodoItems
  • GET /api/TodoItems/{id}

Протестируйте приложение, вызвав эти две конечные точки в браузере или в Postman.Test the app by calling the two endpoints from a browser or Postman. Например:For example:

При вызове GetTodoItems возвращается примерно такой ответ:A response similar to the following is produced by the call to GetTodoItems:

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Тестирование Get с использованием PostmanTest Get with Postman

  • Создайте новый запрос.Create a new request.
  • Укажите метод HTTP GET.Set the HTTP method to GET.
  • Укажите URL-адрес запроса https://localhost:<port>/api/TodoItems.Set the request URL to https://localhost:<port>/api/TodoItems. Например, https://localhost:5001/api/TodoItems.For example, https://localhost:5001/api/TodoItems.
  • Выберите режим Представление с двумя областями в Postman.Set Two pane view in Postman.
  • Нажмите кнопку Отправить.Select Send.

Это приложение использует выполняющуюся в памяти базу данных.This app uses an in-memory database. Если остановить и вновь запустить его, предшествующий запрос GET не возвратит никаких данных.If the app is stopped and started, the preceding GET request will not return any data. Если данные не возвращаются, данные для приложения получаются методом POST.If no data is returned, POST data to the app.

Маршрутизация и пути URLRouting and URL paths

Атрибут [HttpGet] обозначает метод, который отвечает на запрос HTTP GET.The [HttpGet] attribute denotes a method that responds to an HTTP GET request. Путь URL для каждого метода формируется следующим образом:The URL path for each method is constructed as follows:

  • Возьмите строку шаблона в атрибуте Route контроллера:Start with the template string in the controller's Route attribute:

    [Route("api/[controller]")]
    [ApiController]
    public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
    
        public TodoItemsController(TodoContext context)
        {
            _context = context;
        }
    
  • Замените [controller] именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller").Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. В этом примере класс контроллера имеет имя TodoItems, а сам контроллер, соответственно, — "TodoItems".For this sample, the controller class name is TodoItemsController, so the controller name is "TodoItems". В ASP.NET Core маршрутизация реализуется без учета регистра символов.ASP.NET Core routing is case insensitive.

  • Если атрибут [HttpGet] имеет шаблон маршрута (например, [HttpGet("products")]), добавьте его к пути.If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. В этом примере шаблон не используется.This sample doesn't use a template. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].For more information, see Attribute routing with Http[Verb] attributes.

В следующем методе GetTodoItem "{id}" — это переменная-заполнитель для уникального идентификатора элемента задачи.In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. При вызове GetTodoItem параметру метода id присваивается значение "{id}" в URL-адресе.When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in itsid parameter.

// GET: api/TodoItems/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Возвращаемые значенияReturn values

Возвращаемое значение имеет тип GetTodoItems, а метод GetTodoItem имеет тип ActionResult<T> type.The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. ASP.NET Core автоматически сериализует объект в формат JSON и записывает данные JSON в тело сообщения ответа.ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. Код ответа для этого типа возвращаемого значения равен 200, что свидетельствует об отсутствии необработанных исключений.The response code for this return type is 200, assuming there are no unhandled exceptions. Необработанные исключения преобразуются в ошибки 5xx.Unhandled exceptions are translated into 5xx errors.

Типы возвращаемых значений ActionResult могут представлять широкий спектр кодов состояний HTTP.ActionResult return types can represent a wide range of HTTP status codes. Например, метод GetTodoItem может возвращать два разных значения состояния:For example, GetTodoItem can return two different status values:

  • Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает ошибку 404 (Не найдено).If no item matches the requested ID, the method returns a 404 NotFound error code.
  • В противном случае метод возвращает код 200 с телом ответа JSON.Otherwise, the method returns 200 with a JSON response body. При возвращении item возвращается ответ HTTP 200.Returning item results in an HTTP 200 response.

Метод PutTodoItemThe PutTodoItem method

Проверьте метод PutTodoItem.Examine the PutTodoItem method:

// PUT: api/TodoItems/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
    if (id != todoItem.Id)
    {
        return BadRequest();
    }

    _context.Entry(todoItem).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!TodoItemExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return NoContent();
}

Страница PutTodoItem аналогична странице PostTodoItem, но использует запрос HTTP PUT.PutTodoItem is similar to PostTodoItem, except it uses HTTP PUT. Ответ — 204 (Нет содержимого).The response is 204 (No Content). Согласно спецификации HTTP, запрос PUT требует, чтобы клиент отправлял всю обновленную сущность, а не только изменения.According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. Чтобы обеспечить поддержку частичных обновлений, используйте HTTP PATCH.To support partial updates, use HTTP PATCH.

Если возникнет ошибка вызова PutTodoItem, вызовите GET, чтобы в базе данных был один элемент.If you get an error calling PutTodoItem, call GET to ensure there's an item in the database.

Тестирование метода PutTodoItemTest the PutTodoItem method

Этот пример использует базу данных в памяти, которая должна быть инициирована при каждом запуске приложения.This sample uses an in-memory database that must be initialed each time the app is started. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент.There must be an item in the database before you make a PUT call. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.Call GET to insure there's an item in the database before making a PUT call.

Обновите элемент списка дел с идентификатором 1 и присвойте ему имя "feed fish":Update the to-do item that has ID = 1 and set its name to "feed fish":

  {
    "ID":1,
    "name":"feed fish",
    "isComplete":true
  }

На следующем рисунке показан процесс обновления Postman:The following image shows the Postman update:

Консоль Postman с ответом 204 (Нет содержимого)

Метод DeleteTodoItemThe DeleteTodoItem method

Проверьте метод DeleteTodoItem.Examine the DeleteTodoItem method:

// DELETE: api/TodoItems/5
[HttpDelete("{id}")]
public async Task<ActionResult<TodoItem>> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);
    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return todoItem;
}

DeleteTodoItemОтвет — 204 (нет содержимого).The DeleteTodoItem response is 204 (No Content).

Тестирование метода DeleteTodoItemTest the DeleteTodoItem method

Удалите элемент списка дел с помощью Postman:Use Postman to delete a to-do item:

  • Укажите метод DELETE.Set the method to DELETE.
  • Укажите URI удаляемого объекта, например https://localhost:5001/api/TodoItems/1Set the URI of the object to delete, for example https://localhost:5001/api/TodoItems/1
  • Нажмите кнопку ОтправитьSelect Send

Вызов API из jQueryCall the API from jQuery

Пошаговые инструкции см. в руководстве Вызов веб-API ASP.NET Core с помощью jQuery.See Tutorial: Call an ASP.NET Core web API with jQuery.

В этом руководстве вы узнаете, как:In this tutorial, you learn how to:

  • Создание проекта веб-API.Create a web API project.
  • Добавление класса модели и контекста базы данных.Add a model class and a database context.
  • Добавление контроллера.Add a controller.
  • Добавление методов CRUD.Add CRUD methods.
  • Настройка маршрутизации и путей URL.Configure routing and URL paths.
  • Указание возвращаемых значений.Specify return values.
  • Вызов веб-API с помощью Postman.Call the web API with Postman.
  • Вызов веб-API с помощью jQuery.Call the web API with jQuery.

В конечном итоге вы получите веб-API, обеспечивающий управление элементами списка дел, хранящимися в реляционной базе данных.At the end, you have a web API that can manage "to-do" items stored in a relational database.

ОбзорOverview

В этом руководстве создается следующий API-интерфейс:This tutorial creates the following API:

APIAPI ОПИСАНИЕDescription Текст запросаRequest body Текст ответаResponse body
GET /api/TodoItemsGET /api/TodoItems Получение всех элементов задачGet all to-do items НетNone Массив элементов задачArray of to-do items
GET /api/TodoItems/{id}GET /api/TodoItems/{id} Получение объекта по идентификаторуGet an item by ID НетNone Элемент задачиTo-do item
POST /api/TodoItemsPOST /api/TodoItems Добавление нового элементаAdd a new item Элемент задачиTo-do item Элемент задачиTo-do item
PUT /api/TodoItems/{id}PUT /api/TodoItems/{id} Обновление существующего элемента  Update an existing item   Элемент задачиTo-do item НетNone
DELETE /api/TodoItems/{id}    DELETE /api/TodoItems/{id}     Удаление элемента    Delete an item     НетNone НетNone

На следующем рисунке показана структура приложения.The following diagram shows the design of the app.

Клиент представлен прямоугольником слева.

Предварительные требованияPrerequisites

Предупреждение

Если вы используете Visual Studio 2017, см. обсуждение dotnet/sdk issue #3124 для получения сведений о версиях пакета SDK для .NET Core, которые не работают с Visual Studio.If you use Visual Studio 2017, see dotnet/sdk issue #3124 for information about .NET Core SDK versions that don't work with Visual Studio.

Создайте веб-проект.Create a web project

  • В меню Файл выберите Создать > Проект.From the File menu, select New > Project.
  • Выберите шаблон Веб-приложение ASP.NET Core и нажмите Далее.Select the ASP.NET Core Web Application template and click Next.
  • Назовите проект TodoApi и нажмите Создать.Name the project TodoApi and click Create.
  • В диалоговом окне Создание веб-приложения ASP.NET Core убедитесь в том, что выбраны платформы .NET Core и ASP.NET Core 2.2.In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 2.2 are selected. Выберите шаблон API и нажмите кнопку Создать.Select the API template and click Create. Не выбирайте Включение поддержки Docker.Don't select Enable Docker Support.

Диалоговое окно создания проекта VS

Тестирование APITest the API

Шаблон проекта создает API values.The project template creates a values API. Вызовите метод Get из браузера для тестирования приложения.Call the Get method from a browser to test the app.

Нажмите клавиши CTRL+F5, чтобы запустить приложение.Press Ctrl+F5 to run the app. Visual Studio запустит браузер и перейдет к https://localhost:<port>/api/values, где <port> — это номер порта, выбранный случайным образом.Visual Studio launches a browser and navigates to https://localhost:<port>/api/values, where <port> is a randomly chosen port number.

Если появится диалоговое окно с запросом о необходимости доверять сертификату IIS Express, выберите Да.If you get a dialog box that asks if you should trust the IIS Express certificate, select Yes. В появляющемся следом диалоговом окне Предупреждение системы безопасности выберите Да.In the Security Warning dialog that appears next, select Yes.

Возвращается следующий файл JSON:The following JSON is returned:

["value1","value2"]

Добавление класса моделиAdd a model class

Модель — это набор классов, представляющих данные, которыми управляет приложение.A model is a set of classes that represent the data that the app manages. Модель этого приложения содержит единственный класс TodoItem.The model for this app is a single TodoItem class.

  • В обозревателе решений щелкните проект правой кнопкой мыши.In Solution Explorer, right-click the project. Выберите Добавить > Новая папка.Select Add > New Folder. Присвойте папке имя Models.Name the folder Models.

  • Щелкните папку Models правой кнопкой мыши и выберите Добавить > Класс.Right-click the Models folder and select Add > Class. Присвойте классу имя TodoItem и выберите Добавить.Name the class TodoItem and select Add.

  • Замените код шаблона следующим кодом:Replace the template code with the following code:

namespace TodoApi.Models
{
    public class TodoItem
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

Свойство Id выступает в качестве уникального ключа реляционной базы данных.The Id property functions as the unique key in a relational database.

Классы моделей можно размещать в любом месте проекта, но обычно для этого используется папка Models.Model classes can go anywhere in the project, but the Models folder is used by convention.

Добавление контекста базы данныхAdd a database context

Контекст базы данных —это основной класс, который координирует функциональные возможности Entity Framework для модели данных.The database context is the main class that coordinates Entity Framework functionality for a data model. Этот класс является производным от класса Microsoft.EntityFrameworkCore.DbContext.This class is created by deriving from the Microsoft.EntityFrameworkCore.DbContext class.

  • Щелкните папку Models правой кнопкой мыши и выберите Добавить > Класс.Right-click the Models folder and select Add > Class. Назовите класс TodoContext и нажмите Добавить.Name the class TodoContext and click Add.
  • Замените код шаблона следующим кодом:Replace the template code with the following code:

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

Регистрация контекста базы данныхRegister the database context

В ASP.NET Core службы (такие как контекст базы данных) должны быть зарегистрированы с помощью контейнера внедрения зависимостей.In ASP.NET Core, services such as the DB context must be registered with the dependency injection (DI) container. Контейнер предоставляет службу контроллерам.The container provides the service to controllers.

Обновите файл Startup.cs, используя следующий выделенный код:Update Startup.cs with the following highlighted code:

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the 
        //container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP 
        //request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for 
                // production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

Предыдущий код:The preceding code:

  • Удалите неиспользуемые объявления using.Removes unused using declarations.
  • Добавляет контекст базы данных в контейнер внедрения зависимостей.Adds the database context to the DI container.
  • Указывает, что контекст базы данных будет использовать базу данных в памяти.Specifies that the database context will use an in-memory database.

Добавление контроллераAdd a controller

  • Щелкните папку Controllers правой кнопкой мыши.Right-click the Controllers folder.

  • Выберите Добавить > Новый элемент.Select Add > New Item.

  • В диалоговом окне Добавить новый элемент выберите шаблон Класс контроллера API.In the Add New Item dialog, select the API Controller Class template.

  • Присвойте классу имя TodoController и выберите Добавить.Name the class TodoController, and select Add.

    Диалоговое окно добавления элемента с контроллером в поле поиска и выбранным контроллером веб-API

  • Замените код шаблона следующим кодом:Replace the template code with the following code:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using TodoApi.Models;
    
    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
            public TodoController(TodoContext context)
            {
                _context = context;
    
                if (_context.TodoItems.Count() == 0)
                {
                    // Create a new TodoItem if collection is empty,
                    // which means you can't delete all TodoItems.
                    _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                    _context.SaveChanges();
                }
            }
        }
    }
    

Предыдущий код:The preceding code:

  • Определяет класс контроллера API без методов.Defines an API controller class without methods.
  • Добавляет в класс атрибут [ApiController].Decorates the class with the [ApiController] attribute. Этот атрибут указывает, что контроллер отвечает на запросы веб-API.This attribute indicates that the controller responds to web API requests. Дополнительные сведения о поведении, которое реализует этот атрибут, см. в Создание веб-API с помощью ASP.NET Core.For information about specific behaviors that the attribute enables, see Создание веб-API с помощью ASP.NET Core.
  • Использует внедрение зависимостей для внедрения контекста базы данных (TodoContext) в контроллер.Uses DI to inject the database context (TodoContext) into the controller. Контекст базы данных используется в каждом методе создания, чтения, обновления и удаления в контроллере.The database context is used in each of the CRUD methods in the controller.
  • Добавляет элемент Item1 в базу данных, если она пуста.Adds an item named Item1 to the database if the database is empty. Этот код находится в конструкторе и выполняется каждый раз при обнаружении нового HTTP-запроса.This code is in the constructor, so it runs every time there's a new HTTP request. Если вы удалите все элементы, конструктор создаст Item1 при следующем вызове метода API.If you delete all items, the constructor creates Item1 again the next time an API method is called. Поэтому может создаться впечатление, что удаление не было выполнено, хотя это не так.So it may look like the deletion didn't work when it actually did work.

Добавление методов GetAdd Get methods

Чтобы получить API, который извлекает элементы списка дел, добавьте следующие методы в класс TodoController:To provide an API that retrieves to-do items, add the following methods to the TodoController class:

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Эти методы реализуют две конечные точки GET:These methods implement two GET endpoints:

  • GET /api/todo
  • GET /api/todo/{id}

Если приложение все еще выполняется, оно останавливается.Stop the app if it's still running. Затем оно запускается снова с последними изменениями.Then run it again to include the latest changes.

Протестируйте приложение, вызвав эти две конечные точки в браузере.Test the app by calling the two endpoints from a browser. Например:For example:

  • https://localhost:<port>/api/todo
  • https://localhost:<port>/api/todo/1

При вызове GetTodoItems возвращается следующий ответ HTTP:The following HTTP response is produced by the call to GetTodoItems:

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

Маршрутизация и пути URLRouting and URL paths

Атрибут [HttpGet] обозначает метод, который отвечает на запрос HTTP GET.The [HttpGet] attribute denotes a method that responds to an HTTP GET request. Путь URL для каждого метода формируется следующим образом:The URL path for each method is constructed as follows:

  • Возьмите строку шаблона в атрибуте Route контроллера:Start with the template string in the controller's Route attribute:

    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
  • Замените [controller] именем контроллера (по соглашению это имя класса контроллера без суффикса "Controller").Replace [controller] with the name of the controller, which by convention is the controller class name minus the "Controller" suffix. В этом примере класс контроллера носит имя Todo, а сам контроллер, соответственно, — "todo".For this sample, the controller class name is TodoController, so the controller name is "todo". В ASP.NET Core маршрутизация реализуется без учета регистра символов.ASP.NET Core routing is case insensitive.

  • Если атрибут [HttpGet] имеет шаблон маршрута (например, [HttpGet("products")]), добавьте его к пути.If the [HttpGet] attribute has a route template (for example, [HttpGet("products")]), append that to the path. В этом примере шаблон не используется.This sample doesn't use a template. Дополнительные сведения см. в разделе Маршрутизация атрибутов с помощью атрибутов Http[Verb].For more information, see Attribute routing with Http[Verb] attributes.

В следующем методе GetTodoItem "{id}" — это переменная-заполнитель для уникального идентификатора элемента задачи.In the following GetTodoItem method, "{id}" is a placeholder variable for the unique identifier of the to-do item. При вызове GetTodoItem параметру метода id присваивается значение "{id}" в URL-адресе.When GetTodoItem is invoked, the value of "{id}" in the URL is provided to the method in itsid parameter.

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

Возвращаемые значенияReturn values

Возвращаемое значение имеет тип GetTodoItems, а метод GetTodoItem имеет тип ActionResult<T> type.The return type of the GetTodoItems and GetTodoItem methods is ActionResult<T> type. ASP.NET Core автоматически сериализует объект в формат JSON и записывает данные JSON в тело сообщения ответа.ASP.NET Core automatically serializes the object to JSON and writes the JSON into the body of the response message. Код ответа для этого типа возвращаемого значения равен 200, что свидетельствует об отсутствии необработанных исключений.The response code for this return type is 200, assuming there are no unhandled exceptions. Необработанные исключения преобразуются в ошибки 5xx.Unhandled exceptions are translated into 5xx errors.

Типы возвращаемых значений ActionResult могут представлять широкий спектр кодов состояний HTTP.ActionResult return types can represent a wide range of HTTP status codes. Например, метод GetTodoItem может возвращать два разных значения состояния:For example, GetTodoItem can return two different status values:

  • Если запрошенному идентификатору не соответствует ни один элемент, метод возвращает ошибку 404 (Не найдено).If no item matches the requested ID, the method returns a 404 NotFound error code.
  • В противном случае метод возвращает код 200 с телом ответа JSON.Otherwise, the method returns 200 with a JSON response body. При возвращении item возвращается ответ HTTP 200.Returning item results in an HTTP 200 response.

Тестирование метода GetTodoItemsTest the GetTodoItems method

В этом учебнике для тестирования веб-API используется Postman.This tutorial uses Postman to test the web API.

  • Установка PostmanInstall Postman
  • Запустите веб-приложение.Start the web app.
  • Запустите Postman.Start Postman.
  • Отключение параметра Проверка SSL-сертификатаDisable SSL certificate verification
  • В меню Файл > Параметры (вкладка Общие) отключите параметр Проверка SSL-сертификата.From File > Settings (General tab), disable SSL certificate verification.

Предупреждение

После тестирования контроллера снова включите проверку SSL-сертификата.Re-enable SSL certificate verification after testing the controller.

  • Создайте новый запрос.Create a new request.
    • Укажите метод HTTP GET.Set the HTTP method to GET.
    • Укажите URL-адрес запроса https://localhost:<port>/api/todo.Set the request URL to https://localhost:<port>/api/todo. Например, https://localhost:5001/api/todo.For example, https://localhost:5001/api/todo.
  • Выберите режим Представление с двумя областями в Postman.Set Two pane view in Postman.
  • Нажмите кнопку Отправить.Select Send.

Postman с запросом Get

Добавление метода CreateAdd a Create method

Добавьте следующий метод PostTodoItem в Controllers/TodoController.cs:Add the following PostTodoItem method inside of Controllers/TodoController.cs:

// POST: api/Todo
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item);
}

Предыдущий код является методом HTTP POST, как указывает атрибут [HttpPost].The preceding code is an HTTP POST method, as indicated by the [HttpPost] attribute. Этот метод получает значение элемента списка дел из текста HTTP-запроса.The method gets the value of the to-do item from the body of the HTTP request.

Метод CreatedAtAction:The CreatedAtAction method:

  • В случае успеха возвращает код состояния HTTP 201.Returns an HTTP 201 status code, if successful. HTTP 201 представляет собой стандартный ответ для метода HTTP POST, создающий ресурс на сервере.HTTP 201 is the standard response for an HTTP POST method that creates a new resource on the server.

  • Добавляет заголовок Location в ответ.Adds a Location header to the response. Заголовок Location расположения указывает URI вновь созданной задачи.The Location header specifies the URI of the newly created to-do item. Дополнительные сведения см. в статье 10.2.2 201 "Создан ресурс".For more information, see 10.2.2 201 Created.

  • Указывает действие GetTodoItem для создания URI заголовка Location.References the GetTodoItem action to create the Location header's URI. Ключевое слово nameof C# используется для предотвращения жесткого программирования имени действия в вызове CreatedAtAction.The C# nameof keyword is used to avoid hard-coding the action name in the CreatedAtAction call.

    // GET: api/Todo/5
    [HttpGet("{id}")]
    public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
    {
        var todoItem = await _context.TodoItems.FindAsync(id);
    
        if (todoItem == null)
        {
            return NotFound();
        }
    
        return todoItem;
    }
    

Тестирование метода PostTodoItemTest the PostTodoItem method

  • Выполните построение проекта.Build the project.

  • В Postman укажите метод HTTP POST.In Postman, set the HTTP method to POST.

  • Откройте вкладку Тело.Select the Body tab.

  • Установите переключатель без обработки.Select the raw radio button.

  • Задайте тип JSON (приложение/json) .Set the type to JSON (application/json).

  • В теле запроса введите код JSON для элемента списка дел:In the request body enter JSON for a to-do item:

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • Нажмите кнопку Отправить.Select Send.

    Postman с запросом Create

    Если вы получаете ошибку 405 "Недопустимый метод", это может свидетельствовать о том, что после добавления метода PostTodoItem не была выполнена компиляция проекта.If you get a 405 Method Not Allowed error, it's probably the result of not compiling the project after adding the PostTodoItem method.

Тестирование URI заголовка расположенияTest the location header URI

  • Перейдите на вкладку Заголовки в области Ответ.Select the Headers tab in the Response pane.

  • Скопируйте значение заголовка Расположение:Copy the Location header value:

    Вкладка "Заголовки" в консоли Postman

  • Укажите метод GET.Set the method to GET.

  • Вставьте URI (например, https://localhost:5001/api/Todo/2)Paste the URI (for example, https://localhost:5001/api/Todo/2)

  • Нажмите кнопку Отправить.Select Send.

Добавление метода PutTodoItemAdd a PutTodoItem method

Добавьте приведенный ниже метод PutTodoItem.Add the following PutTodoItem method:

// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
    if (id != item.Id)
    {
        return BadRequest();
    }

    _context.Entry(item).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}

Страница PutTodoItem аналогична странице PostTodoItem, но использует запрос HTTP PUT.PutTodoItem is similar to PostTodoItem, except it uses HTTP PUT. Ответ — 204 (Нет содержимого).The response is 204 (No Content). Согласно спецификации HTTP, запрос PUT требует, чтобы клиент отправлял всю обновленную сущность, а не только изменения.According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. Чтобы обеспечить поддержку частичных обновлений, используйте HTTP PATCH.To support partial updates, use HTTP PATCH.

Если возникнет ошибка вызова PutTodoItem, вызовите GET, чтобы в базе данных был один элемент.If you get an error calling PutTodoItem, call GET to ensure there's an item in the database.

Тестирование метода PutTodoItemTest the PutTodoItem method

Этот пример использует базу данных в памяти, которая должна быть инициирована при каждом запуске приложения.This sample uses an in-memory database that must be initialed each time the app is started. При выполнении вызова PUT в базе данных уже должен существовать какой-либо элемент.There must be an item in the database before you make a PUT call. Для этого перед вызовом PUT выполните вызов GET, чтобы убедиться в наличии такого элемента в базе данных.Call GET to insure there's an item in the database before making a PUT call.

Обновите элемент списка дел с идентификатором = 1 и присвойте ему имя "feed fish":Update the to-do item that has id = 1 and set its name to "feed fish":

  {
    "ID":1,
    "name":"feed fish",
    "isComplete":true
  }

На следующем рисунке показан процесс обновления Postman:The following image shows the Postman update:

Консоль Postman с ответом 204 (Нет содержимого)

Добавление метода DeleteTodoItemAdd a DeleteTodoItem method

Добавьте приведенный ниже метод DeleteTodoItem.Add the following DeleteTodoItem method:

// DELETE: api/Todo/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    _context.TodoItems.Remove(todoItem);
    await _context.SaveChangesAsync();

    return NoContent();
}

DeleteTodoItemОтвет — 204 (нет содержимого).The DeleteTodoItem response is 204 (No Content).

Тестирование метода DeleteTodoItemTest the DeleteTodoItem method

Удалите элемент списка дел с помощью Postman:Use Postman to delete a to-do item:

  • Укажите метод DELETE.Set the method to DELETE.
  • Укажите URI удаляемого объекта, например https://localhost:5001/api/todo/1Set the URI of the object to delete, for example https://localhost:5001/api/todo/1
  • Нажмите кнопку ОтправитьSelect Send

В этом примере приложения вы можете удалить все элементы.The sample app allows you to delete all the items. Однако в случае удаления последнего элемента в момент следующего вызова API конструктор класса модели создаст новый элемент.However, when the last item is deleted, a new one is created by the model class constructor the next time the API is called.

Вызов API с помощью jQueryCall the API with jQuery

В этом разделе добавляется HTML-страница, которая использует jQuery для вызова веб-API.In this section, an HTML page is added that uses jQuery to call the web api. jQuery запускает запрос и вносит на страницу подробные сведения из ответа API.jQuery initiates the request and updates the page with the details from the API's response.

Настройте приложение для обслуживания статических файлов и включения сопоставления файлов по умолчанию, обновив Startup.cs следующим выделенным кодом:Configure the app to serve static files and enable default file mapping by updating Startup.cs with the following highlighted code:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        // The default HSTS value is 30 days. You may want to change this for 
        // production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    app.UseDefaultFiles();
    app.UseStaticFiles();
    app.UseHttpsRedirection();
    app.UseMvc();
}

Создайте папку wwwroot в каталоге проекта.Create a wwwroot folder in the project directory.

Добавьте HTML-файл index.html в каталог wwwroot.Add an HTML file named index.html to the wwwroot directory. Замените его содержимое следующей разметкой:Replace its contents with the following markup:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>To-do CRUD</title>
    <style>
        input[type='submit'], button, [aria-label] {
            cursor: pointer;
        }

        #spoiler {
            display: none;
        }

        table {
            font-family: Arial, sans-serif;
            border: 1px solid;
            border-collapse: collapse;
        }

        th {
            background-color: #0066CC;
            color: white;
        }

        td {
            border: 1px solid;
            padding: 5px;
        }
    </style>
</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="spoiler">
        <h3>Edit</h3>
        <form class="my-form">
            <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="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <script src="site.js"></script>
</body>
</html>

Добавьте файл JavaScript с именем site.js в каталог wwwroot.Add a JavaScript file named site.js to the wwwroot directory. Замените его содержимое следующим кодом:Replace its contents with the following code:

const uri = "api/todo";
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 = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").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: $("#edit-id").val()
  };

  $.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" });
}

Может потребоваться изменение параметров запуска проекта ASP.NET Core для локального тестирования HTML-страницы:A change to the ASP.NET Core project's launch settings may be required to test the HTML page locally:

  • Откройте файл Properties\launchSettings.json.Open Properties\launchSettings.json.
  • Удалите свойство launchUrl, чтобы приложение открылось через index.html — файл проекта по умолчанию.Remove the launchUrl property to force the app to open at index.html—the project's default file.

Для получения jQuery можно использовать следующие способы.There are several ways to get jQuery. В предыдущем фрагменте кода библиотека загружается из CDN.In the preceding snippet, the library is loaded from a CDN.

В этом примере вызываются все методы CRUD в API.This sample calls all of the CRUD methods of the API. Ниже приводится пояснение вызовов API.Following are explanations of the calls to the API.

Получение списка элементов задачGet a list of to-do items

Функция jQuery ajax отправляет запрос GET к API, который возвращает JSON, представляющий массив элементов списка дел.The jQuery ajax function sends a GET request to the API, which returns JSON representing an array of to-do items. В случае успешного запроса используется функция обратного вызова success.The success callback function is invoked if the request succeeds. При обратном вызове в модель DOM вносятся данные о задачах.In the callback, the DOM is updated with the to-do information.

$(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 = $("<tr></tr>")
          .append(
            $("<td></td>").append(
              $("<input/>", {
                type: "checkbox",
                disabled: true,
                checked: item.isComplete
              })
            )
          )
          .append($("<td></td>").text(item.name))
          .append(
            $("<td></td>").append(
              $("<button>Edit</button>").on("click", function() {
                editItem(item.id);
              })
            )
          )
          .append(
            $("<td></td>").append(
              $("<button>Delete</button>").on("click", function() {
                deleteItem(item.id);
              })
            )
          );

        tr.appendTo(tBody);
      });

      todos = data;
    }
  });
}

Добавление элемента задачиAdd a to-do item

Функция ajax отправляет запрос POST с элементом списка дел в теле запроса.The ajax function sends a POST request with the to-do item in the request body. Для параметров accepts и contentType указывается application/json, чтобы указать тип носителя при получении и отправке.The accepts and contentType options are set to application/json to specify the media type being received and sent. Элемент списка дел преобразуется в JSON с помощью JSON.stringify.The to-do item is converted to JSON by using JSON.stringify. Если интерфейс API возвращает код состояния успешного выполнения, вызывается функция getData для обновления HTML-таблицы.When the API returns a successful status code, the getData function is invoked to update the HTML table.

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("");
    }
  });
}

Обновление элемента задачиUpdate a to-do item

Обновление элемента списка дел выполняется аналогично его добавлению.Updating a to-do item is similar to adding one. url изменяется, чтобы добавить уникальный идентификатор для элемента, а в качестве type устанавливается PUT.The url changes to add the unique identifier of the item, and the type is PUT.

$.ajax({
  url: uri + "/" + $("#edit-id").val(),
  type: "PUT",
  accepts: "application/json",
  contentType: "application/json",
  data: JSON.stringify(item),
  success: function(result) {
    getData();
  }
});

Удаление элемента задачиDelete a to-do item

Чтобы удалить элемент списка дел, установите для type в вызове AJAX значение DELETE и укажите уникальный идентификатор элемента в URL-адресе.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.

$.ajax({
  url: uri + "/" + id,
  type: "DELETE",
  success: function(result) {
    getData();
  }
});

Дополнительные ресурсыAdditional resources

Просмотреть или скачать пример кода для этого учебника.View or download sample code for this tutorial. См. раздел Практическое руководство. Скачивание файла.See how to download.

Дополнительные сведения см. в следующих ресурсах:For more information, see the following resources: