I'm having difficulty writing a custom remote validator that will evaluate distinct pairs of fields from a list? The list has 2 fields that need to be validated: Description and Amount. This is my list.
@for (int i = 0; i < Model.MyList.Count(); i++)
{
@Html.TextBoxFor(m => m.MyList[i].Description)
@Html.TextBoxFor(m => m.MyList[i].Amount)
@Html.ValidationMessageFor(m => m.MyList[i].Description)
@Html.ValidationMessageFor(m => m.MyList[i].Amount)
}
The validation rules are as follows:
- Amount must be zero or greater. It cannot be blank.
- Description is required only when an amount is greater than zero.
- When description is entered, the amount must be greater than zero.
I've seen (and implemented) solutions like these, but they don't address this type of scenario of evaluating multiple distinct pairs of fields that are in a list.
- Multiple fields validation using Remote Validation
- how to use multiple AdditionalFields in remote validation - asp.net mvc
This is in my model. And the validation rules for Amount work. But the custom remote validator (ValidateDescriptionAmountPair) for Description fails.
[Range(0, int.MaxValue, ErrorMessage = "Amount must be 0 or greater.")]
[Required(ErrorMessage = "Amount is required.", AllowEmptyStrings = false)]
public decimal Amount { get; set; }
[Remote("ValidateDescriptionAmountPair", "MyController", AdditionalFields = "Amount")]
public string Description { get; set; }
This is my custom validator.
[HttpGet]
public virtual JsonResult ValidateDescriptionAmountPair(string Description, string Amount)
{
bool isOkay = true;
string reasonItsInvalid = string.Empty;
// TODO: Add code to evaluate business rules, and change
// isOkay and reasonItsInvalid accordingly.
if (isOkay)
{
return Json(true, JsonRequestBehavior.AllowGet);
}
else
{
return Json(reasonItsInvalid, JsonRequestBehavior.AllowGet);
}
}
I put a breakpoint in ValidateDescriptionAmountPair. This method gets called, but the Description and Amount values arrive as NULL rather than with expected values.
These are some markup examples for fields rendered in the view.
<input data-val="true" data-val-remote="'Description' is invalid." data-val-remote-additionalfields="*.Description,*.Amount" data-val-remote-url="/MyController/ValidateDescriptionAmountPair" id="MyList_0__Description" name="MyList[0].Description" type="text" value="Paid for this" aria-invalid="false">
<input class="form-control text-right" value="5000.00" data-val="true" data-val-number="The field Amount must be a number." data-val-range="Amount must be 0 or greater." data-val-range-max="2147483647" data-val-range-min="0" data-val-required="Amount is required." id="MyList_0__Amount" name="MyList[0].Amount" placeholder="Dollar Amount" style="width:100px;" type="text" aria-required="true" aria-invalid="false" aria-describedby="MyList_0__Amount-error">
<input data-val="true" data-val-remote="'Description' is invalid." data-val-remote-additionalfields="*.Description,*.Amount" data-val-remote-url="/MyController/ValidateDescriptionAmountPair" id="MyList_1__Description" name="MyList[1].Description" type="text" value="test" aria-invalid="false" aria-describedby="MyList_1__Description-error">
<input class="form-control text-right" value="10000.00" data-val="true" data-val-number="The field Amount must be a number." data-val-range="Amount must be 0 or greater." data-val-range-max="2147483647" data-val-range-min="0" data-val-required="Amount is required." id="MyList_1__Amount" name="MyList[1].Amount" placeholder="Dollar Amount" style="width:100px;" type="text" aria-required="true" aria-invalid="false" aria-describedby="MyList_1__Amount-error">
<input data-val="true" data-val-remote="'Description' is invalid." data-val-remote-additionalfields="*.Description,*.Amount" data-val-remote-url="/MyController/ValidateDescriptionAmountPair" id="MyList_2__Description" name="MyList[2].Description" type="text" value="Paid for that" aria-invalid="false">
<input class="form-control text-right" value="20000.00" data-val="true" data-val-number="The field Amount must be a number." data-val-range="Amount must be 0 or greater." data-val-range-max="2147483647" data-val-range-min="0" data-val-required="Amount is required." id="MyList_2__Amount" name="MyList[2].Amount" placeholder="Dollar Amount" style="width:100px;" type="text" aria-required="true" aria-invalid="false" aria-describedby="MyList_2__Amount-error">
What I think may be happening is that the names applied to list entries don't exactly match the "Description" and "Amount" parameter names in ValidateDescriptionAmountPair(), because they have indexes applied to the names. In other words, the field names are MyList[1].Description and MyList[1].Amount, but the ValidateDescriptionAmountPair() method is looking for Description and Amount. That's just a hunch which could be totally off base. If indeed that's why it fails, then what is the solution?
At any rate, I need to be able to implement the business rules noted above, and I would prefer to do this using an MVC data annotation or custom remote validation approach rather than hand-rolling some client-side jQuery to do this. Thanks for your help.