2011-08-30 8 views
7

Recentemente ho riscontrato un problema durante l'implementazione di una soluzione JSON per un client. Se il nome del parametro di azione corrisponde a un nome di proprietà del modello, il raccoglitore non riesce a associare QUALSIASI proprietà.MVC3 Json Bind Bug?

Un esempio:

controller persone

public ActionResult SetEmails(Person emails){ 
    ... 
    return Content(""); 
} 

Poiché il nome del parametro è stato chiamato "email" e che corrisponde a un nome di proprietà del modello di persona chiamata "Messaggi di posta elettronica" .. il legante non riesce, ma non dà alcuna indicazione sul perché ..

avevano un modello chiamato persona

public class Person { 
    public string Name { get; set; } 
    public List<string> Emails { get; set; } 

    public Person() { 
     Emails = new List<string>(); 
    } 
} 

Si tratta di un bug o di una 'funzione'?

Proprio come una nota a margine, la mia domanda riguarda più in che modo il nome di un argomento potrebbe causare un conflitto a un raccoglitore? Il nome non dovrebbe avere importanza in quanto è il tipo di classe che definisce lo schema in modo che corrisponda ai dati JSON. Perché il raccoglitore dovrebbe preoccuparsi di ciò che si chiama l'argomento o se corrisponde a un nome di proprietà all'interno del tipo di classe dell'argomento stesso?

+4

puoi pubblicare il codice js di chiamata o almeno il JSON che stai inviando? –

+0

json sarebbe: {"Nome": "Giovanni", "Email": ["[email protected]", "test2 @ test.com "]} Il json andava bene, come ho affermato, una volta ho cambiato il nome dell'argomento Actions da Email (corrisponde al nome della proprietà dei modelli) a tutto ciò che non corrisponde, ha funzionato .. Ho pensato che fosse interessante e non riesco a vedere perché questo non dovrebbe funzionare, o per lo meno lanciare un'eccezione invece di una classe istanziata con valori di proprietà nulli !? – Mike

risposta

2

Il problema è che si ha un'ambiguità nel dizionario, con due elementi entrambi denominati "e-mail" (anche se con custodia differente). DefaultModelBinder non può risolvere questa ambiguità.

Due possibili soluzioni: (1) se si passa indietro un intero modello di persona, cambiare il nome del proprio elemento di livello superiore in "persona" (che ha più senso, dato il contesto), che eliminerebbe l'ambiguità e consentire che il binding avvenga come previsto, oppure (2) se si sta solo restituendo un elenco di e-mail, modificare la propria firma dell'azione su public ActionResult SetEmails(List<Emails> emails).

Non definirei un errore o una funzionalità, ma un problema relativo al progetto.

+0

L'ho passato a una persona, che ha risolto il problema. Il nome non è un requisito, Stavo solo prendendo il codice legacy e il mio ultimo pensiero sul motivo per cui il legatore del modello avrebbe fallito era che il nome dell'argomento Action corrispondeva al nome di una proprietà del tipo di classe degli argomenti. Non capisco perché questo causerebbe qualche email di Ambiguità? .GetType(). GetProperties() ecc. Li confronta con il JSON in arrivo .. se un tipo di classe argomenti (schema suppongo) corrisponde a quello del JSON, grande .. cosa fa l'argomento nam E 'importante? Come entra in gioco il nome durante la rilegatura? Il suo nome non indica il suo tipo di classe! – Mike

+0

JSON è associato tramite 'DictionaryValueProvider', quindi i valori sono associati tramite i nomi delle chiavi. Se ci sono due chiavi con lo stesso nome, il dizionario non sarà valido. Si prega di contrassegnare come risposta se questo è stato utile. – counsellorben

+1

E quelle chiavi dovrebbero provenire dalle proprietà delle classi, non dal nome che hai dato all'argomento utilizzato per associare il tuo modello. In che modo il nome del parametro ha rilevanza durante l'iterazione sulle sue proprietà? var pi = controller.GetMethod ("azione"). GetParameters(); Come qui, si richiede il nome del parametro o come influenza il risultato del recupero dei parametri, a quel punto si può quindi ottenere il suo tipo di classe e iterare sulle sue proprietà per legare i dati. Non si tratta di due proprietà con lo stesso nome (non valide e non vengono compilate). – Mike

0

Non sto dicendo che I come questo per una risposta, ma è possibile evitare di cambiare il nome della proprietà.

Avvolgi il tuo oggetto JSON con il nome della variabile del parametro (in questo caso, è "email"). Quindi, questo funziona:

dati: JSON.stringify ({email: {Name: "il mio nome", Email: [ "[email protected]", "[email protected]"]}}) ;

ma questo non lo fa - i rendimenti modelbinder null al suo posto:

dati: JSON.stringify ({name: "il mio nome", Email: [ "[email protected]", " [email protected] "]});

Ancora, questo è piuttosto schifoso. Comunque le cose funzionano in profondità sotto le copertine, non c'è ragione per cui il mio web client debba sapere quale sia il nome del parametro nel controller per funzionare correttamente. Per quanto mi riguarda, è un bug nel modelbinder di MVC.