Here is my model class:
public class MyModel { public Employees[] MyEmpls{get;set;} public int Id{get;set;} public OrgName{get;set;} }
Passing the below JSON structure object with MyEmpls as empty array
to MVC controller.
["Id":12, "MyEmpls":[], "OrgName":"Kekran Mcran"]
Controller
[HttpPost] public ActionResult SaveOrg(MyModel model) { //model.MyEmpls is null here }
I am expecting mode.MyEmpls
to be an empty c# array, not a null. Is a custom model binder necessary to achieve an empty array?
if we send any json object from JavaScript to asp.net mvc controller action method json object can directly bind to strongly typed . net object (model or viewmodel in asp.net mvc) automatically, provider will take care validations, serializing, de-serializing values etc.
Model binding is a well-designed bridge between the HTTP request and the C# action methods. It makes it easy for developers to work with data on forms (views), because POST and GET is automatically transferred into a data model you specify. ASP.NET MVC uses default binders to complete this behind the scene.
MVC doesn't use data bindings like old web api. You have to use model bindings in a MVC or MVVM approach.
Model binding allows controller actions to work directly with model types (passed in as method arguments), rather than HTTP requests. Mapping between incoming request data and application models is handled by model binders.
I think that some of the other answers have missed the meaning of the question: why does the default MVC model binder bind an empty Json array to null instead of an empty C# array?
Well, I can't tell you why they did that, but I can show you where it happens. The source for MVC can be found on CodePlex here: http://aspnetwebstack.codeplex.com/SourceControl/latest. The file you're looking for is ValueProviderResult.cs where you can see:
private static object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType) { if (value == null || destinationType.IsInstanceOfType(value)) { return value; } // array conversion results in four cases, as below Array valueAsArray = value as Array; if (destinationType.IsArray) { Type destinationElementType = destinationType.GetElementType(); if (valueAsArray != null) { // case 1: both destination + source type are arrays, so convert each element IList converted = Array.CreateInstance(destinationElementType, valueAsArray.Length); for (int i = 0; i < valueAsArray.Length; i++) { converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType); } return converted; } else { // case 2: destination type is array but source is single element, so wrap element in array + convert object element = ConvertSimpleType(culture, value, destinationElementType); IList converted = Array.CreateInstance(destinationElementType, 1); converted[0] = element; return converted; } } else if (valueAsArray != null) { // case 3: destination type is single element but source is array, so extract first element + convert if (valueAsArray.Length > 0) { value = valueAsArray.GetValue(0); return ConvertSimpleType(culture, value, destinationType); } else { // case 3(a): source is empty array, so can't perform conversion return null; } } // case 4: both destination + source type are single elements, so convert return ConvertSimpleType(culture, value, destinationType); } }
The interesting part is "case 3":
else { // case 3(a): source is empty array, so can't perform conversion return null; }
You can sidestep this issue by initialising your array on the model in its constructor. In my quick reading of the source I can't tell you why they can't return an empty array or why they decide not to, but it should make for interesting reading.
You're getting a null value as this is the default value for a reference type in C#. In order to get an empty array you will need to initialise the array in your model using a constructor. However as you will need to define the size of the array when it's initialized it might be better using another type of collection such as a List
:
public class MyModel { public List<Employees> MyEmpls{get;set;} public int Id{get;set;} public OrgName{get;set;} public MyModel() { MyEmpls = new List<Employees>(); } }
You will then get an empty list when an empty array is passed from the json.
If you really have to use an array just initialise it with a size:
public class MyModel { public Employees[] MyEmpls{get;set;} public int Id{get;set;} public OrgName{get;set;} public MyModel() { MyEmpls = new Employees[/*enter size of array in here*/]; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With