ASPNET MVC - Почему ModelState.IsValid false "Поле 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 вместо submit? Что я могу сделать?

Вот что выглядит отладчик:

alt text http://www.freeimagehosting.net/uploads/f734f3d95d.png

EDIT: дополнительная информация....

Я действительно думаю, что по какой-то причине привязка к модели не происходит. Когда я попробую этот код найти здесь:)

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 имеет правильное значение.

Так что все еще не разрешено, но, надеюсь, эта дополнительная информация поможет найти решение

Ответ 1

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

Мне пришлось сделать три вещи:

  • Удалить json-фильтр (фильтры не привязаны)

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

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

  • Используйте фьючерсы MVC для загрузки 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(новый JsonValueProviderFactory());

Теперь я точно не знаю, почему это сработало, но оно есть.

К сожалению, он имел отрицательный побочный эффект: contenttype применяется ко всем методам $.get() и $.post() и разбивает все мои jqgrids - они работают только, если тип содержимого является значением по умолчанию применение/х-WWW-форм-urlencoded

Итак, я задал два вопроса:

Ответ 2

Вы уверены, что ошибка исходит из поля OrderNumber?

Кажется странным, что сообщение об ошибке имеет номер заказа в 2 слова.

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

Ответ 3

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