ЛР1: как показать работу на защите
Короткая шпаргалка на сам момент защиты — что запустить и что показать, без теории (она в ЛР1: UserService — gRPC, PostgreSQL и слоистая архитектура на троих).
Поднять окружение
docker compose up -d
dotnet build
dotnet run --project UserService
Сервис слушает localhost:5002. Reflection не подключён — grpcurl и Postman должны явно знать про UserService/Protos/user-service.proto.
Способ 1 — grpcurl (быстрее, без интерфейса)
Из папки UserService/:
grpcurl -plaintext -proto Protos/user-service.proto \
-d '{"login":"user1","password":"pass1234","name":"Ivan","surname":"Petrov","age":25}' \
localhost:5002 userService.UserService/CreateUser
Способ 2 — Postman
Postman умеет gRPC, но без reflection ему тоже нужен .proto руками:
- New → gRPC Request, адрес
localhost:5002,Use plaintextвключить (TLS не настроен). - Вкладка Service definition → Import a .proto file → указать
UserService/Protos/user-service.proto. - В выпадающем списке методов появятся все 5 rpc — выбираешь метод, слева пишешь JSON тела запроса (как в примерах ниже), Invoke.
Сценарий показа — happy path по всем 5 методам
Прогнать по порядку, посмотреть результат каждого — этого достаточно, чтобы продемонстрировать всё ТЗ разом.
1. CreateUser — заводим первого пользователя:
{"login":"user1","password":"pass1234","name":"Ivan","surname":"Petrov","age":25}
Ответ: {"id":1,"login":"user1","name":"Ivan","surname":"Petrov","age":25} — обратить внимание, что password в ответе нет, это осознанное решение ([MapperIgnoreSource] в мапперe), а не забытое поле.
2. CreateUser — второй пользователь, id пригодится для DeleteUser ниже:
{"login":"user2","password":"pass5678","name":"Anna","surname":"Sidorova","age":30}
3. GetUserById — {"id":1} → возвращает user1 целиком.
4. GetUserByName — {"name":"Ivan","surname":"Petrov"} → {"users":[{...}]}, список, даже когда совпадение одно (по контракту — всегда массив, не одиночный объект).
5. UpdateUser — меняем всё, кроме id и login (login в запросе нет вообще):
{"id":1,"password":"newpass1","name":"Ivan","surname":"Ivanov","age":26}
Ответ содержит прежний login: "user1" — если спросят "а почему он не изменился" — потому что UpdateUser по ТЗ не имеет права его менять, и в .proto для этого метода поля login физически нет.
6. DeleteUser — {"id":2} → пустой ответ {}, значит удаление прошло.
Сценарий показа — три вида ошибок
Если время на защите позволяет, эти три вызова наглядно показывают, что валидация и обработка ошибок не только "для галочки":
Дубликат login (регистр другой специально — проверка регистронезависимости):
{"login":"USER1","password":"x","name":"Someone","surname":"Else","age":40}
→ Code: AlreadyExists, Message: User with login 'USER1' already exists.
Невалидный возраст:
{"login":"user3","password":"x","name":"A","surname":"B","age":150}
→ Code: InvalidArgument, Message: 'Age' must be between 1 and 120. You entered 150.
Несуществующий id (GetUserById с {"id":999}):
→ Code: NotFound, Message: User with id '999' was not found.
Если что-то пошло не так во время демо
Address already in useприdotnet run— старый процесс сервиса не остановился с прошлого раза:pkill -f UserServiceи запустить заново.- Правка в
Database/*.sqlне подхватилась — Postgres накатывает эти скрипты только при первом старте контейнера на пустом volume.docker compose down -v(обязательно с-v), затемdocker compose up -dзаново. - Нужны чистые данные перед показом (без мусора от прошлых прогонов) — не обязательно
down -v, достаточноdocker exec user-service-postgres psql -U user_service -d user_service -c "TRUNCATE TABLE users RESTART IDENTITY;".