MVC 3 Unobtrusive Checklist

Question

I created a server side property level validation attribute. But instead of applying it to a single field, I applied it to a list. This allows you to check the model as a whole.

Now I need to know how to convert this to work using the unobtrusive client-side validation built into MVC 3.

My current code is below to illustrate my problem ...

Scenario

The main scenario was the ability to sum all quantity values ​​for each row in a list grouped by GroupNo field. If the sum of any of the groups was more than 10, then an error should be displayed.

I was asked to answer in a previous article to do this server-side work using the validation attribute for a list ...

Model:

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

and the validation attribute itself:

[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>
}

- , Items, (~/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 # , , , #. VB, #.

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

, ?

+5
1

, , HTML5 data-* . . jquery validate , .

+4

All Articles