GPGVM GPGVM - 18 days ago 5
Ajax Question

Ajax post to MVC controller List<T> properties correct count but null

In MVC using Telerik MultiSelect control I am posting back to the controller via ajax. My data is correct but I am missing some connection on how to get the POST action to interpret the ajax data parameter as it is always the correct number of elements but they are null.

My model:

public class SeeAlso
{
public List<SubCategories> SelectedCategories { get; set; }
public List<SubCategories> AvailableCategories { get; set; }
}


My Controller

[AcceptVerbs(HttpVerbs.Post)]
public async Task<ActionResult> SeeAlso_Update(SeeAlso data)
{
if (data != null && ModelState.IsValid)
{...}
}


My cshtml:

<h2>See Also</h2>

@using (Html.BeginForm())
{
<label for="required">Selected</label>
@(Html.Kendo().MultiSelect()
.Name("SeeAlso")
.Placeholder("Selected Categories...")
.BindTo(Model.AvailableCategories.Select(x => x.SubCategoryName).ToList())
.Value(Model.SelectedCategories.Select(c => c.SubCategoryName).ToArray())
.Events(e => { e.Change("onChange"); })
)
}

<script type="text/javascript">
function onChange()
{
$.ajax({
url: "/Admin/SeeAlso/SeeAlso_Update",
type: "POST",
async: true,
dataType: "json",
contentType: "application/json",

data: JSON.stringify({ SelectedCategories: $("#SeeAlso").data("kendoMultiSelect").dataItems() })

});

}

</script>


And when I post is always gets the count right but the value is null.

enter image description here

As requesteed here is the json which I know is close but I don't know how to get the parent SeeAlso container represented.

{"SelectedCategories":["Cat1","Cat2"]}

Answer

You cannot bind a <select multiple> to a collection of complex objects (it posts back only and array of the values of the selected options) so the property you need to bind to needs to be IEnumerable<string> (assuming SubCategoryName is typeof string). You view model needs to be

public class SeeAlso
{
    public IEnumerable<string> SelectedCategories { get; set; }
    public List<SubCategories> AvailableCategories { get; set; }
}

To submit the model using ajax, you can simply serialize the form

$.ajax({
    url: "/Admin/SeeAlso/SeeAlso_Update",
    type: "POST",
    dataType: "json",
    data: $('form').serialize();
});

which will correctly bind to

[HttpPost]
public ActionResult SeeAlso_Update(SeeAlso model)

and model.SelectedCategories will be an array of the selected option values.

Refer this DotnetFiddle for an example of creating and binding a listbox (Kendo MultiSelect is just a wrapper around the ListBox() method so the result will be the same)