Reputation: 3
I have been struggling to get this post to work in my project. Bascially, I am passing a list of Install objects ( an install object contains a list of Facility objects) to my controller. I have yet to get the binding to work successfully. I have been able to get the count of list items to reflect the number of items passed to the controller, however none of the properties are being set in the individual objects.
Here is the code that performs the post:
$("#OpenFacilityResults").button().click(function () {
var installHolder = {
InstallList: []
}
var foundInstall = false
$('.FullExport').each(function () {
//var Install = { InstallRecnum: 0, FacilityList: [Facility, Facility] }
//var Facility = { ID: 0, Product: 0 }
if ($(this).prop('checked')) {
var substr = $(this).parent().find('input:hidden').val().split('|');
var fac = {
ID: substr[1],
Product: substr[2]
}
foundInstall = false
$.each(installHolder.InstallList, function (index, value) {
if (value.InstallRecnum == substr[0]) {
foundInstall = true
installHolder.InstallList[index].FacilityList.push(fac);
}
});
if (foundInstall == false) {
var i = {
InstallRecnum: substr[0],
FacilityList: []
}
i.FacilityList.push(fac)
installHolder.InstallList.push(i)
}
}
});
console.log(JSON.stringify(installHolder));
var dataHolder = JSON.stringify(installHolder)
$.ajax({
url: '@Url.Action("ViewFacilityDetails", "CHI")',
type: 'POST',
dataType: 'json',
data: dataHolder,
contentType: 'application/json',
success: function (data) {
// get the result and do some magic with it
}
});
});
Here is what the JSON looks like:
{"InstallList":[{"InstallRecnum":"140","FacilityList":[{"ID":"0","Product":"1"}]},{"InstallRecnum":"138","FacilityList":[{"ID":"0","Product":"1"}]}]}
Here is the controller action:
Function ViewFacilityDetails(ByVal InstallList As List(Of InstallInputModel)) As ActionResult
Return Json(InstallList)
End Function
And the objects that I am attempting to bind:
<Serializable()> _
Public Class InstallInputModel
Public InstallRecnum As Integer
Public FacilityList As List(Of FacilityInputModel)
End Class
<Serializable()> _
Public Class FacilityInputModel
Public ID As Integer
Public Product As Integer
End Class
Any help would be much appreciated - thanks in advance!
UPDATE
Here is the working code to accomplish this:
Custom model binder:
Public Class JsonBinder
Implements IModelBinder
Public Function BindModel(controllerContext As System.Web.Mvc.ControllerContext, bindingContext As System.Web.Mvc.ModelBindingContext) As Object Implements System.Web.Mvc.IModelBinder.BindModel
If controllerContext Is Nothing Then
Throw New ArgumentNullException
End If
If bindingContext Is Nothing Then
Throw New ArgumentNullException
End If
Dim request = controllerContext.HttpContext.Request
request.InputStream.Seek(0, IO.SeekOrigin.Begin)
Dim jsonString = New StreamReader(request.InputStream).ReadToEnd
If Not jsonString Is Nothing Then
Dim deserializer As New System.Web.Script.Serialization.JavaScriptSerializer
Dim result = deserializer.Deserialize(Of InstallInputModelHolder)(jsonString)
Return result
Else
Return Nothing
End If
End Function
End Class
*Gloabl.asax.vb addition *
ModelBinders.Binders.Add(GetType(InstallInputModelHolder), New JsonBinder())
I'll most likely change the JSON so it can just pass the array and an extra container class won't be needed to deserialize the JSON.
Upvotes: 0
Views: 369
Reputation: 1538
Create a ModelBinder that will bind your Jsonstring to an List(of InstallInputModel) and register it in global.asax
Off the top of my head (C#):
public class JsonBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//return base.BindModel(controllerContext, bindingContext);
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (bindingContext == null)
{
throw new ArgumentNullException("bindingContext");
}
// Get the JSON data that's been posted
var request = controllerContext.HttpContext.Request;
request.InputStream.Seek(0, SeekOrigin.Begin);
var jsonString = new StreamReader(request.InputStream).ReadToEnd();
if (jsonString != null)
{
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize(jsonString, typeof(List<InstallInputModel>));
return result;
}
else
{
return null;
}
}
}
In the Application_Start of Global.asax, add:
ModelBinders.Binders.Add(typeof(List<InstallInputModel>), new JsonBinder());
Upvotes: 1