Il passaggio della matrice js vuota al controller dà null

Ecco il mio modello che è una class Proxy WCF

public class MyModel { public Employees[] MyEmpls{get;set;} public int Id{get;set;} public OrgName{get;set;} } 

Passando un object struttura sotto json con MyEmpls as empty array al controller MVC.

 ["Id":12, "MyEmpls":[], "OrgName":"Kekran Mcran"] 

controllore

 [HttpPost] public ActionResult SaveOrg(MyModel model) { //model.MyEmpls is null here } 

Mi aspetto mode.MyEmpls come array c # vuoto e non null. Qualcuno potrebbe aiutarmi qui? Abbiamo bisogno di scrivere un raccoglitore di modelli personalizzato per questo?

Penso che alcune delle altre risposte abbiano perso il significato della domanda: perché il raccoglitore modello MVC predefinito associa una matrice Json vuota a null invece di un array C # vuoto?

Beh, non posso dirti perché l’hanno fatto, ma posso mostrarti dove succede. La fonte per MVC può essere trovata su CodePlex qui: http://aspnetwebstack.codeplex.com/SourceControl/latest . Il file che stai cercando è ValueProviderResult.cs dove puoi vedere:

  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); } } 

La parte interessante è “caso 3”:

 else { // case 3(a): source is empty array, so can't perform conversion return null; } 

Puoi aggirare questo problema inizializzando la tua matrice sul modello nel suo costruttore. Nella mia rapida lettura della fonte non posso dirti perché non possono restituire un array vuoto o perché decidono di non farlo, ma dovrebbe essere una lettura interessante.

Stai ottenendo un valore nullo poiché questo è il valore predefinito per un tipo di riferimento in C #. Per ottenere un array vuoto è necessario inizializzare l’array nel modello usando un costruttore. Tuttavia, poiché è necessario definire la dimensione dell’array quando è inizializzato, potrebbe essere meglio utilizzare un altro tipo di raccolta come una List :

 public class MyModel { public List MyEmpls{get;set;} public int Id{get;set;} public OrgName{get;set;} public MyModel() { MyEmpls = new List(); } } 

Otterrai quindi una lista vuota quando un array vuoto viene passato da JSON.

Se davvero devi usare una matrice, inizializza semplicemente con una dimensione:

 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]; } } 

Se si ottiene model.MyEmpls come null, è ansible creare una condizione sul lato server per interrompere l’aumento di un’eccezione come:

 if(model.MyEmpls !=null){ ... } 

E lo stai rendendo nullo perché MyEmpls è un array di classi personalizzate e stai inviando solo [].

Spero che questo ti aiuti.

Prova a creare un raccoglitore modello come in seguito

 public class MyModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { try { var request = controllerContext.HttpContext.Request; return new MyModel { MyEmpls = request[] ?? new Employees[0], Id = request["Id"] ?? "", OrgName = request["OrgName"] ?? "" }; } catch { //do required exception handling } } } 

In Application_Start registrare il modello legante

 ModelBinders.Binders.Add(typeof(MyModel), new MyModelBinder()) 

E modificare il controller come

 [HttpPost] public ActionResult SaveOrg([ModelBinder(typeof(MyModelBinder))] MyModel model) { //model.MyEmpls is null here } 
 [HttpPost] public ActionResult SaveOrg(MyModel model) { var serializer = new JavaScriptSerializer(); var stream = System.Web.HttpContext.Current.Request.InputStream; var reader = new StreamReader(stream); stream.Position = 0; var json = reader.ReadToEnd(); model= serializer.Deserialize(json); //model.MyEmpls is [] here } 

JavaScriptSerializer deserializza correttamente gli array vuoti. Quindi puoi ignorare il modello passato e ricostruirlo dal stream di richiesta di input. Probabilmente non è il modo corretto, ma se hai solo bisogno di farlo una volta si risparmia qualche sforzo. Avrai bisogno di fare riferimento a System.Web.Extensions.

Il comportamento predefinito dell’inizializzazione dell’array C # è l’array null non vuoto

Quindi se si invia un array vuoto non si avvierà un array vuoto, ma si attiverà l’inizializzazione predefinita su null

Vedi il seguente link http://www.dotnetperls.com/null-array

puoi definire un setter che controlla se il valore è nullo

 public class MyModel { private _myEmpls{get;set;} public Employees[] MyEmpls{ get{return _myEmpls;} set{_myEmpls=(value==null?new List():value);} } public int Id{get;set;} public OrgName{get;set;} }