在控制器上绑定视图数据

时间:2016-12-05 17:44:35

标签: c# asp.net asp.net-mvc razor

我有当前的ViewModel:

public class ServiceSheetViewModel
{
    public List<ServiceSheetQuestionViewModel> questions { get; set; }
    public List<VehicleAction> actions { get; set; }
}

而且,在视图中,我正在生成以下内容:

@Html.EditorFor(modelItem => Model.questions[j], "ServiceSheetQuestionViewModel");
@Html.EditorFor(m => Model.actions[i], "VehicleAction");

在控制器上:

[HttpPost]
public ActionResult CreateServiceSheet([Bind(Include = "questions,actions")]  ServiceSheetViewModel model, int vehicleId, int serviceSheetId)

当我提交表格时,它没有约束力。

在帖子信息中,它说它发送了ServiceSheetQuestionViewModel列表和VehicleActions列表。

如何正确绑定表单?

编辑1 - 查看代码

@model  SupervisedSolutions.Models.ViewModels.ServiceSheetViewModel
....
@using (Html.BeginForm("CreateServiceSheet", "PerformService", Model))
{
    ....
    @foreach (var rootItem in Model.questions.Where(x => x.Question.IsGroup || (!x.Question.IsGroup && (x.Question.ParentQuestion == null || x.Question.ParentQuestion.ID == 0))).ToList())
    {
        var i = Model.questions.IndexOf(rootItem);
        if (Model.questions[i].Question.IsGroup)
        {
            @Html.HiddenFor(m => Model.questions[i].Question.ID)
            @Html.HiddenFor(m => Model.questions[i].Question.Title)
            @Html.HiddenFor(m => Model.questions[i].Question.Description)
            @Html.HiddenFor(m => Model.questions[i].Question.IsGroup)
            @Html.HiddenFor(m => Model.questions[i].Question.OrderIndex)
            @Html.HiddenFor(m => Model.questions[i].Question.ParentQuestion.ID)
            @Html.HiddenFor(m => Model.questions[i].Question.ParentQuestion.setDeleted)
            @Html.HiddenFor(m => Model.questions[i].Question.ParentQuestion.Title)
            @Html.HiddenFor(m => Model.questions[i].Question.ParentQuestion.Created)
            <h1>@Model.questions[i].Question.Title</h1>
            <p>@Model.questions[i].Question.Description</p>
            ....
            @foreach (var item in Model.questions.Where(x => !x.Question.IsGroup && (x.Question.ParentQuestion != null && x.Question.ParentQuestion.ID == Model.questions[i].Question.ID)).ToList())
            {
                var j = Model.questions.IndexOf(item);
                @Html.EditorFor(modelItem => Model.questions[j], "ServiceSheetQuestionViewModel");
            }
        }
        else
        {
            @Html.EditorFor(modelItem => Model.questions[i], "ServiceSheetQuestionViewModel");
        }
    }
    @foreach (var todo in Model.actions)
    {
        var i = Model.actions.IndexOf(todo);
        @Html.EditorFor(m => Model.actions[i], "VehicleAction");
    }
    <input type="submit" value="Start Run" class="btn btn-info" />
}

这是EditorTemplate的{​​{1}}:

ServiceSheetQuestionsViewModel

这是@model SupervisedSolutions.Models.ViewModels.ServiceSheetQuestionViewModel .... @Html.HiddenFor(m => m.Question.ID) @Html.HiddenFor(m => m.Question.Title) @Html.HiddenFor(m => m.Question.Description) @Html.HiddenFor(m => m.Question.IsGroup) @Html.HiddenFor(m => m.Question.OrderIndex) @Html.HiddenFor(m => m.Question.ParentQuestion.ID) @Html.HiddenFor(m => m.Question.ParentQuestion.setDeleted) @Html.HiddenFor(m => m.Question.ParentQuestion.Title) @Html.HiddenFor(m => m.Question.ParentQuestion.Created) <b>@Html.DisplayFor(m => m.Question.Title)</b> <label> @Html.RadioButtonFor(m => m.isFault, "Fault")Fault </label> <label> @Html.RadioButtonFor(m => m.isFault, "NoFault")No Fault </label> @Html.LabelFor(model => model.FaultDescription) @Html.TextAreaFor(model => model.FaultDescription) @Html.ValidationMessageFor(model => model.FaultDescription) @Html.ValidationMessageFor(m => m.isFault) 的{​​{1}}:

EditorTemplate

编辑2 - 以下是有关帖子数据的信息:

Vehicle Action

1 个答案:

答案 0 :(得分:1)

首先删除您的[Bind]属性(使用视图模型时不需要该属性)。

从简单的方法开始,用{/ 1>替换@foreach (var todo in Model.actions){ ... }的{​​{1}}循环

actions

并确保您的@Html.EditorFor(m => m.actions) 位于EditorTemplate(或/Views/Shared/EditorTemplates)文件夹中,并命名为/Views/youControllerName/EditorTemplatesVehicleAction.cshtml方法接受EditorFor(),并会正确生成集合中每个项目的html。

IEnumerable<T>没有绑定的问题是questions(默认情况下)要求集合索引器从零开始并且是连续的。 DefaultModelBinder@foreach (var rootItem in Model.questions.Where.....,尤其是@foreach (var item in Model.questions.Where...块中的逻辑意味着您没有生成连续的索引器(您的请求显示它们的顺序为if (Model.questions[i].Question.IsGroup){ ... } else { ... },{{ 1}},[1][0])。

解决此问题的一种方法是为集合索引器包含一个隐藏的输入,以覆盖[3]的默认行为,但这意味着您无法使用[2],您将需要{{1 }循环生成控件。请参阅this answer中的第一个代码段,以获取必要隐藏输入的示例。

但是,这种逻辑不属于视图,特别是因为您已经使用了视图模型。您的DefaultModelBinder应该有EditorTemplate的2个集合属性,比如说

for

并根据ServiceSheetViewModel的值在控制器中填充这些集合。然后在视图中,您只需使用

ServiceSheetQuestionViewModel

处理您当前在视图中使用的public List<ServiceSheetQuestionViewModel> GroupedQuestions { get; set; } public List<ServiceSheetQuestionViewModel> UngroupedQuestions { get; set; } 块。

您没有提供足够的信息来了解IsGroup循环中的逻辑正在做什么,但看起来您有基于@Html.EditorFor(m => m.GroupedQuestions) @Html.EditorFor(m => m.UngroupedQuestions) 属性的层次结构,这意味着您的视图模型也应该具有层次结构,即if/else需要包含foreach属性,以便您可以使用ParentQuestion QuestionList<Question> SubQuestions循环。

作为旁注,渲染所有这些隐藏的输入是不必要的和不好的做法(恶意用户可以轻松回发不良数据而你只是降低性能)。只需为问题nested属性生成隐藏输入,并在提交时,根据ID从数据库中获取原始数据,并仅更新基于视图模型在视图中编辑的属性。