Knockout и MVC3: отправка JSON в действие, сериализация дважды?Не можете конвертировать в C # объекты? - PullRequest
2 голосов
/ 24 марта 2012

У меня есть модель нокаута, которая публикуется с помощью метода сохранения:

 self.save = function(form) {
        ko.utils.postJson($("form")[0], self);
    };

Я проверяю запрос, чтобы убедиться, что все данные публикуются правильно (это так):

enter image description here

Однако, когда я доберусь до своего действия:

 [HttpPost]
 public ActionResult Create(EquipmentCreateModel equipmentCreateModel)
 {
    /stuff here
 }

BuildingCode и Room содержат экранированные кавычки, а идентификаторы не равны нулю, но имеют счетчик 0:

enter image description here

И мой ModelState недействителен, есть одна ошибка для свойства Identifiers, у которого есть попытка значения:

enter image description here

и сообщение об исключении:

"Преобразование параметра из типа 'System.String' в тип 'System.Collections.Generic.KeyValuePair`2 [[System.Guid, mscorlib, Версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089], [ System.String, mscorlib, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089]] 'не удалось, поскольку преобразователь типов не может преобразовывать эти типы. "

Моя модель:

public class EquipmentCreateModel
{
//used to populate form drop downs
public ICollection<Building> Buildings { get; set; }
public ICollection<IdentifierType> IdentifierTypes { get; set; }

[Required]
[Display(Name = "Building")]
public string BuildingCode { get; set; }

[Required]
public string Room { get; set; }

[Required]
[Range(1, 100, ErrorMessage = "You must add at least one identifier.")]
public int IdentifiersCount { get; set; } //used as a hidden field to validate the list
public string IdentifierValue { get; set; } //used only for knockout viewmodel binding

public IDictionary<Guid, string> Identifiers { get; set; }
}

Сначала я подумал, что это проблема с нокаутом, но потом выяснил, что данные не были правильно размещены в запросе. Я исправил это и все еще имел ту же проблему. Я думал, что MVC3 автоматически преобразует Json сейчас? Почему мои простые свойства отображаются в экранированных кавычках и почему моя коллекция идентификаторов не может быть правильно заполнена из опубликованных данных?

Ответы [ 4 ]

2 голосов
/ 24 марта 2012

Попробуйте это:

 [HttpPost]
 public ActionResult Create([FromJson] EquipmentCreateModel equipmentCreateModel)
 {
    //stuff here
 }

где FromJson:

   public class FromJsonAttribute : CustomModelBinderAttribute
    {
      private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
      public override IModelBinder GetBinder()
      {
         return new JsonModelBinder();
      }

      private class JsonModelBinder : IModelBinder
      {
         public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
         {
           var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
           if (string.IsNullOrEmpty(stringified))
                return null;
           return serializer.Deserialize(stringified, bindingContext.ModelType);
          }
     }
 }

Это взято из: http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/ вы должны проверить комментарии, так как есть некоторые изменениядля атрибута FromJson.

1 голос
/ 09 апреля 2012

Если вы используете MVC3, вам не нужно добавлять JsonValueProviderFactory.Для тех из нас, кто все еще находится в MVC2, вы можете добавить JsonValueProviderFactory вручную http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx

Однако JsonValueProvider работает только с AJAX post .Для полной обратной передачи требуется дополнительная обработка.Есть ветка, описывающая, как обрабатывать полную обратную передачу: groups.google.com / d / topic / knockoutjs / 3FEpocpApA4 / обсуждение

Самым простым решением было бы использование записи AJAX.Измените

ko.utils.postJson($("form")[0], self);

на

$.ajax({
  url: $("form").action,
  type: 'post',
  data: ko.toJSON(self),
  contentType: 'application/json',
  success: function (result) {
     alert(result);
  }
});
0 голосов
/ 09 июля 2012

@ DOTang, у меня другой подход.Во-первых, вам нужен чистый объект js из вашей модели представления.Вы можете получить его, вызвав: ko.mapping.toJS(self), а затем передать вашу модель представления в функцию postJson как свойство.Наконец добавьте атрибут [FromJson] к вашему контроллеру.Имя аргумента вашего контроллера должно совпадать с именем вашего свойства js, в этом случае: model .

Я надеюсь, что оно работает для вас так же, как и для меня.

[HttpPost]
public ActionResult RegisterUser([FromJson] EquipmentCreateModel model)
{
    //...
}

клиент

self.save = function() {
    var jsModel = ko.mapping.toJS(self);
    ko.utils.postJson('@Url.Action("Create", "Equipment")', { model : jsModel });
}
0 голосов
/ 24 марта 2012

Вы можете попробовать:

[HttpPost]
 public ActionResult Create(string equipmentCreateModelString)
 {
    var equipmentCreateModel = JsonConvert.DeserializeObject<EquipmentCreateModel> equipmentCreateModelString, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
 }

В противном случае вам нужно использовать JsonValueProviderFactory. Вот пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...