ASPNET MVC - Почему ModelState.IsValid имеет значение "Поле x обязательно", если это поле имеет значение?
У меня есть такая модель:
public PurchaseOrder
{
[Required] [StringLength(15)]
public virtual string OrderNumber {get;set;}
// etc.
}
Когда я отправляю заказ из представления (используя $.post, а не input type=submit), он отправляется в мой класс контроллера:
public class PurchaseOrderController
{
public JsonResult Save(PurchaseOrder order)
{
// TryUpdateModel(order); // commented out since modelstate.isvalid remains false anyway
if (ModelState.IsValid)
{
// its never valid
}
}
}
ModelState.IsValid всегда возвращает false с ошибкой: "Поле номера заказа обязательно". Но есть значение в этой области (почему)
Почему это говорит "значение требуется", если оно имеет значение? Я что-то пропустил? Это из-за $.post вместо подтверждения? Что я могу сделать?
Вот как выглядит отладчик:
http://www.freeimagehosting.net/uploads/f734f3d95d.png
РЕДАКТИРОВАТЬ: Дополнительная информация....
Я действительно думаю, что по какой-то причине связывание модели не происходит. Когда я попробую этот код, найденный здесь:)
if (!ModelState.IsValid)
{
ModelState.Clear();
ModelMetadata modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => order, order.GetType());
ModelValidator compositeValidator = ModelValidator.GetModelValidator(modelMetadata, base.ControllerContext);
foreach (ModelValidationResult result in compositeValidator.Validate(null))
{
this.ModelState.AddModelError(result.MemberName, result.Message);
}
}
Тогда ModelState.IsValid = true. CompositeValidator.Validate() возвращает 0 ошибок. Я думаю, что это означает, что модель не была связана, но я все еще не знаю почему.
Метод контроллера на самом деле выглядит так (я пропустил фильтр при первоначальном написании этого вопроса)
[JsonFilter(Param = "order", JsonDataType = typeof(PurchaseOrder))]
public JsonResult Save(PurchaseOrder order) { // etc ... }
И JsonFilter делает это для извлечения POCO из данных, представленных json:
filterContext.ActionParameters[Param]
= jsSerializer.Deserialize(inputContent, JsonDataType);
Я поставил точку останова на этой строке, и порядок действителен, плюс order.OrderNumber имеет правильное значение.
Так что все еще не решена, но, надеюсь, эта дополнительная информация поможет найти решение
3 ответа
Ну, я "решил" это, но я не очень понимаю, почему изменения, которые я сделал, помогли.
Я должен был сделать три вещи:
Удалить фильтр json (фильтры не связываются)
Измените contentType на application / json
$.ajaxSetup ({contentType: "application / json; charset = utf-8"});
Загрузите файл Microsoft.Mvc.dll, который описан здесь: http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx. Где говорится, чтобы добавить это к Application_Start() в Global.asax.cs:
ValueProviderFactories.Factories.Add (new JsonValueProviderFactory ());
Теперь я не знаю точно, почему это сработало, но это имеет.
К сожалению, у него был отрицательный побочный эффект: тип содержимого применяется ко всем методам $.get() и $.post() и нарушает все мои jqgrids - кажется, что они работают, только если тип содержимого является значением по умолчанию application/x-www форм-urlencoded
Поэтому я попросил 2 подписаться на вопросы:
Можно ли установить тип содержимого в вызове $.post()? Тогда мне не нужно было бы устанавливать его глобально. Jquery - Как заставить $.post() использовать contentType=application/json?
Можно ли заставить работать jqrid, если тип контента - application / json? Как заставить $.post() использовать contentType=application/json?
Вы уверены, что ошибка исходит из поля OrderNumber?
Кажется странным, что сообщение об ошибке содержит номер заказа в 2 слова.
Попробуйте изменить имя поля или удалить требуемый тег, чтобы убедиться, что именно отсюда и происходит ошибка.
Существует вероятность того, что ваше сообщение jQuery неправильно отправляется обратно в контроллер. Возможно, вы публикуете только номер заказа, а не объект, который точно представляет модель. Мне нужно увидеть ваш javascript, чтобы быть абсолютно уверенным.
Правильный способ публикации этого метода будет (при условии, что ваш номер заказа хранится в переменной javascript с именем "orderNumber":
$.post([url to method],
{ order: { OrderNumber: orderNumber } },
function(json) {
//Insert code for actions to take after AJAX post returns.
},
'json');
Если это так, то следующий шаг, который я предприму, - это двойная проверка, что javascript действительно фиксирует значение вашего номера заказа и публикует его как часть запроса. Быстрый осмотр через Firebug должен быть в состоянии сказать вам, происходит ли это или нет.