【问题标题】:Simulating a form POST to ASP.NET MVC with javascript使用 javascript 模拟表单 POST 到 ASP.NET MVC
【发布时间】:2009-11-05 22:12:19
【问题描述】:

我在尝试将 JSON 发送到 ASP.NET MVC 控制器时遇到问题。我不想在每个控制器方法上接受一个字符串参数并手动反序列化。我发现构造一个 post 变量的集合是可靠的,但我没有一个通用的函数来这样做。如果没有人做过,我可以自己写一个,但我觉得很难相信。

如果明天还没有人回答这个问题,我想我就不再偷懒了。

编辑:明确地说,我不是在问如何将 .NET 对象序列化为 JSON。我在问是否有人编写了 javascript 函数来执行以下操作:

给定的 javascript 对象:

{ 
    name: { first: "first", last: "last" }, 
    age: 35,
    drinks: [
        { carbonated: false, name: "juice" },
        { carbonated: true, name: "soda" }
    ]
}

返回(POST 请求作为对象):

name.first  :   first
name.last   :   last
age         :   35
drinks[0].carbonated    :   false
drinks[0].name          :   juice
drinks[1].carbonated    :   true
drinks[1].name          :   soda

谢谢。

【问题讨论】:

  • 您可以添加一个问题吗?您是在问是否有现有的图书馆可以做到这一点?您是否在尝试自己创建泛化函数时遇到一些特定问题寻求帮助?

标签: javascript asp.net-mvc json


【解决方案1】:

这取决于您希望序列化工作的深度。您可以在 jQuery 中使用 $.param(obj) 方法进行简单的对象序列化,但它不适用于您的示例,因为它假定值是简单类型或简单类型的数组。您可能想查看 param 的代码并根据您的特殊需求对其进行调整。本质上,您需要确定值何时是对象,并在构造键/值数组时使用它将对象中的键附加到外部键。处理复杂对象的数组需要一些类似的操作才能正确设置键索引。

以下已在 FF3.5/IE8 中测试。不保证其他浏览器,但我认为它应该可以工作。

jQuery.extend( {
    isObject: function(obj) {
       return typeof(obj) === "object";
    },
    complexParam: function( a ) {
        var s = [ ];

        function add( key, value ){
            s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
        };

        // If an array was passed in, assume that it is an array
        // of form elements
        if ( jQuery.isArray(a) || a.jquery )
            // Serialize the form elements
            jQuery.each( a, function(){
                add( this.name, this.value );
            });

        // Otherwise, assume that it's an object of key/value pairs
        else
            // Serialize the key/values
            for ( var j in a )
                // If the value is an array then the key names need to be repeated
                if ( jQuery.isArray(a[j]) )
                    jQuery.each( a[j], function(){
                        if (jQuery.isObject(this)) {
                            var idx = 0;
                            for (var k in this) {
                               add( j + "[" + idx + "]." + k, this[k] );
                               ++idx;
                            }
                        }
                        else {
                             add( j, this );
                        }
                    });
                else {
                    if (jQuery.isFunction(a[j])) {
                       add( j, a[j]() );
                    }
                    else if (jQuery.isObject(a[j])) {
                       for (var k in a[j]) {
                          add( j + "." + k, a[j][k] );
                       }
                    }
                    else {
                        add( j, a[j] );
                    }
                }

        // Return the resulting serialization
        return s.join("&").replace(/%20/g, "+");
    }
});

称为

var serialized = $.complexParam( obj );

请注意,这会留下括号 URL 编码。如果还不行,那就加

.replace(/%5B/g, "[").replace(/%5D/g, "]")

在 complexParam() 中返回

【讨论】:

  • 谢谢!终于有人阅读了这个问题:) 我刚刚修改了您的代码以使用 Mootools。我会尽快发布。
【解决方案2】:
【解决方案3】:

所以,.Net v3.5 及更高版本中有 System.Runtime.Serialization.Json.DataContractJsonSerializer 类。它将 JSON 数据序列化和反序列化为对象。您必须引用 System.ServiceModel.Web 程序集。

System.Web.Mvc.Controller.Json() 函数也可以处理您的序列化需求。

所以你已经覆盖了控制器,听起来你已经覆盖了 javascript 方面,对吧?

【讨论】:

    【解决方案4】:

    他们的问题已经有人编写了一个操作过滤器来执行此操作,您可能想查看他们的解决方案。

    Binding application/json to POCO object in asp.net mvc, Serialization exception

    【讨论】:

      【解决方案5】:

      我不知道这是否是您真正想听到的那种答案,但我个人不会尝试将所有内容都推送到 JavaScript 中的 JSON 对象,您仍然需要做一些工作另一端。

      我目前这样做的方式是通过将 Request.Form 值从 Controller 传递到模型基础对象,然后使用反射从 Request.Form 变量中提取必要的值并更新模型对象中的值.因此,基本上您可以使用单个方法调用来保存对象的所有核心细节,而不必担心手动将表单分开。这方面的一个例子是:

      Job temp = new Job();
      temp.UpdateDetails(Request.Form);
      

      这通常在您的“保存”或等效操作中,并且显然会以相同的方式与现有对象一起使用。请注意,这是您的基类上的单个方法,您不需要在每个模型对象上重新实现它。与单独序列化 JSON 对象相比,使用此方法可以大大降低代码(javascript 和后端代码)的复杂性/大小。

      如果您愿意,我可以更详细地解释此方法,但如果这不是您需要的,我不会费力解释每个单独的步骤,因为我意识到这不是您最初的问题是关于。

      【讨论】:

      • 我正在寻找的答案应该只是 javascript 的形式。我想要一个 JS 函数,它将创建标准 ASP.NET MVC 控制器操作所期望的“POST 编码”格式。这允许我在不修改操作的情况下对任何 MVC 控制器操作进行 ajax 调用。我不需要期望 JSON 传递给控制器​​。
      • 难道你不能对任何 MVC 控制器操作进行 AJAX 调用吗?您无需为每个操作指定所需的每个单独的输入参数,只需使用 Request.Form 值,否则您的操作将变得臃肿。也许您正在寻找的是 jQuery 核心库 Post 方法 (docs.jquery.com/Post)。我亲自使用了这个,效果很好。如果这不是您所需要的,您可能需要重新表述您的问题,因为我对您实际要问的内容有点茫然。
      【解决方案6】:

      我使用 jQuery 的 $.toJSON 在 javascript 端序列化对象,然后在控制器端使用 Json.Net 反序列化它(我发现在某些输入上有时会在 ASP.NET MVC barfs 中反序列化库存 JSON)。

      【讨论】:

        【解决方案7】:

        这是我想要的 Mootools 版本。我实际上没有意识到 Mootools Hash.toQueryString() 默认情况下几乎是这样做的。它以 ASP.NET MVC 无法识别的方式格式化数组,所以我仍然需要实现自己的:

        var POSTEncoder = {
        getHash: function(request, prefix, out) {
        
            if($type(out) != 'object') { out = {}; }
        
            function add(key, value){
                out[ key ] = value;
            };
        
            var validPrefix = $type(prefix) == 'string';
        
            switch($type(request)) {
                case 'array':
        
                    if(!validPrefix) { prefix = 'request'; }
        
                    request.each(function(item, i){
                        POSTEncoder.getHash(item, prefix + '[' + i + ']', out);
                    });
        
                    break;
        
                case 'object':
        
                    if(!validPrefix) { prefix = ''; }
        
                    new Hash(request).each(function(val, key) {
                        POSTEncoder.getHash(val, (prefix != '' ? prefix + '.' : '') + key, out);
                    });
        
                    break;
        
                case 'string':
                case 'number':
                case 'boolean':
                case 'date':
        
                    if(!validPrefix) { prefix = 'request'; }
        
                    add(prefix, request);
        
                    break;
                case false:
                    add(prefix || 'request', '');
            }
        
            return new Hash(out);
        }};
        

        POSTEncoder.getHash(request) 会将请求扁平化为适合表单 POST 的键/值对。 POSTencoder.getHash(request).toQueryString() 会将其转换为查询字符串。

        例子:

        var test = {
        bool: true,
        strng: 'a',
        numbr: 1,
        basicArr: ['d','e','f'],
        basicObj: {x:1, y: 'z'},
        objectArr: [{n:1, o:2}, {n:3,o:4}],
        complex: {
            one: 1,
            two: 'two',
            three: [{x:1},{x:2},{x:3}]
        }};
        
        var hash = POSTEncoder.getHash(test);
        
        console.log(hash);
        console.log(hash.toQueryString());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-13
          • 2020-05-23
          • 2015-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-24
          • 1970-01-01
          相关资源
          最近更新 更多