views:

165

answers:

1

I have a list of objects that are organized in a tree using a Depth property:

public class Quota
{
    [Range(0, int.MaxValue, ErrorMessage = "Please enter an amount above zero.")]
    public int Amount { get; set; }

    public int Depth { get; set; }

    [Required]
    [RegularExpression("^[a-zA-Z]+$")]
    public string Origin { get; set; }

    // ... another properties with validation attributes
}

For data example (amount - origin)

100 originA
200 originB
    50 originC
    150 originD

the model data looks like:

IList<Quota> model = new List<Quota>();
model.Add(new Quota{ Amount = 100, Depth = 0, Origin = "originA");
model.Add(new Quota{ Amount = 200, Depth = 0, Origin = "originB");
model.Add(new Quota{ Amount = 50,  Depth = 1, Origin = "originC");
model.Add(new Quota{ Amount = 150, Depth = 1, Orinig = "originD");

Editing of the list

Then I use Editing a variable length list, ASP.NET MVC 2-style to raise editing of the list.

Controller actions QuotaController.cs:

public class QuotaController : Controller
{
    //
    // GET: /Quota/EditList
    public ActionResult EditList()
    {
        IList<Quota> model = // ... assigments as in example above;

        return View(viewModel);
    }

    //
    // POST: /Quota/EditList
    [HttpPost]
    public ActionResult EditList(IList<Quota> quotas)
    {
        if (ModelState.IsValid)
        {
            // ... save logic
            return RedirectToAction("Details");
        }
        return View(quotas); // Redisplay the form with errors
    }

    // ... other controller actions
}

View EditList.aspx:

<%@ Page Title="" Language="C#" ... Inherits="System.Web.Mvc.ViewPage<IList<Quota>>" %>

...
<h2>Edit Quotas</h2>
<%=Html.ValidationSummary("Fix errors:") %>
<% using (Html.BeginForm()) { 
     foreach (var quota in Model)
     {
         Html.RenderPartial("QuotaEditorRow", quota);
     } %>
<% } %>
...

Partial View QuotaEditorRow.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Quota>" %>

<div class="quotas" style="margin-left: <%=Model.Depth*45 %>px">
    <% using (Html.BeginCollectionItem("Quotas")) { %>
        <%=Html.HiddenFor(m=>m.Id) %>
        <%=Html.HiddenFor(m=>m.Depth) %>


        <%=Html.TextBoxFor(m=>m.Amount, new {@class = "number", size = 5})%>
        <%=Html.ValidationMessageFor(m=>m.Amount) %>

        Origin:
        <%=Html.TextBoxFor(m=>m.Origin)%>
        <%=Html.ValidationMessageFor(m=>m.Origin) %>

        ...
    <% } %>
</div>

Business rule validation

  1. How do I implement validation of business rule: Amount of quota should equal to sum of amounts of its nested quotas (e.a. 200 = 50 + 150 in example)?

  2. I want appropriate inputs Html.TextBoxFor(m=>m.Amount) to be highlighted in red, if the rule is broken for it. In example if user enters not 200, but 201 - it should be red on submit.

  3. Using sever validation only.

Thanks a lot for any advise.

+1  A: 

Try FluentValidation. It is a very simple and powerful validation framework that is able to validate your classes based on rules. It can also be used to generate ClientSide JQuery Validators

The result of validating an object is a list of ValidationFailue objects. You can iterate these or bind them to a repeater which contains an unordered list which is formatted in red.

IList<ValidationFailure> failures = results.Errors;
Daniel Dyson
But what about highlighting of broken fields?
SergeanT
See edited answer
Daniel Dyson
`failures` is a local variable. What shall I do with it next?
SergeanT
I want to use build in `HtmlHelper`'s highlighting without any looping at all. Just bind and it's all. How to bind?
SergeanT