2011-08-30 14 views
7

Niedawno napotkałem problem podczas wdrażania rozwiązania JSON dla klienta. Jeśli nazwa parametru akcji pasuje do nazwy właściwości modelu, bindownica nie zwiąże żadnych właściwości.MVC3 Json Bind Bug?

Przykład:

Controller Ludzie

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

Ponieważ nazwa parametr zwany „email” i że pasuje do nazwy właściwości modelu osobę zwaną „email” .. spoiwo zawiedzie, ale nie daje żadnych wskazówek, dlaczego ..

mieli model o nazwie Person

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

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

Czy to błąd, czy "funkcja"?

Moje pytanie brzmi bardziej w odniesieniu do tego, jak nazwa argumentu może spowodować konflikt ze spoiwem? Nazwa nie powinna mieć znaczenia, ponieważ jest to typ klasy, który definiuje swój schemat, aby dopasować go do danych json. Dlaczego więc segregator powinien dbać o nazwę argumentu lub czy pasuje do nazwy właściwości w typie klasy samego argumentu?

+4

Czy możesz wysłać kod wywołujący js, lub co najmniej JSON, który przesyłasz? –

+0

json będzie: {"Nazwa": "Jan", "E-maile": ["[email protected]", "test2 @ test.com "]} Json był w porządku, jak powiedziałem, kiedy zmieniłem nazwę argumentu Akcje z E-maili (pasuje do nazwy właściwości modelu) na wszystko, co nie pasowało, zadziałało. Po prostu pomyślałem, że to jest interesujące i nie widzę powodu, dla którego to nie powinno zadziałać, lub przynajmniej wyrzuć wyjątek zamiast instancji klasy o zerowych wartościach właściwości !? – Mike

Odpowiedz

2

Problem polega na tym, że w słowniku słychać niejednoznaczność, a dwa elementy są nazwane "wiadomościami e-mail" (choć z inną obudową). DefaultModelBinder nie może rozwiązać tej niejednoznaczności.

Dwa możliwe rozwiązania: (1) jeśli przekazujesz z powrotem cały model osoby, zmień nazwę elementu najwyższego poziomu na "osoba" (co ma więcej sensu, biorąc pod uwagę kontekst), co wyeliminowałoby niejednoznaczność i zezwalaj na wiązanie, aby nastąpiło zgodnie z oczekiwaniami, lub (2) jeśli tylko odsyłasz listę e-maili, zmień sygnaturę działania na public ActionResult SetEmails(List<Emails> emails).

Nie nazwałbym tego, co doświadczyłeś albo błędu lub funkcji, ale problem z projektem.

+0

Zmieniłem ją na osobę, która rozwiązała problem. Nazwa nie jest wymagana, Właśnie przyjąłem starszy kod i moja ostatnia myśl o tym, dlaczego błąd modelu zakończył się niepowodzeniem, był taki, że nazwa argumentu Action pasowała do nazwy właściwości typu klasy argumentów: Nie rozumiem, dlaczego spowodowałoby to jakiekolwiek niejednoznaczności? .GetType(). GetProperties() itd. Dopasuj je do nadchodzącego json .. jeśli typ klasy argumentów (schemat przypuszczam) pasuje do json, great .. co oznacza argument nam e materia? W jaki sposób nazwa wchodzi w grę podczas wiązania? Jego nazwa nie oznacza, że ​​jest to typ klasy! – Mike

+0

JSON jest powiązany przez 'DictionaryValueProvider', więc wartości są powiązane poprzez nazwy kluczy. Jeśli są dwa klucze o tej samej nazwie, słownik nie będzie ważny. Proszę oznaczyć jako odpowiedź, jeśli było to pomocne. – counsellorben

+1

Te klucze powinny pochodzić z właściwości klas, a nie z nazwy, którą podałeś argumentowi używanemu do wiązania modelu. W jaki sposób nazwa parametru ma jakiekolwiek znaczenie podczas iteracji jej właściwości? var pi = controller.GetMethod ("akcja"). GetParameters(); Jak w tym przypadku potrzebujesz nazwy parametru lub jak wpływa on na wynik pobierania parametrów, w którym to momencie możesz uzyskać jego typ klasy i iterować po jego właściwościach, aby powiązać dane. Nie jest to kwestia dwóch właściwości o tej samej nazwie (nieprawidłowa i nie będzie kompilacji). – Mike

0

Nie mówię, że to jest , takie jak, ale można uniknąć zmiany nazwy nieruchomości.

Owiń obiekt JSON nazwą zmiennej (w tym przypadku jest to "wiadomość e-mail"). Tak to działa:

danych: JSON.stringify ({e-maile: {name: "moje imię", e-maile: [ "[email protected]" "[email protected]"]}}) ;

ale to nie robi - wraca modelbinder wartość null zamiast:

dane: JSON.stringify ({nazwa: "moje imię", e-maile: [ "[email protected]", " [email protected] "]});

Nadal jest to dość brzydkie. Jednak rzeczy działają głęboko pod pokrywami, nie ma powodu, dla którego mój klient sieci powinien wiedzieć, jaka jest nazwa parametru w kontrolerze, aby działała poprawnie. O ile mi wiadomo, jest to błąd w modelbinderze MVC.