将具有多级属性的对象发布到控制器

时间:2019-01-01 05:37:10

标签: javascript asp.net-mvc properties binding

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

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进行隐藏输入。如何正确输入?谢谢。

1 个答案:

答案 0 :(得分:0)

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

  1. 所有模型都必须具有无参数的构造函数。我的其中一个模型没有。
  2. 隐藏输入应采用以下方法

我写了一种方法,可以为具有多级列表的send对象进行输入。代码:

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