Working with a form where user should be able to uncheck pre selected checkbox and save that state on AJAX post through JSON object to the Controller in ASP.Net MVC
Requirement:
- Unchecking a pre selected checkbox should change a row in the database property from "Active" = 'Y' to "Active=" = 'N'
- Newly selected checkbox would create a complete new row in the db
Problem:
- After unchecking the selected text box Model is not updated in
VIEW. Hence serverside data is not updated. Requires a client side update before data is parsed intoAJAXcall. - Don't know how to capture the checkbox value change and pass it to the Model so that parsed data can then be changed to button click/submit form.
- Following code also gives error 200 because dataType is supposedly incorrect on submit (doing a button submit here).
View:
@model List<DashboardPermissionTool.ViewModels.UserViewModel>
@using (@Html.BeginForm(new { id = "UserForm" }))
{
<table class="table">
<tr>
<th>User</th>
@for (int i = 0; i < Model[0].Roles.Count; i++)
{
<th>
@Model[0].Roles[i].RoleName
</th>
}
</tr>
@for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
@Html.HiddenFor(m => m[i].UserName)
@Model[i].UserName
</td>
@for (int j = 0; j < Model[i].Roles.Count; j++)
{
<td>
@Html.CheckBoxFor(m => m[i].Roles[j].IsSelected)
</td>
}
</tr>
}
</table>
<div class="form-actions">
<a id="SubmitUserRoles" class="btn btn-success submit" value="Save">Save changes</a>
</div>
<script>
var parsedData = @Html.Raw( new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));
$(document).ready(function() {
$("#SubmitUserRoles").click(function () {
$('input[type=checkbox]').on("change",function(){
if($(this).prop('checked'))
{
$(this).attr('checked', false);
}
else
{
$(this).attr('checked', true);
}
});
$.ajax({
url: '@Url.Action("Create", "User")',
type: 'POST',
contentType: 'application/json; charset=utf-8',
cache: false,
dataType: 'json',
data: JSON.stringify(parsedData),
success: function (data) {
console.log(data);
}, error: function (xhr, ajaxOptions, error) {
alert(xhr.status);
alert("Error: " + xhr.responseText);
}
});
});
});
</script>
}
HTML Response: : For each selected check box Response is as follows:
<td>
<input checked="checked" data-val="true" data-val-required="The IsSelected field is required." name="[0].Roles[0].IsSelected" type="checkbox" value="true" />
<input name="[0].Roles[0].IsSelected" type="hidden" value="false" />
</td>
For each unchecked check box Response is as follows:
<td>
<input data-val="true" data-val-required="The IsSelected field is required." name="[0].Roles[1].IsSelected" type="checkbox" value="true" />
<input name="[0].Roles[1].IsSelected" type="hidden" value="false" />
</td>
ViewModels:
public class UserViewModel
{
public string UserName { get; set; }
public List<RoleViewModel> Roles { get; set; }
}
public class RoleViewModel
{
public string RoleName { get; set; }
public bool IsSelected { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(List<UserViewModel> model)
{
for (int i = 0; i < model.Count; i++)
{
for (int j = 0; j < model[i].Roles.Count; j++)
{
db.User.Add(new User
{
username = model[i].UserName,
role = model[i].Roles[j].RoleName
});
}
db.SaveChanges();
return RedirectToAction("Index", "User");
}
return View("Index", model);
}

data: $('form').serialize()and removecontentType: 'application/json; charset=utf-8',and it will all be sent and bound correctly (I'm assuming the model in the view isList<UserViewModel>). Although its a bit unclear why you would want to stay in the same page after the user has made the changesreturn RedirectToAction("Index", "User");andreturn View("Index", model);in the method is pointless - ajax calls do not redirect and your code will throw an exception because you specify the return type isjsonwhen your actually returninghtml$('input[type=checkbox]').on("change",function(){ ... }script (not clear what you think that is trying to do)return View("Index", model);be handled in theController?