Создание клиента для WEB API

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 30.12.2019

Продолжим работу с проектом из прошлой теме. В ней был создан и протестирован контроллер UsersController. Теперь создадим для него визуальную часть, которая будет представлять веб-страницу. То есть из веб-страницы мы будем отправлять запросы к контроллеру и обрабатывать ответ от контроллера.

Для создания веб-клиента добавим в проект папку wwwroot и затем в ней определим новый элемент HTML Page, который назовем "index.html":

Добавление веб-страницы в ASP NET Core Web API

Затем изменим класс Startup:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using WebAPIApp.Models;

namespace WebAPIApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            string con = "Server=(localdb)\\mssqllocaldb;Database=usersdbstore;Trusted_Connection=True;";
            // устанавливаем контекст данных
            services.AddDbContext<UsersContext>(options => options.UseSqlServer(con));
            services.AddControllers(); // используем контроллеры без представлений
        }

        public void Configure(IApplicationBuilder app)
        {
            app.UseDeveloperExceptionPage();

            app.UseDefaultFiles();
            app.UseStaticFiles();

            app.UseRouting();

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

Здесь в метод Configure() были добавлены два вызова для работы со статическими файлами:

app.UseDefaultFiles();
app.UseStaticFiles();

Благодаря этому мы сможем обратиться напрямую к веб-странице, например, по пути http://localhost:xxxx/index.html. Для этого изменим файл index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Список пользователей</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
    <h2>Список пользователей</h2>
    <form name="userForm">
        <input type="hidden" name="id" value="0" />
        <div class="form-group col-md-5">
            <label for="name">Имя:</label>
            <input class="form-control" name="name" />
        </div>
        <div class="form-group col-md-5">
            <label for="age">Возраст:</label>
            <input class="form-control" name="age" type="number" />
        </div>
        <div class="panel-body">
            <button type="submit" id="submit" class="btn btn-primary">Сохранить</button>
            <a id="reset" class="btn btn-primary">Сбросить</a>
        </div>
    </form>
    <table class="table table-condensed table-striped  col-md-6">
        <thead><tr><th>Id</th><th>Имя</th><th>возраст</th><th></th></tr></thead>
        <tbody>
        </tbody>
    </table>
    <div>2019 © Metanit.com</div>
    <script>
        // Получение всех пользователей
        async function GetUsers() {
            // отправляет запрос и получаем ответ
            const response = await fetch("/api/users", {
                method: "GET",
                headers: { "Accept": "application/json" }
            });
            // если запрос прошел нормально
            if (response.ok === true) {
                // получаем данные
                const users = await response.json();
                let rows = document.querySelector("tbody"); 
                users.forEach(user => {
                    // добавляем полученные элементы в таблицу
                    rows.append(row(user));
                });
            }
        }
        // Получение одного пользователя
        async function GetUser(id) {
            const response = await fetch("/api/users/" + id, {
                method: "GET",
                headers: { "Accept": "application/json" }
            });
            if (response.ok === true) {
                const user = await response.json();
                const form = document.forms["userForm"];
                form.elements["id"].value = user.id;
                form.elements["name"].value = user.name;
                form.elements["age"].value = user.age;
            }
        }
        // Добавление пользователя
        async function CreateUser(userName, userAge) {

            const response = await fetch("api/users", {
                method: "POST",
                headers: { "Accept": "application/json", "Content-Type": "application/json" },
                body: JSON.stringify({
                    name: userName,
                    age: parseInt(userAge, 10)
                })
            });
            if (response.ok === true) {
                const user = await response.json();
                reset();
                document.querySelector("tbody").append(row(user));
            }
        }
        // Изменение пользователя
        async function EditUser(userId, userName, userAge) {
            const response = await fetch("api/users", {
                method: "PUT",
                headers: { "Accept": "application/json", "Content-Type": "application/json" },
                body: JSON.stringify({
                    id: parseInt(userId, 10),
                    name: userName,
                    age: parseInt(userAge, 10)
                })
            });
            if (response.ok === true) {
                const user = await response.json();
                reset();
                document.querySelector("tr[data-rowid='" + user.id + "']").replaceWith(row(user));
            }
        }
        // Удаление пользователя
        async function DeleteUser(id) {
            const response = await fetch("/api/users/" + id, {
                method: "DELETE",
                headers: { "Accept": "application/json" }
            });
            if (response.ok === true) {
                const user = await response.json();
                document.querySelector("tr[data-rowid='" + user.id + "']").remove();
            }
        }

        // сброс формы
        function reset() {
            const form = document.forms["userForm"];
            form.reset();
            form.elements["id"].value = 0;
        }
        // создание строки для таблицы
        function row(user) {

            const tr = document.createElement("tr");
            tr.setAttribute("data-rowid", user.id);

            const idTd = document.createElement("td");
            idTd.append(user.id);
            tr.append(idTd);

            const nameTd = document.createElement("td");
            nameTd.append(user.name);
            tr.append(nameTd);

            const ageTd = document.createElement("td");
            ageTd.append(user.age);
            tr.append(ageTd);
            
            const linksTd = document.createElement("td");

            const editLink = document.createElement("a");
            editLink.setAttribute("data-id", user.id);
            editLink.setAttribute("style", "cursor:pointer;padding:15px;");
            editLink.append("Изменить");
            editLink.addEventListener("click", e => {

                e.preventDefault();
                GetUser(user.id);
            });
            linksTd.append(editLink);

            const removeLink = document.createElement("a");
            removeLink.setAttribute("data-id", user.id);
            removeLink.setAttribute("style", "cursor:pointer;padding:15px;");
            removeLink.append("Удалить");
            removeLink.addEventListener("click", e => {

                e.preventDefault();
                DeleteUser(user.id);
            });

            linksTd.append(removeLink);
            tr.appendChild(linksTd);

            return tr;
        }
        // сброс значений формы
        document.getElementById("reset").click(function (e) {

            e.preventDefault();
            reset();
        })

        // отправка формы
        document.forms["userForm"].addEventListener("submit", e => {
            e.preventDefault();
            const form = document.forms["userForm"];
            const id = form.elements["id"].value;
            const name = form.elements["name"].value;
            const age = form.elements["age"].value;
            if (id == 0)
                CreateUser(name, age);
            else
                EditUser(id, name, age);
        });

        // загрузка пользователей
        GetUsers();

    </script>
</body>
</html>

Основная логика здесь заключена в коде javascript. При загрузке страницы в браузере получаем все объекты из БД с помощью функции GetUsers:

async function GetUsers() {
	const response = await fetch("/api/users", {
		method: "GET",
		headers: { "Accept": "application/json" }
	});
	if (response.ok === true) {
		const users = await response.json();
		let rows = document.querySelector("tbody"); 
		users.forEach(user => {
			rows.append(row(user));
		});
	}
}

Для добавления строк в таблицу используется функция row(), которая возвращает строку. В этой строке будут определены ссылки для изменения и удаления пользователя.

Ссылка для изменения пользователя с помощью функции GetUser() получает с сервера выделенного пользователя:

async function GetUser(id) {
	const response = await fetch("/api/users/" + id, {
		method: "GET",
		headers: { "Accept": "application/json" }
	});
	if (response.ok === true) {
		const user = await response.json();
		const form = document.forms["userForm"];
		form.elements["id"].value = user.id;
		form.elements["name"].value = user.name;
		form.elements["age"].value = user.age;
	}
}

И выделенный пользователь добавляется в форму над таблицей. Эта же форма применяется и для добавления объекта. С помощью скрытого поля, которое хранит id пользователя, мы можем узнать, какое действие выполняется - добавление или редактирование. Если id равен 0, то выполняется функция CreateUser, которая отправляет данные в POST-запросе:

async function CreateUser(userName, userAge) {

	const response = await fetch("api/users", {
		method: "POST",
		headers: { "Accept": "application/json", "Content-Type": "application/json" },
		body: JSON.stringify({
			name: userName,
			age: parseInt(userAge, 10)
		})
	});
	if (response.ok === true) {
		const user = await response.json();
		reset();
		document.querySelector("tbody").append(row(user));
	}
}

Если же ранее пользователь был загружен на форму, и в скрытом поле сохранился его id, то выполняется функция EditUser, которая отправляет PUT-запрос:

async function EditUser(userId, userName, userAge) {
	const response = await fetch("api/users", {
		method: "PUT",
		headers: { "Accept": "application/json", "Content-Type": "application/json" },
		body: JSON.stringify({
			id: parseInt(userId, 10),
			name: userName,
			age: parseInt(userAge, 10)
		})
	});
	if (response.ok === true) {
		const user = await response.json();
		reset();
		document.querySelector("tr[data-rowid='" + user.id + "']").replaceWith(row(user));
	}
}

При нажатии на ссылку "Удалить" выполняется DELETE-запрос, который по id удаляет пользователя.

Представление для ASP.NET Core Web API
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850