0

I have a container that I populate from a ajax call that returns a PartialView of a list. I have 2 calls: CreateSplitInput and RemoveSplit.

The call to the controller seems to work and the model passed to the partial view is correct with the right child list. During debug, it would appear that the view would return back the correct html.

Adding new inputs I have no problems... removing the input item only "pops" the last item of the list.


UPDATE: MVC will check the ModelState first THEN the Model. I needed to add ModelState.Clear() in my RemoveSplit controller method.

Credit to awrigley MVC 3 + $.ajax - response seems to be caching output from partial view


TIA!!!

Model:

public class Split
{
    public int SplitID { get; set; }
    public int ClientProfileID { get; set; }
    public int CoveredPersonID { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }

    public virtual List<SplitPercent> Percentages { get; set; }
}

public class SplitPercent
{
    public int SplitPercentID { get; set; }
    public int SplitID { get; set; }
    public string PremiumKeyField { get; set; }
    public decimal Percentage { get; set; }
}

Controller:

public ActionResult CreateSplitInput(Split model)
    {
        if (model.Percentages == null)
            model.Percentages = new System.Collections.Generic.List<SplitPercent>();
        model.Percentages.Add(new SplitPercent());
        return PartialView("~/views/clients/_SplitPercentages.cshtml", model);
    }

public ActionResult RemoveSplit(Split model, int index)
    {
        ModelState.Clear(); // <== HERE IS THE ANSWER!!!!!
        if (model.Percentages != null && model.Percentages.Count >= (index + 1))
        {
            model.Percentages.RemoveAt(index);
        }
        return PartialView("~/views/clients/_SplitPercentages.cshtml", model);
    }

Javascrpt:

function addSplit() {
        if (true) { // testing purposes
            $.ajax({
                url: '/clients/CreateSplitInput',
                data: $("#frm").serialize(),
                cache: false,
                success: function(resp) {
                    setSplitContainer(resp);
                },
                error: function(err, status) {
                    alert(status);
                }
            });
        }
    }

function removeSplit(indx) {
        if (true) { // testing purposes
            $.ajax({
                url: '/clients/RemoveSplit/?index=' + indx,
                data: $("#frm").serialize(),
                cache: false,
                type: 'GET',
                success: function(resp) {
                    //debugger;
                    setSplitContainer(resp); //<-- the resp html just has the last item popped off
                },
                error: function(err, status) {
                    alert(status);
                }
            })
        }           
    }

function setSplitContainer(h) {
        $("#splitPercents").html(h);
        $("select").chosen(chosenOpts);
    }

_SplitPercentages.cshtml PartialView: Debugging this shows the correct Percentages collection... appears to bind correctly.

@model BillingWeb.Models.Split


@if (Model != null && Model.Percentages != null)
{
    var logic = new ClientLogic();
    var premiumKeys = logic.GetAllPremiumKeyFields(Model.ClientProfileID);
    string test = "";

    int index = 0;
    foreach (var percent in Model.Percentages)
    {
        test += ", " + percent.PremiumKeyField; // <- collect the model data to show at the end
        var selectList = new SelectList(premiumKeys, percent.PremiumKeyField); // Trying anything now...

        <div class="form-group">
            @Html.Hidden("Percentages.Index", index)
            @Html.Hidden(string.Format("Percentages[{0}].SplitID", index), percent.SplitID)

            <div class="col-md-5 col-lg-5">
                @Html.DropDownListFor(m => m.Percentages[index].PremiumKeyField, selectList, new { @class = "form-control" })
            </div>
            <div class="col-md-4 col-lg-4">
                <div class="input-group">
                    <span class="input-group-addon">%</span>
                    @Html.TextBoxFor(m => m.Percentages[index].Percentage, new { @class = "form-control text-right", placeholder = "Split %" })
                    <button type="button" class="btn btn-danger input-group-addon" onclick="removeSplit(@index)">
                        <span class="glyphicon glyphicon-remove"></span>
                    </button>
                </div>
            </div>
        </div>

        index++;
    }
    <p>@test</p> <!-- WTH?! this works? -->
}

Main View:

@model BillingWeb.Models.Split

    <div class="form-group">
        <label class="control-label col-md-2">Percentages</label>
        <div class="col-md-8">
            <div id="splitPercents">
                @Html.Partial("~/Views/Clients/_SplitPercentages.cshtml", Model)
            </div>
            <button type="button" class="btn btn-primary" onclick="addSplit()">Add Split</button>
        </div>
    </div>
Community
  • 1
  • 1
alex.davis.dev
  • 411
  • 7
  • 18

1 Answers1

0

After more digging, I found that MVC will check the ModelState first THEN the Model.

Credit: awrigley's response to MVC 3 + $.ajax - response seems to be caching output from partial view

Community
  • 1
  • 1
alex.davis.dev
  • 411
  • 7
  • 18