Asp.net mvc 敲除和MVC3:将JSON发布到操作,序列化两次?Can';t转换为C#对象?

Asp.net mvc 敲除和MVC3:将JSON发布到操作,序列化两次?Can';t转换为C#对象?,asp.net-mvc,json,asp.net-mvc-3,post,knockout.js,Asp.net Mvc,Json,Asp.net Mvc 3,Post,Knockout.js,我有一个通过保存方法发布的淘汰模型: self.save = function(form) { ko.utils.postJson($("form")[0], self); }; 我检查请求以确保所有数据都已正确发布(它是): 然而,当我开始行动时: [HttpPost] public ActionResult Create(EquipmentCreateModel equipmentCreateModel) { /stuff here } Bui

我有一个通过保存方法发布的淘汰模型:

 self.save = function(form) {
        ko.utils.postJson($("form")[0], self);
    };
我检查请求以确保所有数据都已正确发布(它是):

然而,当我开始行动时:

 [HttpPost]
 public ActionResult Create(EquipmentCreateModel equipmentCreateModel)
 {
    /stuff here
 }
BuildingCode和Room包含转义引号,标识符完全不为null,但计数为0:

my ModelState无效,对于尝试值为的
Identifiers
属性有一个错误:

例外信息是:

“从类型'System.String'到类型'System.Collections.Generic.KeyValuePair`2[[System.Guid,mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089],[System.String,mscorlib,Version=4.0.0.0,Culture=neutral,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; }
}
公共类设备CreateModel
{
//用于填充表单下拉列表
公共ICollection建筑物{get;set;}
公共ICollection标识符类型{get;set;}
[必需]
[显示(Name=“Building”)]
公共字符串构建代码{get;set;}
[必需]
公共字符串室{get;set;}
[必需]
[Range(1100,ErrorMessage=“您必须至少添加一个标识符。”)]
public int-IdentifiersCount{get;set;}//用作验证列表的隐藏字段
公共字符串IdentifierValue{get;set;}//仅用于剔除viewmodel绑定
公共IDictionary标识符{get;set;}
}
首先,我认为这是敲除的问题,但后来我发现数据没有正确地发布在请求中。我解决了这个问题,但仍然有同样的问题。我以为MVC3现在会自动转换Json?为什么我的简单属性出现在转义引号中,为什么我的标识集合不能从发布的数据中正确填充?

您可以尝试:

[HttpPost]
 public ActionResult Create(string equipmentCreateModelString)
 {
    var equipmentCreateModel = JsonConvert.DeserializeObject<EquipmentCreateModel> equipmentCreateModelString, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
 }
[HttpPost]
公共操作结果创建(字符串设备CreateModelString)
{
var equipmentCreateModel=JsonConvert.DeserializeObject equipmentCreateModelString,新的JsonSerializerSettings(){NullValueHandling=NullValueHandling.Ignore});
}
否则,您需要使用
JsonValueProviderFactory

试试这个:

 [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);
          }
     }
 }
这是取自:
您应该检查注释,因为FromJsonAttribute有一些修改。

如果您使用的是MVC3,则不需要添加JsonValueProviderFactory。对于我们这些仍然使用MVC2的人,您可以手动添加JsonValueProviderFactory

但是,JsonValueProvider仅适用于AJAX post。对于完整回发,它需要额外的处理。有一个线程描述如何处理完整回发:

最简单的解决方案是使用AJAX post。改变

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


@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 });
}

添加JsonValueProviderFactory不起作用(我所需要做的就是注册正确吗?)另一个建议的方法也不起作用,因为它完全绕过了模型验证,服务器端验证将不起作用,因为ModelState只有那个字符串。这不再需要了,MVC3会自动完成这项工作。我在其他问题中也看到了这一点:。问题是,在该示例中,他们传递的是收集礼物,而不是整个视图模型,如果您尝试将其设置为在包含礼物集合的视图模型中传递,则这不起作用。看起来是因为knockout中的
postJSON
方法无法处理视图模型之外的嵌套集合。我认为现在这甚至是有道理的。postJSON创建一个表单,打开值,然后提交表单。但是集合只是被转换成字符串,至少在我看来是这样,我很想找到任何能够创建一个工作示例的人,其中提交的KO对象上有一个复杂的对象集合,整个视图模型都是通过postJSON提交的,并且可以正常工作。我需要使用常规的回发,而不是AJAX。你好,DOTang,我也有同样的问题。你能解决它吗?@eze1981我刚刚写了一个方法来删除这些区域的转义字符。不过,如何在常规帖子中击败对手似乎是个问题。
self.save = function() {
    var jsModel = ko.mapping.toJS(self);
    ko.utils.postJson('@Url.Action("Create", "Equipment")', { model : jsModel });
}