【问题标题】:Post object with multi level property to controller将具有多级属性的对象发布到控制器
【发布时间】:2019-05-28 07:51:21
【问题描述】:

我需要将一个对象从视图发送到控制器,并且模型包含一个对象列表,每个对象都有一个其他复杂对象的列表。 考虑我有这些模型:

public class CourseVm {
    public IList<CousreAttendance> CourseAttendances { get; set;}
}

public class CourseAttendance {
    public int StudentId { get; set; }
    public List<SessionAttendance> SessionAttendances { get; set; }
}

public class SessionAttendance {
    public int SessionId { get; set; }
    public bool IsPresent { get; set; }
} 

我可以发送一个没有内部列表属性的对象列表,但是将CourseVm 以上发送到控制器总是失败。我想创建正确的输入形式,如下所示:

// Before submit form to controller
form.append('<input type="hidden" name="CourseAttendances.Index" value="0" />'+
            '<input type="hidden" name="CourseAttendances[0].StudentId" value="5" />'+

            '<input type="hidden" name="CourseAttendances[0].SessionAttendances.Index" value="0" />' +
            '<input type="hidden" name="CourseAttendances[0].SessionAttendances[0].IsPresent" value="true" />' +
            '<input type="hidden" name="CourseAttendances[0].SessionAttendances[0].SessionId" value="555" />' 

    // Do same logic for SessionAttendances[1..n]
  );

由于某些原因,我不想使用@Html.HiddenFor(),并且必须通过 jquery 进行隐藏输入。我怎样才能做出正确的输入?谢谢。

【问题讨论】:

    标签: javascript asp.net-mvc properties binding


    【解决方案1】:

    我找到了解决问题的方法,并将其发布给未来的读者。解决方案应包括 2 个步骤

    1. 所有模型都必须有一个无参数构造函数。我的一个模型没有。
    2. 应通过以下方法进行隐藏输入

    我编写了一个方法来为具有多级列表的发送对象进行输入。代码:

    function hiddenInputForComplexListItemWithListProperty(index, inputName, objectProperties) 
    {
        /// <summary>
        /// Used when user wants to create related html inputs for a list of a complex object
        /// </summary>
        /// <param name="index">Index of item in the list. it starts from 0</param>
        /// <param name="inputName">The name for the entry in the form.</param>
        /// <param name="objectProperties">The object's properties that hold the data and will carry the information for
        /// the input. The properties should be in the json format. If the property is object again, flatten the inner object.
        /// for example if the object has 2 properties like Id and Student which is complex object, make student object like below:
        /// { "Id": 5, "Student.Id" : 1000, "Student.Name": "Reza", "Student.LastName" : "Ghasemi" }
        /// </param>
        /// <returns>A string containing the hidden inputs for current list object</returns>    
        var inputs = `<input type="hidden" name="${inputName}.Index" value="${index}" />`;
        inputs += _makeInput(index, inputName, objectProperties);
    
        return inputs;
    }
    
    function isPrimitive(obj) {
        /// <summary>Checks the variable and if it is primitive variable returns true.</summary>
        return Object(obj) !== obj;
    }
    
    function _normalize(propertyName) {
        return propertyName.replace(/(\[|\]|\.)/g, '_');
    }
    
    function _makeInput(index, inputName, values) {
        function _inputForNonPrimitives(values) {
            var output = '';
            Object.keys(values).forEach(function(key) {
                var value = values[key];
    
                if (isPrimitive(value)) {
                    var name = `${inputName}[${index}].${key}`;
                    output += `<input type="hidden" name="${name}" id="${_normalize(name)}" value="${value}" Value="${value}" />`;
                } else {
                    for (var i = 0; i < value.length; i++) {
                        output += _makeInput(i, `${inputName}[${index}].${key}`, value[i]);
                    }
                }
            });
            return output;
        }
    
        if (isPrimitive(values))
            return `<input type="hidden" name="${inputName}[${index}]" id="${_normalize(name)}" value="${values}" Value="${values}" />`;
    
        var output = '';
        if (Array.isArray(values)) {
            values.forEach(function(item) {
                output += _inputForNonPrimitives(item);
            });
        } else {
            output += _inputForNonPrimitives(values);
        }
    
        return output;
    }
    

    用法:假设您想将以下模型的列表发送到控制器:

    {
        "Id" : 1,
        "CourseAttendances": [ 
                              {"StudentId" : 100, 
                               "SessionAttendances" : [{"SessionId":1, "IsPresent":true},
                                                       {"SessionId":2, "IsPresent":false}]
                              },
                              {"StudentId" : 101, 
                               "SessionAttendances" : [{"SessionId":1, "IsPresent":true},
                                                       {"SessionId":2, "IsPresent":true}]
                              }
                             ]
    }
    

    你应该使对象像:

    var form = $('#yourForm');
    
    for (var i=0; i<list_of_objects; i++){
        form.append(
            hiddenInputForComplexListItemWithListProperty(
                 i,  // i will be the index of object
                 "CourseAttendances", // Name of property name in the model
                 all_of_model_properties_with_their_values                                          
            ));
    }
    

    示例 json 模型(我在上面写的)调用方法的正确形式是:

    hiddenInputForComplexListItemWithListProperty(
        1,
        "CourseAttendances",
        [ 
         {"StudentId" : 100, 
          "SessionAttendances" : [{"SessionId":1, "IsPresent":true},
                                  {"SessionId":2, "IsPresent":false}]
         },
         {"StudentId" : 101, 
          "SessionAttendances" : [{"SessionId":1, "IsPresent":true},
                                  {"SessionId":2, "IsPresent":true}]
         }
        ]
    );
    

    【讨论】:

      猜你喜欢
      • 2013-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 2021-11-07
      • 2017-02-22
      • 2015-05-03
      相关资源
      最近更新 更多