1

当 ViewModel 是(具有)集合时,是否可以将 ViewModel 属性与匹配的 ModelState.Key 值匹配?

示例:要编辑视图模型项的集合,我使用的是在此处找到的扩展

这会将 GUID 添加到页面上字段的 id 中。

例子:

class Pets
{
    string animal;
    string name;
}

对于 Pets 列表,生成的 html 源代码如下:

<input name="Pets.index" autocomplete="off" value="3905b306-a9..." type="hidden">
<input value="CAT" id="Pets_3905b306-a9...__animal" name="Pets[3905b306-a9...].animal" type="hidden">
<input value="MR. PEPPERS" id="Pets_3905b306-a9...__name" name="Pets[3905b306-a9...].name" type="hidden">


<input name="Pets.index" autocomplete="off" value="23342306-b4..." type="hidden">
<input value="DOG" id="Pets_23342306-b4...__animal" name="Pets[23342306-b4...].animal" type="hidden">
<input value="BRUTICUS" id="Pets_23342306-b4...__name" name="Pets[23342306-b4...].name" type="hidden">

因此,当它在 post 上绑定时,ModelState 会加载所有表单字段。在 ModelSTate.Keys 中,有:

Pets[23342306-b4...].name
Pets[23342306-b4...].animal
Pets[3905b306-a9...].name
Pets[3905b306-a9...].animal

到目前为止一切都很好,但是我正在做一些业务逻辑验证,例如,如果存在同名的动物,则无法添加新动物。在这种情况下,我希望能够突出显示错误的输入字段。

因此,如果我的 create 函数失败,它将返回一个错误/键值对,如下所示:

{ error = "Duplicate Name", key="name" }

所以我至少现在会是什么属性导致了这个问题。

但是由于我的存储库函数不知道视图字段 id,我如何将键“名称”与适当的 ModelState 键匹配(在这种情况下,Pets[23342306-b4...].name 或 Pets[3905b306 -a9...].name)?

4

2 回答 2

0

如果您像我一样使用 Html.BeginCollectionItem 扩展方法,我可以通过不使用 GUID 来解决这个问题。我需要动态添加和删除,但我一直在查找已知项目,即具有 ID 的人,我在编辑器中拥有这些 ID。因此,我没有使用 GUID,而是在下面的代码中分配了 ID (uniqueId)。然后我可以找到密钥,因为我知道它是 Person[234232]。当然,如果您要添加新项目而不显示所选项目,它可能不适合您。

        public static IDisposable BeginCollectionItem(this HtmlHelper html, string collectionName, string uniqueId)
    {
        var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
        string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : uniqueId;

        // autocomplete="off" is needed to work around a very annoying Chrome behaviour whereby it reuses old values after the user clicks "Back", which causes the xyz.index and xyz[...] values to get out of sync.
        html.ViewContext.Writer.WriteLine(string.Format("<input type=\"hidden\" name=\"{0}.index\" autocomplete=\"off\" value=\"{1}\" />", collectionName, html.Encode(itemIndex)));

        return BeginHtmlFieldPrefixScope(html, string.Format("{0}[{1}]", collectionName, itemIndex));
    }
于 2013-04-03T21:21:17.903 回答
0

如果您使用 MVC 的内置功能通过适当的显示/编辑器模板显示集合(Html.DisplayFor(m => m.Pets)Html.EditorFor(m => m.Pets)),MVC 将呈现如下内容:

Pets[0].name
Pets[0].animal
Pets[1].name
Pets[1].animal

这映射到IEnumerable<Pets>并且您知道第一项的索引为 0,第二项的索引为 1,依此类推。

因此,如果第二项有错误,您可以为ModelState键设置错误"Pets[1].name",例如。

于 2012-10-13T09:31:07.397 回答