C# 在控制器上绑定视图数据

C# 在控制器上绑定视图数据,c#,asp.net,asp.net-mvc,razor,C#,Asp.net,Asp.net Mvc,Razor,我有当前的ViewModel: public class ServiceSheetViewModel { public List<ServiceSheetQuestionViewModel> questions { get; set; } public List<VehicleAction> actions { get; set; } } 在控制器上: [HttpPost] public ActionResult CreateServiceSheet([

我有当前的ViewModel:

public class ServiceSheetViewModel
{
    public List<ServiceSheetQuestionViewModel> questions { get; set; }
    public List<VehicleAction> actions { get; set; }
}
在控制器上:

[HttpPost]
public ActionResult CreateServiceSheet([Bind(Include = "questions,actions")]  ServiceSheetViewModel model, int vehicleId, int serviceSheetId)
当我提交表格时,它没有约束力

在post信息中,它说它发送了一个
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" />
}
这是
车辆操作的
编辑器模板

@model SupervisedSolutions.Models.VehicleAction

@Html.LabelFor(model => model.Description)
@Html.TextAreaFor(model => model.Description)
@Html.ValidationMessageFor(model => model.Description)

@Html.LabelFor(model => model.Priority)
@Html.TextAreaFor(model => model.Priority)
@Html.ValidationMessageFor(model => model.Description)

@Html.LabelFor(m => m.DueDate>
@Html.EditorFor(model => model.DueDate)
@Html.ValidationMessageFor(m => m.DueDate)
编辑2-以下是有关post数据的信息:

vehicleId:50
serviceSheetId:1
ID:0
questions[1].Question.ID:3
questions[1].Question.Title:Testing
questions[1].Question.Description:AASDASD
questions[1].Question.IsGroup:True
questions[1].Question.OrderIndex:1
questions[1].Question.ParentQuestion.ID:
questions[1].Question.ParentQuestion.setDeleted:
questions[1].Question.ParentQuestion.Title:
questions[1].Question.ParentQuestion.Created:
questions[0].Question.ID:1
questions[0].Question.Title:Test Question
questions[0].Question.Description:Habba
questions[0].Question.IsGroup:False
questions[0].Question.OrderIndex:0
questions[0].Question.ParentQuestion.ID:3
questions[0].Question.ParentQuestion.setDeleted:False
questions[0].Question.ParentQuestion.Title:Testing
questions[0].Question.ParentQuestion.Created:28/11/2016 7:35:12 PM
questions[0].isFault:NoFault
questions[0].FaultDescription:Teste
questions[3].Question.ID:5
questions[3].Question.Title:Group 2
questions[3].Question.Description:Groupin 2
questions[3].Question.IsGroup:True
questions[3].Question.OrderIndex:0
questions[3].Question.ParentQuestion.ID:
questions[3].Question.ParentQuestion.setDeleted:
questions[3].Question.ParentQuestion.Title:
questions[3].Question.ParentQuestion.Created:
questions[2].Question.ID:4
questions[2].Question.Title:Test Question 23
questions[2].Question.Description:TEEEE
questions[2].Question.IsGroup:False
questions[2].Question.OrderIndex:0
questions[2].Question.ParentQuestion.ID:5
questions[2].Question.ParentQuestion.setDeleted:False
questions[2].Question.ParentQuestion.Title:Group 2
questions[2].Question.ParentQuestion.Created:1/12/2016 4:19:49 PM
questions[2].isFault:NoFault
questions[2].FaultDescription:Teste
actions[0].Description:Erro2
actions[0].Priority:1
actions[0].DueDate:2010-01-01

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

从简单的开始,将
@foreach(Model.actions中的var todo){…}
循环的
操作
替换为

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

questions
未绑定的问题在于
DefaultModelBinder
(默认情况下)要求集合索引器从零开始,并且是连续的。
@foreach(Model.questions.Where…
@foreach(Model.questions.Where…
中的var项)中的逻辑,特别是
if(Model.questions[i].Question.IsGroup){…}else{…}
块表示您没有生成连续的索引器(您的请求显示它们的顺序是
[1]
[0]
[3]
[2]

解决此问题的一种方法是为集合索引器包含一个隐藏输入,以覆盖
DefaultModelBinder
的默认行为,但这意味着您不能使用
EditorTemplate
,您将需要
for
循环来生成控件。请参阅中的第一个代码段以获取必要的hi示例dden输入

但是,这种逻辑不属于视图,特别是因为您已经在使用视图模型。您的
ServiceSheetQuestionViewModel
应该有两个集合属性,例如
ServiceSheetQuestionViewModel

public List<ServiceSheetQuestionViewModel> GroupedQuestions { get; set; }
public List<ServiceSheetQuestionViewModel> UngroupedQuestions { get; set; }
处理视图中当前使用的
if/else

您没有提供足够的信息来理解
foreach
循环中的逻辑在做什么,但您似乎有一个基于
ParentQuestion
属性的层次结构,这意味着您的视图模型也应该有一个层次结构,即
Question
需要包含一个
列出子问题
属性,以便您可以使用
嵌套的
编辑器或模板
进行循环


作为旁注,呈现所有这些隐藏的输入是不必要的,也是不好的做法(恶意用户很容易发回坏数据,而您只会降低性能)。只需为问题
ID
属性生成一个隐藏输入,然后在提交时,根据ID从数据库中获取原始信息,并根据视图模型仅更新您在视图中编辑的属性。

显示视图(您在其中生成表单控件的循环和编辑器将使用
ServiceSheetQuestionViewModel
VehicleAction
)@StephenMuecke I为视图添加了完整的HTML。
@Html.EditorFor(m => m.actions)
public List<ServiceSheetQuestionViewModel> GroupedQuestions { get; set; }
public List<ServiceSheetQuestionViewModel> UngroupedQuestions { get; set; }
@Html.EditorFor(m => m.GroupedQuestions)
@Html.EditorFor(m => m.UngroupedQuestions)