У меня возникла потребность для 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, где содержится намного больше деталей описанного выше процесса.