C# MVC 5通用列表绑定到局部视图

C# MVC 5通用列表绑定到局部视图,c#,asp.net-mvc-5,C#,Asp.net Mvc 5,我在将模型绑定到局部视图时遇到了一个问题,我觉得必须有一种方法来实现我想要的。我想知道我的设计是否有缺陷,可能需要进行一次小的重构 我的模型的一个非常简化(和抽象)的版本如下: Public Class BaseClass { Public string Name { get; set; } Public List<SomeClass> Things { get; set; } } Public Class DerivedClass : BaseClass {

我在将模型绑定到局部视图时遇到了一个问题,我觉得必须有一种方法来实现我想要的。我想知道我的设计是否有缺陷,可能需要进行一次小的重构

我的模型的一个非常简化(和抽象)的版本如下:

Public Class BaseClass
{
    Public string Name { get; set; }
    Public List<SomeClass> Things { get; set; }
}

Public Class DerivedClass : BaseClass
{
    Public List<LineItem> Items { get; set; }
}

Public Class Library
{
    Public List<LineItem> Items { get; set; }
}

Public Class LineItem
{
    Public string Name { get; set; }
    Public string Value { get; set; }
}
我刚刚注意到在呈现的Html中,SomeClass控件名为
SomeClass。[0]。Name
,而LineItem控件名为
[0]。Name
。我觉得这可能是这个问题的一个症状

我的观点与此相似:

DerivedClassEditor

@model DerivedClass

@using (Html.BeginForm())
{
    @Html.EditorFor(model => model)

    @Html.Partial("LineItemListPartialView")

    <input type="submit" />
}
@model-DerivedClass
@使用(Html.BeginForm())
{
@EditorFor(model=>model)
@Html.Partial(“LineItemListPartialView”)
}
LineItemListPartialView

@model List<LineItem>

<div name="Items">
    @Html.EditorFor(model => model)
</div>
@model LineItem

<div name="LineItem">
    @Html.LabelFor(model => model.Name)
    @Html.TextEditorFor(model => model.Name)
</div>
@型号列表
@EditorFor(model=>model)
LineItemPartialView

@model List<LineItem>

<div name="Items">
    @Html.EditorFor(model => model)
</div>
@model LineItem

<div name="LineItem">
    @Html.LabelFor(model => model.Name)
    @Html.TextEditorFor(model => model.Name)
</div>
@model行项目
@LabelFor(model=>model.Name)
@Html.TextEditorFor(model=>model.Name)
编辑

指向我的观点的链接:


我已经将问题缩小到这样一个事实:当我使用@Html.editor加载其中一个列表时,它命名输入
Collection[index].Property
,而当我使用相同的名称动态添加一个列表时,它只命名输入
Property
。有没有一种简单且可重复使用的方法使添加的新项目具有相同的命名结构?

关键是,您没有发布控制器代码,所以我在暗中捅了捅,但我想我可以很好地猜到发生了什么。您很可能有以下情况:

[HttpPost]
public ActionResult MyAwesomeAction(BaseClass model)
{
    ...
}
您假设,由于您的视图使用的是
DerivedClass
并发布
DerivedClass
,因此在您的操作中应该以
DerivedClass
的实例结束,而不是
BaseClass
。这种假设是不正确的

post上只存在一组字符串键值对。modelbinder查看动作签名并尝试将发布的数据绑定到参数实例,根据需要更新类。有鉴于此,modelbinder在该场景中拥有的唯一信息是,它需要将值绑定到
BaseClass
的一个实例和一组数据,以尝试这样做。因此,它将创建一个
BaseClass
实例,并绑定它可以绑定的数据,删除它不能绑定的任何数据。重要的是,由于
基类
不包括
属性之类的内容,因此所有这些数据都将被丢弃

长和短,操作参数不支持多态性。参数的类型必须是所需的类型。句号

值得一提的是,您可以为列表属性使用编辑器模板
EditorFor
只需为列表中的每个项目呈现包含类型的编辑器模板。例如,呼叫:

@Html.EditorFor(m => m.Items)
基本上与以下内容相同:

@for (var i = 0; i < Model.Items.Count(); i++)
{
    @Html.EditorFor(m => m.Items[i])
}
for(var i=0;im.Items[i]) }
因此,经过埃里克的大量研究、反复试验和帮助,我终于解决了我的问题。问题是在我的局部视图中表单元素的命名。当由模型添加时,它们的索引如下:
name=“ListProperty[Index].PropertyName”
。当我使用ajax添加局部视图时,这些视图仅以属性名命名。为了解决这个问题,我必须像下面这样处理对部分视图的ajax调用:

public ActionResult CreateParameter(Int32索引)
{
ViewData.TemplateInfo.HtmlFieldPrefix=$“参数[{index}]”;
返回PartialView(“~/Views/Shared/EditorTemplates/Configuration.cshtml”);
}

不幸的是,我就是这么做的。我的编辑器的模型是DerivedClass,控制器方法的参数也是。我将此添加到我的初始问题中以进行澄清。我无意中发现EditorFor使用了一个列表,谢谢您的分享。您上次关于命名的评论表明您不是使用EditorFor来呈现行项目,而是以某种方式使用了分部。您真的应该包含视图代码,这样我们就可以看到发生了什么。@ErikFunkenbusch,我将尝试添加一个我正在做的简化版本。我不想把问题问得太长。这是github中的实际视图:上面的代码与实际视图中的代码不同,您遗漏了一个关键部分,即使用子模型调用分部。这就是你的问题所在。执行此操作时,将丢失生成名称中模型命名的层次结构。我建议您传递基本模型(或者更确切地说,像您在示例中所做的那样,将其保留为空),然后让您的部分模型采用
DerivedClass
模型,而不是
列表
模型。这里的问题是,局部视图不理解它的模型是更大视图模型的一部分,因此它不会为它生成名称。谢谢Erik,我如何继续这样做,并且仍然保持局部视图的通用性,以同时处理库对象?