можно чистыми. Есть action, который принимает id и возвращает документ. Единственное что делает контроллер, это вызывает EntityService.GenerateDoc(id); Но что делать, если такого id не существует? Пока рассматривал следующие варианты:
1) Возвращать null. Это дает абсолютно ноль информации вызывающему методу о том, что действительно произошло(id нет или проблема возникла с генерацией документа).
2) Кидать exception. Решает проблему первого варианта, но логически не стыкуется. Ситуация не критичная(not exceptional), зачем тогда exception кидать. Еще возможно perf будет страдать.
3) Поменять сигнатуру сервиса и принимать сам объект, а не id. Контроллер берет на себя слишком много ответственности. Возможно со временем разрастется еще больше.
4) Возвращать из сервиса result объект. С таким никогда не работал, так что не знаю, надо ли с этим заморачиваться. Ведь тогда предпочтительнее везде result использовать.
Какие еще есть варианты обработки не критических ошибок в приложении? Если выбирать из описанных выше вариантов, то что предпочтительнее?
Если в нормальной работе сервиса не ожидаются несуществующие ID, то не вижу ничего дурного кидать исключение.
Во флудильне на днях обсуждали Как вариант, возвращать 422.
Кидай просто BadRequest
Это понятно, что контроллер должен вернуть http код. Я понять не могу, что сам сервис должен возвращать в таком случае.
kidai httperror. badrequest priamo iz service
А Если несколько вариантов, почему не удалось так сделать, то я бы кидал исключение
Я вот на этот вопрос и ищу ответ. То есть сервис обращаясь к бд проверяет есть ли такая запись. Если ее нет, та какие действия предпочтительнее принять?
А как часто такие обращения идут? )
А если это сторонни й сервис, который не только в asp.net core используется?
Я за исключения, потому что сервис не может сам решить что делать в этой ситуации
По хорошему конечно никогда, но frontend'у доверять не стоит.
На вкус и цвет все фломастеры разные. Если в проекте есть nullable reference - можно null, если нет или не хочется null, то исключения. Да, перф там не без оверхеда, но задача не вычислительная, и кидаются исключения не в промышленных масштабах
Ну значит исключение )
Какая разница? IActionResult Это просто интерфейс. Клиент получит ошибку или результат. Для результата возвращай return Ok(result), а если ошибка то return BadRequest()
Есть довольно популярная имплементация realworld.io с CQRS и MediatR'ом, там в хэндлере (условно говоря твой сервис) кидается RestException https://github.com/gothinkster/aspnetcore-realworld-example-app/blob/94e4616f8ecd48d5f42cd33f2bb0caac7a14417c/src/Conduit/Features/Articles/Details.cs#L40 По поводу перформанса хз, как-то пытался найти бэнчмарки, да так и не нашёл. Если у кого-то есть, дайте ссыль
Вы предлагает потом всем проектам, даже не asp.net, тащить в зависимости asp потом?
Зачем тащить то? Есть rest api, какая разница, что он возращает. Клиенту фиолетово
Внимательнее вопрос посмотрите. Есть ASP.NET API, контроллер которого использует класс-сервис. Вопрос не что должно делать API, а что должен делать этот сервис-класс, который потом может быть использован вне ASP
Ну значит я неправильно понял вопрос. Мне показалось, что нужно правильно обработать ошибку в контроллере.
Отвечая на вопрос, большинство сошлось, что кидать exception неплохое решение. Но что по поводу четвертого варианта, какие у него проблемы? Потому что смотрится хорошо: дает достаточно информации контроллеру, чтобы сформировать правильный ответ, но не имеет проблем с производительностью.
Так ты через RestException тоже можешь нормальный ответ передать. Бойлерплейта меньше, чем result тащить откуда-то возможно издалека
Ну тащить вроде не кажется проблемой, пока проект не большой. Не идиоматично выходит, но звучит вроде нормально.
Проблема с производительностью преувеличена. Там оверхед будет на порядки меньше чем то же обращение в базу. Если НАСТОЛЬКО не хочется - есть паттерн TrySomething()
Да, проблемы действительно нет. Но вопрос все-таки был про вариант с возвращение result объекта, который, как мне показалось, все упустили из виду. Хотел узнать причину. А так решение уже принято, будет кидаться исключение.
Потому что зачем целый Result object, когда достаточно bool или null? =)
Ты можешь вернуть result через RestException, типа throw new RestException(HttpStatusCode.NotFound, new { /* тут объект, который будет сконверчен в json и отдан на клиент */ }); Контроллер сам захэндлит эксепшен если что
Ну такой result будет бесполезным. Но если добавить поле errors или взять готовую библиотеку, реализующую этот паттерн, то это даст куда больше полезной информации, чем bool.
А стоит ли в сервисе завязываться на rest api?
Это уже лишние. Result и exception тут делают одну и ту же задачу - передают информацию об ошибке. Тут логичней выбрать что-то одно.
И тем самым заменить общепринятый механизм исключений на что-то собственного изобретения? Не вижу смысла. Если произошло то, чего не ожидалось - это исключение
Не согласен. Отсутствие ресурса, который запросил пользователь, - обыденное дело. В любом случае, это уже спор предпочтений, так что считаю вопрос закрытым.
null, потому что у него семантика "Значение отсутствует" и Nullable reference чтобы не подорваться на NRE. Ну, как хотите, закрыт так закрыт ¯\_(ツ)_/¯
Смотря что за сервис. Если это сервис который разгружает контроллер (как в вопросе), то вполне можно Но вообще нет
Я делаю три варианта ошибок. Делаю на аппликейшн, лоджик и валидейшн. Аппликейшн это значит отвалился третий сервис (бд, апиха сторонняя, и ТД) показываем попап с ошибкой Лоджик это значит по логике энтити не может принять тот или иной стейт, тот же попап но с большей подробностью для юзера Ну и валидацию, просто словарь привязанный к полям формы Ещё есть NotFoundException, кидаю когда ничего не приходит из дал по запросу. На уровне апи я ловлю их в мидлваре и оборачиваю в 400 первые три экзепшена с типом для фронта и в 404 последний. Нюансов много ещё есть, но в целом я думаю картина ясна
Можно возвращать null, если это метод только на чтение, в твоем случае не понятно что он даст Эксепшен можно кинуть на любом уровне абстракции, что довольно удобно, а обрабатывать эксепшены где-то в мидлварях, тем самым не засоряя код контроллера. Я бы выбрал этот вариант. Result вариант неплохой, но тебе придется тащить его по всему коду на все слои, чтобы иметь возможность из них всегда вернуть ошибку, кроме того по всему коду у тебя будут везде размазаны проверки иф резалт=саксес что тоже не слишком красиво.
Обсуждают сегодня