Why does the ASP.Net MVC model binder bind an empty JSON array to null?
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*/];
}
}