0

I have an object inside an IEnumerable of my model class, the rendered HTML looks like

<input data-val="true" data-val-number="The field money must be a number." data-val-remote="&amp;#39;money&amp;#39; is invalid." data-val-remote-additionalfields="*.money" data-val-remote-url="/RemoteValidator/ValidateMoney" data-val-required="The money field is required." id="BudgetDetails_0__BudgetData_Money" name="BudgetDetails[0].BudgetData.Money" type="text" value="100" />
<span class="field-validation-valid" data-valmsg-for="BudgetDetails[0].BudgetData.Money" data-valmsg-replace="true"></span>

The model classes look like

public class MyViewModel
{
    public IEnumerable<Budget> BudgetDetails { get; set; }
}

public class Budget
{
    public int SomeIdentifier { get; set; }
    public BudgetValues BudgetData { get; set; }
}

public class BudgetValues
{
    [Remote("ValidateMoney", "RemoteValidator")]
    public decimal? Money { get; set; }

    // other properties
}

View is

@model DictionaryAndRemote.Models.MyViewModel
<!DOCTYPE html>
<html>
<head>
    <title>Index</title>
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
    @using (Html.BeginForm())
    {
        @Html.EditorFor(x => x.BudgetDetails)
        <br />
        <input type="submit" value="Submit user Data" />
    }
</body>
</html>

The edit template Views\Shared\EditorTemplates\Budget.cshtml is

@model DictionaryAndRemote.Models.Budget
<div id="@Model.SomeIdentifier.ToString()">
    <div>
        @Html.TextBoxFor(x => x.BudgetData.Money)
        @Html.ValidationMessageFor(x => x.BudgetData.Money)
    </div>
</div>

The UI will trigger Ajax call http://localhost:4276/RemoteValidator/ValidateMoney?BudgetDetails%5B0%5D.BudgetData.Money=500 but unfortunately routing table is unable to match the request to my action method

    public ActionResult ValidateMoney(decimal money)
    {
        return Json("I will always fail you.", JsonRequestBehavior.AllowGet);
    }

Because the parameter name does not match. Since is is inside an IEnumerable the parameter name is even dynamic BudgetDetails[0].BudgetData.Money, BudgetDetails[1].BudgetData.Moneyand so on.

Of course I always can tweak action medhod to be

    public ActionResult ValidateMoney()
    {
        string parameter = Request.QueryString.ToString();
        return Json("I will always fail you.", JsonRequestBehavior.AllowGet);
    }

And use very primitive way to parse query string, but I don't think it is the most elegant solution.

Anybody has some experience to share?

hardywang
  • 4,864
  • 11
  • 65
  • 101

1 Answers1

0

Try this way.

public JsonResult ValidateMoney([Bind(Include = "Money")]BudgetValues budgetValues)
{
 if(null != budgetValues)
 {
  decimal money = budgetValues.Money 
 }
 return Json("I will always fail you.", JsonRequestBehavior.AllowGet); 
}
Zoli
  • 250
  • 2
  • 6
  • Does not work, because the incoming request contains `BudgetDetails%5b0%5d.BudgetData.Money=100`, for example, and it is never able to bind to `money` parameter, thus the value is always null. – hardywang Mar 01 '12 at 15:23
  • How is your ValidateMoney model? Just this simple BudgetValues class? What are do in the view? – Zoli Mar 01 '12 at 17:30
  • Nope, I tried and it did not work, the binding does not handle indexer properly, I guess. – hardywang Mar 02 '12 at 14:06