Проверка модели — Почему ModelState .isValid всегда возвращает true, даже если значения не указаны?

#c# #.net #asp.net-web-api #asp.net-mvc-5 #asp.net-web-api2

#c# #.net #asp.net-web-api #asp.net-mvc-5 #asp.net-web-api2

Вопрос:

Это касается WEBAPI , и ниже приведен мой класс модели.

     public class Request
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [Required]
        public Gender Gender { get; set; }
    }
  

И моя функция контроллера (POST)

 public class Values1Controller : ApiController
    {
        public IHttpActionResult Post([FromBody] Models.Request request)
        {
            if (!ModelState.IsValid)
            {
               return BadRequest();
            }
            var gender = request.Gender;
            var id = request.Id;
            var name = request.Name;
            // do some operations!
            return Ok();
        }
    }
  

И xml, который я отправляю вместе с каждым запросом.

 <Request xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
                xmlns="http://schemas.datacontract.org/2004/07/webapi1.Models">
  <id>1</id>
  <name>testName</name>      
</Request>
  

В приведенных выше данных XML post я вообще не указываю значение для Gender , которые помечены как [required] .

Но ModelState.IsValid возвращает значение true, даже если в приведенном выше XML не указано значение Gender .

Как запретить WebAPI присваивать значения по умолчанию перечислению в модели?

Есть идеи, почему?

Комментарии:

1. Вы проверили, что ваша модель (запрос) не равна null, так как это приведет к тому, что значение isValid будет равно true?

2. Модель не равна нулю, но перечислению gender присваивается значение по умолчанию.

3. Я не могу воспроизвести вашу проблему, что вы используете для публикации данных? Когда я отправляю данные (используя Chrome addin Postman), значения, которые не указаны, равны нулю, и в результате моя модель недействительна.

4. @DavidMartin: Я обновил свой вопрос. Пожалуйста, посмотрите

Ответ №1:

Я не знаю, почему ваша модель действительна, если вы не указываете пол, но вы можете сделать так, чтобы это значение не имело значения по умолчанию, определив значение Gender как обнуляемое следующим образом:

 public class Request
{
    public int id { get; set; }

    public string Name { get; set; }

    [Required]
    public Gender? Gender { get; set; }
}
  

В качестве альтернативы вы можете указать значение по умолчанию для gender следующим образом:

 public enum Gender
{
    Unknown = 0,
    Male,
    Female
} 
  

Обновить
Теперь я вижу разницу между нашими результатами, снова используя Postman, если я отправляю необработанный запрос в формате xml:

Заголовок: текст типа содержимого / xml

 <Request xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://schemas.datacontract.org/2004/07/webapi1.Models">
    <id>1</id>
    <Name>testName</Name>      
</Request>
  

Моя модель действительна, однако, если я отправлю данные в формате x-www-form-urlencoded:

Заголовок: приложение типа содержимого/x-www-form-urlencoded

 id=1,Name=testname
  

Тогда моя модель недействительна, даже если тип значения имеет значение, мой modelstate сообщает мне, что требуется свойство Gender .

Поскольку x-www-form-urlencoded является частью строки запроса, я предполагаю, что MVC может определить, что значение отсутствует, но когда данные представляются в виде простого xml, он не может это определить.

Я полагаю, что если вы хотите, чтобы требуемый атрибут работал во всех случаях, вы делаете свои типы значений обнуляемыми следующим образом:

 [Required]
public Gender? Gender { get; set; }
  

Комментарии:

1. Спасибо, Дэвид. Но является ли поведение webapi по умолчанию для указания значения по умолчанию для enum ? Я тестировал с целочисленным значением, и оно также присваивает значение по умолчанию для integer . Это только для меня или вы сталкиваетесь с той же проблемой>

2. Это не имеет ничего общего с webapi, но разница между типами значений и ссылочными типами — msdn.microsoft.com/en-us/library/t63sy5hs.aspx

3. Спасибо, Дэвид. Итак, я должен написать a custom method , который будет проверять значения модели, несмотря на наличие a filter attribute ?

4. Вам не нужно, мой код правильно проверяет, что значение Gender не было указано, поэтому по этому вопросу я не уверен, почему ваш не ведет себя так, как ожидалось.

5. Я обновил свой ответ, теперь я понимаю, почему мы получаем разные результаты.

Ответ №2:

Вы просто ввели Required validate , но не проверили значение следующим образом:

 [RegularExpression("^[0-9]*$", ErrorMessage = "Your fill the wrong content!")]
  

и если вы хотите установить значение по умолчанию перед сохранением, вы можете сделать что-то подобное в своем классе:

 public Request()
    {
        Gender = "male";
        Name = "default name"
    }
  

Надеюсь на помощь!