使用部分视图提交表单的MVC

7

如果此前已回答过,我很抱歉,但我找不到与我的问题匹配的内容。

我有一个包含部分视图的视图,在提交视图时,来自部分视图的数据未发送到控制器。我理解如果使用编辑器模板,则应该可以解决此问题,但我无法使用它,因为我需要在部分视图中使用主模型的数据。

我的创建视图(简化版):

@model CreateXmlSchemaModel
@using (Html.BeginForm("Create", "XmlSchema", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    <fieldset>
        <div class="editor-label">
            @Html.LabelFor(m => m.XmlSchema.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(m => m.XmlSchema.Name)
        </div>
        <div id="fieldmapping">
            @Html.Partial("_XmlFieldMapping")
        </div>
        <div>
            <input type="submit" value="Create" class="button" />
        </div>
    </fieldset>
}

我的模型结构(简化版):

public abstract class XmlSchemaModelContainerBase
{
    public IEnumerable<string> BusinessObjects { get; set; }
    public IEnumerable<XmlInputFieldModel> XmlFields { get; set; }
    public IEnumerable<string> BusinessObjectFields { get; set; }
}

public class XmlSchemaModelContainer : XmlSchemaModelContainerBase
{
    public XmlSchemaModel XmlSchema { get; set; }
}

public class XmlSchemaModel
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string BusinessObject { get; set; }
    public IEnumerable<XmlSchemaField> MappedFields { get; set; }
}

public class XmlSchemaField
{
    public string XmlElement { get; set; }
    public string BusinessObjectField { get; set; }
}

public class XmlInputFieldModel
{
    public string XmlElement { get; set; }
    public string XmlValue { get; set; }
}

public class CreateXmlSchemaModel : XmlSchemaModelContainer
{
    [Required(ErrorMessage = "File upload required")]
    public HttpPostedFileBase Xml { get; set; }
}

我的控制器(我不会全部发布,因为我可以立即看出我的viewModel不包含MappedFields):

[HttpPost]
public ActionResult Create(CreateXmlSchemaModel viewModel)
{
}

我这个_XmlMappedFields部分视图:

@model CherwellXmlConnector.Models.XmlSchemaModelContainer
@{
    Model.XmlSchema.MappedFields = Model.XmlSchema.MappedFields.OrderBy(i => i.XmlElement);
}

<div>
    <div>
        @for(int i = 0; i < @Model.XmlFields.Count(); i ++)
        {
            List<CherwellXmlConnector.Models.XmlSchemaField> fields = Model.XmlSchema.MappedFields.ToList();
            string itemValue = Model.XmlFields.FirstOrDefault(x => x.XmlElement == fields[i].XmlElement).XmlValue;

            <div style="width: 300px; display: inline-block;">
                @Html.DisplayFor(x => fields[i].XmlElement)
            </div>
            <div style="width: 300px; display: inline-block;">
                @itemValue
            </div>
            <div class="busoblist" style="display: inline-block;">
                @Html.DropDownListFor(x => fields[i].BusinessObjectField, new SelectList(Model.BusinessObjectFields))
            </div>
            <hr />
        }
    </div>
</div>

我的意图是在部分页面中向用户显示所有给定XmlFields及其值的列表,并允许他们为每个XmlField从下拉列表中选择BusinessObjectField。然后,我希望将此提交回控制器中的IEnumerable<XmlSchemaField> MappedFields对象中。这是否可能?


通常情况下,可以提交包含部分视图的表单。如果没有看到您的控制器和XmlInputFieldModel类的类型,很难回答您的问题。您能提供一下吗? - Nilzor
此外,展示生成的部分视图的HTML也会很有帮助。为了您自己的利益,使用Fiddler调试POST数据也会很有帮助。 - Nilzor
@Nilzor,我已经为您添加了缺失的类。 - Mark
1个回答

5

是的,这是可能的。

你面临的问题是由于模型绑定的工作方式造成的。如果你只是尝试为 IEnumerable 绑定一个 primitive type,那么它就可以正常工作。

@foreach(var item in @Model.XmlSchema.MappedFields)
    {
        string itemValue = Model.XmlFields.FirstOrDefault(x => x.XmlElement == item.XmlElement).XmlValue;
        <div style="width: 300px; display: inline-block;">
            @Html.DisplayFor(i => item.XmlElement)
        </div>
        <div style="width: 300px; display: inline-block;">
            @itemValue
        </div>
        <div class="busoblist" style="display: inline-block;">
            @Html.DropDownListFor(i => item.BusinessObjectField, new SelectList(Model.BusinessObjectFields))
        </div>
        <hr />
    }

如果您查看上述代码生成的源代码,您会发现所有从上述代码生成的下拉菜单(select标签)具有相同的名称。因此,在提交表单时,它将无法正确绑定到您的模型。以下是一篇非常有用的博客文章,详细解释了这个问题。

http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/

更新

对于那些寻求将数据发布到列表的答案的人,我已经写了一篇博客文章。 http://amilaudayanga.wordpress.com/2014/03/05/posting-data-to-a-list-in-asp-net-mvc-part1/


1
只是补充一下:将foreach循环改为for循环,并使用老式的索引,你就可以继续了。 - Nilzor
@Html.Partial("_XmlFieldMapping") 你没有将模型传递给部分视图。你应该传递一个类型为CherwellXmlConnector.Models.XmlSchemaModelContainer的对象。 - Amila
请问您能否更新您的帖子,加上[HttpGet]创建操作以及如何创建XmlSchemaModelContainer实例。顺便问一下,更新后的循环是否目前生成任何HTML? - Amila
1
@Amila。我刚刚成功地解决了它。我太蠢了。在我对Partial所做的更改中,我实例化了一个新的MappedFields列表,因为我无法将索引应用于IEnumerable。然后我使用这个新列表来操作字段,但没有将其发送回去。我现在已经更改了我的XmLSchemaModel,使其具有MappedFields数组,并直接在部分循环中引用它。感谢您的时间和耐心 :) - Mark
1
没关系,我很高兴能够帮助。如果有时间的话,这是一个不错的博客主题。 - Amila
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接