0

在使用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传递给的 ("Idiom")与字典中的现在ValidationResult不同,因为 Steven 的助手使用's 并且看起来像这样:MemberNameModelStateGuid

[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].IdiomMemberName但我不知道如何从 the 中获取此信息,validationContext或者即使有可能。无论如何,这必须是动态的。

你知道有什么办法可以克服这个吗?

4

1 回答 1

0

After a lot of Googling I found the right way of doing what I want:

Model Validation in ASP.NET MVC 3

To validate (ie. find duplicate entries) in a collection/list property in your ViewModel you must add a

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

for the property in your View and compose the errorMessage inside the Validate method. Finally assign the message to the correct property name, that is, Idioms in my case.

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" });
    }
}

BONUS

If you want to display each duplicate group in separate lines (adding line breaks <br>), do this:

Replace {0} was selected {1} times with {0} was selected {1} times<br>

and then on the View side do this:

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

Output will be:

French was selected 2 times
English was selected 3 times
于 2013-10-01T20:27:21.307 回答