@ Html.BeginCollectionItem与IValidatableObject和MemberName不匹配

时间:2013-09-30 21:07:49

标签: asp.net-mvc dynamic guid ivalidatableobject begincollectionitem

在使用Steven Sanderson的@Html.BeginCollectionItem帮助器时,我正在尝试使用IValidatableObject界面验证服务器端的集合项

我想阻止用户选择两个相同的项目。因此,例如,给定用户说话的习语列表,可以回发这些值:

English
English
Spanish

Validate实现如下所示:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    foreach(var idiom in Idioms)
    {
        if(Idioms.Any(i => i != idiom && i.Idiom == idiom.Idiom))
        {
            yield return new ValidationResult("Idiom already selected", new string[] { "Idiom" });
        }
    }
}

问题在于,传递给MemberName的{​​{1}}(“Idiom”)与ValidationResult字典中存在的MemberName不同,因为帮助者是史蒂文使用ModelState,看起来像这样:

Guid

你可以看到[42] = {[Idioms[83c2c6db-0157-42f3-bf3f-f7c9e6bc0a37].Idiom, System.Web.Mvc.ModelState]}

在最好的情况下,我必须有一种传递方式,例如Idiom != [Idioms[83c2c6db-0157-42f3-bf3f-f7c9e6bc0a37].Idiom作为[Idioms[83c2c6db-0157-42f3-bf3f-f7c9e6bc0a37].Idiom,但我不知道如何从MemberName获取此信息或即使这是可能的。无论如何,这必须是动态的。

你知道如何克服这个问题吗?

1 个答案:

答案 0 :(得分:0)

经过大量的谷歌搜索后,我找到了正确的方法来做我想要的事情:

Model Validation in ASP.NET MVC 3

要在ViewModel的集合/列表属性中验证(即找到重复的条目),您必须添加

@Html.ValidationMessageFor(u => u.Idioms)

表示View中的媒体资源,并在errorMessage方法中撰写Validate。最后将消息分配给正确的属性名称,即在我的情况下为Idioms

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
    var grouping = Idioms.GroupBy(ui => ui.Idiom);

    var duplicates = grouping.Where(group => group.Count() > 1);

    if(duplicates.Any())
    {
        string message = string.Empty;

        foreach(var duplicate in duplicates)
        {
             message += string.Format("{0} was selected {1} times", duplicate.Key, duplicate.Count());
        }

        yield return new ValidationResult(message, new[] { "Idioms" });
    }
}

<强>奖金

如果您想在separate lines中显示每个重复的组(添加换行符<br>),请执行以下操作:

{0} was selected {1} times替换为{0} was selected {1} times<br>

然后在View方面执行此操作:

@Html.Raw(HttpUtility.HtmlDecode(Html.ValidationMessageFor(u => u.Idioms).ToHtmlString()))

输出将是:

French was selected 2 times
English was selected 3 times