Reputation: 366
There are a few similar questions on here that I have checked but none seem to answer my issue, so here's hoping someone can help me out.
I have a form in a view, and a partial view I'm using like a subform. The Partial view is used to display an iList of items. (Screenshot below to show how this appears).
In the partial view, each item has a checkbox which the user can check to delete it. If I check the checkbox for the first item, the first item is removed from the list in code, but when the model is passed back to the View, the wrong item (the checked item) is the one that comes back.
So in the example below, if I check the first item (No Answer Delay = 18) and submit, that same item stays on the page whilst the other one (No Answer Delay = 10) disappears. If I then reload all the data, the correct item (No Answer Delay = 10) appears.
I have checked in the method that the correct data is being passed back, but the wrong item remains on the page. If I then refresh the page, the correct item appears. Note, the method has been sanitised a bit but the correct item does get removed them the database.
One other thing to note, this is a plugin to a 3rd party product so I cannot run it unless I publish to the other product, making debugging tricky.
The code for the main view is
@using(Html.BeginForm("SaveCallFeatures", "CallFeatures", FormMethod.Post, new { id = "CallFeatures", name = "CallFeatures" }))
{
@Html.AntiForgeryToken()
<div>
<h2>Call Features</h2>
<div class="form-panel">
<h4>Telephone Call Features</h4>
<div>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.phoneNumber, htmlAttributes: new { @class = "label" })
@Html.EditorFor(model => model.phoneNumber, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
@Html.ValidationMessageFor(model => model.phoneNumber, "", new { @class = "text-danger" })
</div>
<div>
@Html.LabelFor(model => model.password, htmlAttributes: new { @class = "label" })
@Html.EditorFor(model => model.password, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.password, "", new { @class = "text-danger" })
</div>
<div>
@Html.LabelFor(model => model.hideOutgoingCallerID, htmlAttributes: new { @class = "label" })
@Html.CheckBoxFor(model => model.hideOutgoingCallerID, new { htmlAttributes = new { @class = "form-control" } })
</div>
<div>
@Html.LabelFor(model => model.callWaiting, htmlAttributes: new { @class = "label" })
@Html.CheckBoxFor(model => model.callWaiting, new { htmlAttributes = new { @class = "form-control" } })
</div>
</div>
<div id="ForwardRules">
@Html.Partial("_ForwardingRules")
</div>
</div> //form
@Html.TextArea("Test")
<div id="form-buttons" class="col-md-offset-4 col-md-6">
<input type="button" value="Save" id="save-button" class="btn btn-primary" />
</div>
<script type="text/javascript">
$("#update-button").on('click', function () {
GetFwdRules();
});
</script>
function GetFwdRules() {
$.ajax
({
url: '@Url.Action("GetFwdRules", "CallFeatures", new { boid = Model.CompanyId })',
method: 'GET',
data: $("#CallFeatures").serialize(),
cache: false,
success: function (returnData) {
$("#ForwardRules").html(returnData);
$("#Test").html(returnData);
alert('GetFwdRules');
},
failure: function () {
alert('GetFwdRules Failure');
}
});
}
The code the the Partial View is
@model XXXXX.Models.CallFeaturesModel
<div class="form-panel">
<h4>Active Forwarding Rules</h4>
@for(int i = 0; i < Model.FwdRules.Count; i++)
{
<div>
@Html.HiddenFor(model => Model.FwdRules[i].ForwardingRuleID)
</div>
<div>
@Html.LabelFor(model => Model.FwdRules[i].Condition)
@Html.TextBoxFor(model => Model.FwdRules[i].Condition, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
</div>
<div>
@Html.LabelFor(model => Model.FwdRules[i].Destination)
@Html.TextBoxFor(model => Model.FwdRules[i].Destination, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
</div>
<div>
@Html.LabelFor(model => Model.FwdRules[i].NoAnswerDelay)
@Html.TextBoxFor(model => Model.FwdRules[i].NoAnswerDelay)
@Html.DescriptionFor(model => model.FwdRules[i].NoAnswerDelay)
</div>
<div>
@Html.LabelFor(model => Model.FwdRules[i].ToDelete)
@Html.CheckBoxFor(model => Model.FwdRules[i].ToDelete)
</div>
<br />
}
This is the method
[HttpGet]
public ActionResult GetFwdRules(CallFeaturesModel CFModel)
{
// Refresh the list to include on those where the ToDelete variable == false (checkbox is unchecked)
CFModel.FwdRules = CFModel.FwdRules.Where(x => x.ToDelete == false).ToList();
return PartialView("_ForwardingRules", CFModel);
}
And this is the model
public class CallFeaturesModel : UIPluginBaseModel
{
[Display(Name = "Phone Number")]
public string phoneNumber { get; set; }
[Display(Name = "Password")]
public string password { get; set; }
[Display(Name = "Hide Outgoing Caller ID")]
public bool hideOutgoingCallerID { get; set; }
[Display(Name = "Call Waiting")]
public bool callWaiting { get; set; }
[Display(Name = "Message")]
public string Message { get; set; }
public IList<ActiveForwardRule> FwdRules { get; set; }
}
public class ActiveForwardRule
{
[Display(Name = "Rule ID")]
public string ForwardingRuleID { get; set; }
[Display(Name = "Condition")]
public string Condition { get; set; }
[Display(Name = "Destination")]
public string Destination { get; set; }
[Display(Name = "No Answer Delay", Description = " seconds (approx. 6 seconds for each ring cycle)")]
public int NoAnswerDelay { get; set; }
[Display(Name = "Delete")]
public bool ToDelete { get; set; }
}
Here's a screenshot of the example. Looks like I'm not allowed to embed an image yet.
Hoping someone can point out where I am going wrong.
Upvotes: 3
Views: 572
Reputation: 7172
When posting data and then re-displaying data in the same request, the ModelState will be populated with the data from the original post.
This can lead to situations where items that should have been deleted still show or a form being pre-filled when it should now be blank.
Adding:
ModelState.Clear()
before re-displaying the data will clear down the model state and prevent the tag helpers from populating themselves from the original post request
Upvotes: 7