【问题标题】:Json and ASP.NET MVC Model BindingJson 和 ASP.NET MVC 模型绑定
【发布时间】:2013-10-16 00:43:42
【问题描述】:

我的 UI 如下所示:

我正在尝试将新创建的行的数据发送到服务器,以便服务器可以保存它。

我正在从客户端向我的 MVC 应用程序发送 JSON 格式的数据。这是我的 ajax 请求:

var values = []; // an array with each item being an object/associative array

// more code to get values into variables

for (var i = 0; i < cultures.length; i++) {
  var cultureName = cultures[i];
  var valueTextBox = $(row).find(...);
  var value = $(valueTextBox).val();

  var cultureNameAndValue = { 'CultureShortName' : cultureName, 'StringValue' : value };

  values.push(cultureNameAndValue);
}

var stringTableRow = 
  { 
    'ResourceKeyId': resourceKeyId, 
    'Key': resourceKeyName, 
    'CategoryId': categoryId, 
    'CategoryName': categoryName, 
    'StringValues': values 
  };

var stringified = JSON.stringify({ StringTableRow: stringTableRow });

$.ajax('/Strings/JsonCreateNew', 
      { 
        cache: false, 
        async: false, 
        type: 'POST', 
        contentType: 'application/json; charset=UTF-8', 
        data: stringified, 
        dataType: 'json', 
        error: SaveNewResourceClientSideHandler.OnError, 
        success: SaveNewResourceClientSideHandler.OnSuccess 
      });

这是它发送的数据(在 Firebug 中可以看到):

{"StringTableRow":{"ResourceKeyId":"","Key":"Foo",
"CategoryId":"1","CategoryName":"JavaScript",
"StringValues":[
{"CultureShortName":"en-US","StringValue":"Something"},
{"CultureShortName":"fr-FR","StringValue":""}]
}}

这是我的服务器端代码:

public ActionResult JsonCreateNew(StringTableRow row)
{
  // CreateNewStringTableRow(row);

  // return a success code, new resource key id, new category id
  // return Json(
              new { Success = true, ResourceKeyId = row.ResourceKeyId, 
                    CategoryId = row.CategoryId }, 
                JsonRequestBehavior.AllowGet);

  return new EmptyResult();
}

这是我希望传入的 POST 数据绑定到的业务对象:

public class StringTableRow
{
    public StringTableRow()
    {
        StringValues = new List<CultureNameAndStringValue>();
    }

    public long ResourceKeyId { get; set; }

    public string Key { get; set; }

    public long CategoryId { get; set; }

    public string CategoryName { get; set; }

    public IList<CultureNameAndStringValue> StringValues { get; set; }  
}


public class CultureNameAndStringValue
{
  public string CultureShortName { get; set; }

  public string StringValue { get; set; }
}

全球.asax

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
        }
    }

问题:

动作JsonCreateNew 接收一个非空但所有属性未初始化的对象,即所有可为空的属性为空,值属性为其默认值。因此,即使客户端发送了一个完全有效的 Json 字符串,我也根本没有得到任何数据。

我需要做自定义模型绑定吗?

【问题讨论】:

    标签: asp.net-mvc json asp.net-mvc-4 model-binding


    【解决方案1】:

    好的,我解决了我的问题,这对其他程序员来说可能也是一个重要的见解,因为我在解决自己的问题时学到了一些东西。

    我的解决方案: 我不使用 JSON,而是使用 HTTP 用于编码表单发布值的默认编码,然后我使用了一些有点自定义模型绑定的东西(实际上没有创建模型绑定器)。

    解释: 通常,当您发出ajax请求并将数据从客户端传递到任何服务器平台时,如果您不指定编码,即jQuery的ajax方法的设置对象中的contentType参数(或者如果您使用任何其他方式要发出 jQuery 以外的 ajax 请求,然后设置 ContentType HTTP 标头是您所追求的),HTTP 使用其默认编码对您发布的数据进行编码,这很像您在之后使用 GET 请求发布的内容查询字符串,只是它是二进制编码的,不作为 URL 的一部分发送。

    如果是这种情况,并且您将任何类型的集合(IListIEnumerableICollectionIDictionary 等)发布到 ASP.NET MVC,则不要创建JavaScript 中的关联数组来体现集合。甚至不要创建数组。不要创造任何东西。

    事实上,只需使用约定在主要的大对象中传递它:

    data = 
    { /*scalar property */ Gar: 'har', 
      /* collection */ 'Foo[index++].Bar' : 'value1', 
      'Foo[index++].Bar' : 'value2'
    }
    

    并且不要使用 JSON。这样就解决了一半的问题。

    在服务器端,接收FormCollection 中发布的数据并使用其IValueProvider 方法(GetValue)挖掘出您需要的数据。您不必显式创建模型绑定器来执行此操作。您可以在控制器本身的私有方法中执行此操作。

    稍后我会找到更多时间来改进这个答案。

    【讨论】:

    • 我也处于类似的场景中,当我使用 ajax 请求将数据发布到服务器时,我必须将所有表单值绑定到 json 格式,如 var name = $("Name").val (); var 年龄 = $("年龄").val(); // 构建 json 对象 var squirrel = { Name: name, Age: age, };有没有其他方法我不必手动将值绑定到 json.Means 有什么可以直接将我的 viewmodel 转换为 json 然后我可以将它作为对象在控制器中获取吗?
    【解决方案2】:

    使用 Backbone 或 KnockoutJs 进行数据绑定。

    【讨论】:

    • 谢谢,塔伦。我一直把淘汰赛作为最后的手段。我只是不想将我的问题委托给抽象,因为那样我会失去控制。我正在使用 jQuery 构建 UI,因为我刚刚放弃了使用 DevExpress 控件,这是另一个抽象。我知道这个问题与自定义模型绑定有关,并且不想依靠像淘汰赛这样的抽象(除非我别无选择)。我已经解决了我的问题,很快就会发布解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多