2016-06-28 6 views
1

Я работаю над приложением ASP.NET MVC 5, а владелец проекта обеспокоен проблемами «недопоставки», вызванными проверкой типов, не допускающих нулевое значение (как указано в http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html и http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api).Проверка модели ASP.NET MVC 5 для типов, не подлежащих обнулению (Int32)

Я создал тестовый пример для репликации этой проблемы в ASP.NET MVC 5, но без везения.

Модель:

public class ContactModel 
{ 
    [Required] 
    public Int32 data1 { get; set; } 

    public Int32 data2 { get; set; } 
} 

Вид:

<div class="form-group"> 
    @Html.LabelFor(model => model.data1) 
    <div> 
     @Html.EditorFor(model => model.data1) 
    </div> 
</div> 
<div> 
    @Html.LabelFor(model => model.data2) 
    <div> 
     @Html.EditorFor(model => model.data2) 
    </div> 
</div> 

Контроллер:

public ActionResult Index(Models.ContactModel contact) 
{ 
    if (ModelState.IsValid) 
    { 
     Response.Write("modelstate is valid<br>"); 

     return View(); 
    } 
    else 
    { 
     Response.Write("modelstate is invalid<br>"); 

     return View(); 
    } 
} 

Кажется, что когда data1 и data2 являются недействительными в должности, их значения в модели (contact) будет 0. Однако ModelState.IsValid будет lso be false (вместо true, как показано в двух статьях).

Что у меня есть:

enter image description here

Что второй статье показано:

enter image description here

Я не мог найти какую-либо информацию в отношении изменений о том, как модель проверки работы в ASP.NET MVC, поэтому я предполагаю, что я сделал что-то не так с моим тестовым случаем. Любую мысль и предложение ценят.

+2

Вам не нужен атрибут '[Обязательный]' в свойстве 'int' (если вы не хотите создать собственное сообщение об ошибке) -' int' никогда не может быть 'null'. «DefaultModelBinder» добавляет ошибку, потому что вы не можете назначить 'null' для' int' и устанавливает 'ModelState.IsValid = false'. Но значение равно '0', потому что это значение по умолчанию для' int' –

+0

@StephenMuecke, это то, что я думал изначально. Но согласно сообщению Брэда Уилсона (первая ссылка в моем вопросе): _ Отключение этого - это то, что [Обязательно] по типу с недействительным значением не может служить гарантией того, что форма включала значение. Если он не содержит значения, то привязка модели пропускается, что означает, что сбой привязки модели не произойдет. Кроме того, когда выполняется [Validired] validator, он запрашивает значение из модели, которое будет содержать значение значения по умолчанию, обычно 0 - и говорит «это не null, все здесь хорошо!» ._ – Jim

+0

Это неправильно, и привязка к модели никогда не пропускается. 'ModelState.IsValid' всегда будет false, если значение отправлено для свойства, которое является типом значения или ссылочным типом с атрибутом' [Обязательный] ' –

ответ

1

Причина, по которой ваш ModelState является ложным, заключается в том, что сообщение предоставляет значения форм из каждого свойства вашей модели. По сути, система привязки модели проверяет достоверность полей данных1 и data2, поскольку у вас есть @ Html.EditorFor helpers явно, написанный для обоих свойств в вашем представлении (поэтому на самом деле не происходит подтасовки).

Я успешно копировал проблемы, связанные с публикацией статей. Просто удалите один из помощников EditorFor, на ваш взгляд, поэтому вы на самом деле подталкиваете. Поскольку оба помощника присутствуют, не происходит никакой подтасовки. Таким образом, вид выглядит, как это сейчас (обратите внимание, что я добавил помощник проверки для обоих свойств, чтобы получить обратную связь в представлении о том, что происходит):

Вид:

<div class="form-group"> 
    @Html.LabelFor(model => model.data1) 
    <div> 
     @Html.EditorFor(model => model.data1) 
     @Html.ValidationMessageFor(model => model.data1) 
     @Html.ValidationMessageFor(model => model.data2) 
    </div> 
</div> 

Убедитесь оставить @Html. EditorFor helper полностью отключен для свойства data2. Теперь заполните нуль в поле формы (теперь вы увидите только одно поле формы в представлении) и отправьте сообщение в свое действие.

ModelState вернётся как истинный в этом сценарии, хотя только одно поле формы отправляется. Не хороший результат, если кто-то делает underpost!Итак, вот (слегка измененный) исходный модельный класс, в котором проблемы с базой будут возникать в случае, когда поле формы остается в стороне от вашей формы (обратите внимание, что обязательные атрибуты не имеют никакой разницы в этой ситуации, так как оба свойства являются типами значений):

//You could add the Required attribute or not, doesn't matter at this point. 
//The concern here is that the Modelstate will still come back as Valid 
//in the case of a form field being left off of your form (or someone underposts). 
//So to replicate underposting issues, make sure to comment or delete 
//at least one Html.EditorFor helper in the view. 

//[Required] Underposting will occur regardless if this is marked required or not, 
//so be careful if someone does underpost your form. 
public Int32 data1 { get; set; } 

//[Required] 
public Int32 data2 { get; set; } 

Теперь решение, если вы хотите, чтобы решить underposting вопрос: Просто маркировать оба свойства по мере необходимости и сделать их обнуляемым, как указано в статьях, предоставленных вами, как так:

[Required] 
public Int32? data1 { get; set; } 

[Required] 
public Int32? data2 { get; set; } 

сейчас, когда просмотр публикуется с отсутствующим @ Html.EditorFor помощником или отсутствующим полем формы, ModelState V алиментация вернется как ложная, и вы защищены от проблем с подтасовкой.

+0

Спасибо! Это звучит очень многообещающе. Я попытаюсь воспроизвести это позже сегодня и отметьте ответ, если он будет работать. – Jim

+0

Awesome Jim. Я провел его через отладчик и проверил поведение, поэтому все должно работать. Дайте мне знать, если у вас есть какие-либо вопросы по этому поводу. Кстати, я рад, что наткнулся на ваш вопрос. Этот атрибут Required может вводить в заблуждение, и внезапно вы можете получить свойства, установленные по умолчанию, если вы не будете осторожны. Спасибо, Тим – firecape