MVC 3 ненавязчивая проверка списка


Вопрос

Я создал атрибут проверки уровня свойств на стороне сервера. Но вместо того, чтобы применить его к отдельному полю, я применил его к списку. Это позволяет мне проверить модель в целом.

Теперь мне нужно знать, как преобразовать это в работу, используя ненавязчивую проверку на стороне клиента, встроенную в MVC 3.

Мой текущий код приведен ниже, чтобы проиллюстрировать мою проблему...

Сценарий

Основным сценарием был возможность суммировать все значения количества для каждой строки в списке, сгруппированном по полю GroupNo. Если сумма любой из групп была больше 10, то должна быть отображена ошибка.

Мне любезно дали ответ в предыдущем посте, чтобы сделать эту работу на стороне сервера, используя атрибут проверки против списка...

Модель:

public class ItemDetails
{
    public int SerialNo { get; set; }
    public string Description { get; set; }
    public int GroupNo { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}

public class MyViewModel
{
    [EnsureMaxGroupItems(10, ErrorMessage = "You cannot have more than 10 items in each group")]
    public IList<ItemDetails> Items { get; set; }
}

И сам атрибут проверки:

[AttributeUsage(AttributeTargets.Property)]
public class EnsureMaxGroupItemsAttribute : ValidationAttribute
{
    public int MaxItems { get; private set; }

    public EnsureMaxGroupItemsAttribute(int maxItems)
    {
        MaxItems = maxItems;
    }

    public override bool IsValid(object value)
    {
        var items = value as IEnumerable<ItemDetails>;
        if (items == null)
        {
            return true;
        }

        return items
            .GroupBy(x => x.GroupNo)
            .Select(g => g.Sum(x => x.Quantity))
            .All(quantity => quantity <= MaxItems);
    }
}

И, наконец, ваши действия контроллера будут работать с представлением модель:

public ActionResult ListItems()
{
    var model = new MyViewModel
    {
        Items = ItemsRepository.GetItems()
    };
    return View(model);
}

[HttpPost]
public ActionResult ListItems(MyViewModel model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    ...
}

И далее соответствующее строго типизированное представление:

@model MyViewModel
@Html.ValidationSummary()
@using (Html.BeginForm())
{
    @Html.EditorFor(x => x.Items)
    <button type="submit">Go go go</button>
}

И последний бит-это соответствующий шаблон редактора, который будет автоматически отображаться для каждого элемента коллекции элементов, так что вам даже не нужно писать для циклов (~/Views/Shared/EditorTemplates/ItemDetails.cshtml):

@model ItemDetails
@Html.HiddenFor(x => x.SerialNo)
@Html.LabelFor(x => x.Description)
@Html.HiddenFor(x => x.GroupNo)
@Html.LabelFor(x => x.Price)
@Html.TextBoxFor(x => x.Quantity)

Возможна ли ненавязчивая проверка на стороне клиента?

Я хотел бы, чтобы все это проверялось с помощью ненавязчивой проверки MVC. Но я не могу понять, как ненавязчиво подтвердить Атрибут EnsureMaxGroupItemsAttribute для списка в целом.

Я реализовал IClientValidatable следующим образом:

    Public Function GetClientValidationRules(metadata As System.Web.Mvc.ModelMetadata, context As System.Web.Mvc.ControllerContext) As System.Collections.Generic.IEnumerable(Of System.Web.Mvc.ModelClientValidationRule) Implements System.Web.Mvc.IClientValidatable.GetClientValidationRules

        Dim result = New List(Of ModelClientValidationRule)

        Dim rule = New ModelClientValidationRule() With { _
            .ErrorMessage = "You cannot have more than 10 items in each group", _
            .ValidationType = "itemscheck"}

        result.Add(rule)

        Return result

    End Function

Примечание: сочетание VB и C# происходит только потому, что на предыдущий вопрос, который я задал, был дан ответ на C#. Проект находится в VB, но я не возражаю против ответа в C#.

Я создал адаптер в своем js-файле:

jQuery.validator.unobtrusive.adapters.addBool("itemscheck"); 

... и...

jQuery.validator.addMethod("itemscheck", function (value, element, params) {
    // The check has been omitted for the sake of saving space.  
    // However this method never gets called
    return false;
});
Есть ли способ подключить это к работе ненавязчиво?
1 5

1 ответ:

Это невозможно, поскольку пользовательский атрибут помещается в свойство collection, а атрибуты HTML5 data-* вообще не создаются. Этот сценарий не поддерживается ненавязчивой клиентской платформой проверки. Вы можете написать непосредственно пользовательское правило проверки jquery для обработки этого сценария, если вам нужна проверка клиента для него.