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 ответа

Решение

Ну, я "решил" это, но я не очень понимаю, почему изменения, которые я сделал, помогли.

Я должен был сделать три вещи:

  1. Удалить фильтр json (фильтры не связываются)

  2. Измените contentType на application / json

    $.ajaxSetup ({contentType: "application / json; charset = utf-8"});

  3. Загрузите файл 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 подписаться на вопросы:

  1. Можно ли установить тип содержимого в вызове $.post()? Тогда мне не нужно было бы устанавливать его глобально. Jquery - Как заставить $.post() использовать contentType=application/json?

  2. Можно ли заставить работать 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 должен быть в состоянии сказать вам, происходит ли это или нет.

Другие вопросы по тегам