Перейти к основному содержимому

Практикум WPF — сервер ASP.NET Core Web API

Разработчику Архитектору

Практикум, шаг 3 из 6. Поднимаем TaskDesk.Api — REST-сервер для десктоп-клиента. Базовый цикл ASP.NET — Первая программа на ASP.NET Core; Minimal API — Minimal API и OpenAPI; REST — REST.


Контракт API

Ресурс — задача (Task). Базовый префикс /api/v1/tasks.

МетодURLТелоОтвет
GET/api/v1/tasks200 массив TaskDto
GET/api/v1/tasks/{id}200 или 404
POST/api/v1/tasks{ "title", "status" }201 + Location
PUT/api/v1/tasks/{id}полный TaskDto200 или 404
DELETE/api/v1/tasks/{id}204 или 404

Фильтр (опционально): GET /api/v1/tasks?status=Todo.


Структура проекта

mkdir TaskDesk
cd TaskDesk
dotnet new sln -n TaskDesk
dotnet new webapi -n TaskDesk.Api -o src/TaskDesk.Api --use-controllers
dotnet new classlib -n TaskDesk.Core -o src/TaskDesk.Core
dotnet sln add src/TaskDesk.Api src/TaskDesk.Core
dotnet add src/TaskDesk.Api reference src/TaskDesk.Core
TaskDesk/
├── TaskDesk.sln
└── src/
├── TaskDesk.Api/
│ ├── Program.cs
│ ├── Controllers/TasksController.cs
│ └── Services/InMemoryTaskStore.cs
└── TaskDesk.Core/
├── Models/TaskItem.cs
└── Contracts/TaskDto.cs

DTO — контракт JSON

namespace TaskDesk.Core.Contracts;

public record TaskDto(
Guid Id,
string Title,
string Status,
DateTimeOffset CreatedAt);

public record CreateTaskRequest(string Title, string Status = "Todo");

public record UpdateTaskRequest(string Title, string Status);

DTO отделены от доменной модели — клиент WPF и тесты завязаны на стабильный JSON, а не на внутренние классы сервера.


Хранилище и DI

Код ITЗагрузка примера кода…

Регистрация в Program.cs:

builder.Services.AddSingleton<ITaskStore, InMemoryTaskStore>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

Для учебного проекта достаточно памяти; прод-вариант — EF Core + SQLite (Приложение с S3, PostgreSQL и ASP.NET Core Web API).


Контроллер REST

Код ITЗагрузка примера кода…


Program.cs — pipeline, Swagger, CORS

Десктоп-клиент на другом origin (или localhost с другим портом) требует CORS:

Код ITЗагрузка примера кода…

CORS и нативный WPF

WPF-приложение не является браузеромHttpClient не применяет CORS так же, как Chrome. Политика CORS нужна, если клиент ходит через WebView или вы тестируете из Swagger/браузера. Для чистого HttpClient из WPF достаточно корректного URL и TLS; CORS оставляем для единообразия с веб-инструментами и будущим Blazor Hybrid.

Запуск:

cd src/TaskDesk.Api
dotnet run --urls http://localhost:5100

Swagger UI: http://localhost:5100/swagger.


Проверка вручную

curl -X GET http://localhost:5100/api/v1/tasks
curl -X POST http://localhost:5100/api/v1/tasks `
-H "Content-Type: application/json" `
-d "{\"title\":\"Настроить Prism\"}"

Ожидаем 201 и JSON с id.


Ошибки и коды

КодКогда
400Пустой заголовок, неверный enum статуса
404Нет задачи с таким id
500Необработанное исключение — логируем, клиенту краткий JSON

Единый формат ошибки упрощает отображение в WPF (ErrorMessage в ViewModel).


Чек-лист шага 3

  • API отвечает на GET и POST /api/v1/tasks.
  • Swagger открывается в Development.
  • DTO в TaskDesk.Core совпадают с тем, что ожидает клиент.
  • Сервис зарегистрирован через DI.

Дальше: Клиент WPF на Prism.