У меня возникла потребность для HttpGet
запроса проверять, что в качестве QueryString
параметра запроса прислан не просто какой-то там string
, а что присланое значение успешно преобразуется к перечислению Enum
вида:
1 | public enum QrCodeTypeEnum |
Причём если QueryString
параметр “левый”, или вообще не прислан, то не должно самопроизвольно выбираться дефолтное значение перечисления QrCodeTypeEnum.Location
как при обычном [FromQuery]
аттрибуте (тут даже аттрибут [BindRequired]
не поможет).
Для решения данной задачи потребовалось расширить возможности FromQueryAttribute
и реализовать интерфейс IParameterModelConvention
, который обязует имплементировать метод void Apply(ParameterModel parameter)
.
Вот как я это сделал:
1 | using System; |
При инициализации контроллера, содержащего наш атрибут [RequiredFromQuery]
, происходит вызов метода Apply
, который понимает, что аттрибут применён к перечислению, благодаря свойству parameter.ParameterType.IsEnum
, и формирует предикат, который передаётся конструктору RequiredFromQueryActionConstraint
и будет использован при поступлении запроса в контроллер для проверки поступающего значения в QueryString
.
Давайте взглянем как реализован класс RequiredFromQueryActionConstraint
, который имплементирует интерфейс IActionConstraint
:
1 | using System; |
При поступлении HttpGet
запроса вида /v3/device/download-report?type=device
к контроллеру device
, вызывается метод Accept
класса RequiredFromQueryActionConstraint
, который проверяет наличие ключа type
, наличие значения у этого ключа, и что значение ключа соответствует предикату _rejectionPredicate
, который формируется из значений перечисления в методе Apply
атрибута RequiredFromQueryAttribute
. Теперь проверка QueryString
параметра запроса осуществляется строго, и в случае отсутствия ключа type
, либо неверного (отсутствующего в перечислении) значения ключа type
методом будет дан ответ с кодом 400 и сообщением вида:
1 | { |
Использовать атрибут [RequiredFromQuery]
можно в методе контроллера следующим образом:
1 | [ ] |
При решении данной задачи я опирался на статью Required query string parameters in ASP.NET Core MVC, где содержится намного больше деталей описанного выше процесса.