2009-11-04 8 views
21

Sto avendo più di un po 'di difficoltà cercando di eseguire il debug perché MVC non è vincolante in modo corretto in un dato caso ho ...ASP.net MVC v2 - Debug dei problemi di binding del modello - ERRORE?

Fondamentalmente, ho la mia azione che riceve un oggetto complesso che a sua volta ha un figlio complessa oggetto - Activity.Location.State (dove Activity è l'oggetto complesso che l'azione si aspetta, Location è un oggetto figlio complesso e State è solo una stringa).

Ora ho creato un progetto di test che, per quanto posso dire, riproduce esattamente lo scenario reale che ho, in questo test il binding funziona ... Ma nel mio progetto, il binding ad Activity funziona ma non per Posizione ... Inserendo punti di interruzione all'interno della proprietà Locaiton, posso dire che MVC recupera l'oggetto posizione complesso dall'attività, ma non imposta nessuna delle proprietà ...

Sto tentando di eseguire il debug del problema ma Ho bisogno di accedere ai 2 simboli di anteprima di MVC v2 2 che non riesco a rintracciare ... Mi piacerebbe vedere cosa sta effettivamente facendo una volta che estrae l'oggetto posizione (per qualche motivo penso che potrebbe non riuscire internamente ma ingoiando l'eccezione).

Tutte le idee su cosa avrei potuto fare qui ...

Acclamazioni Anthony

UPDATE:

Ok ho fatto quello J.W. suggerito e riferimento diretto al progetto MVC ...

Ho trovato il problema e c'era una differenza molto piccola che non tenevo in considerazione ... Come risultato ho scoperto che MVC attualmente non supporta più livelli di ereditarietà di INTERFACE quando viene a modello vincolante ... Vedere il seguente ...

//MODEL 
public class Location : ILocation 
{ 
    ... 
} 

public interface ILocation : ILocationCore 
{ 
    ... 
} 

public interface ILocationCore //In my sample I didn't have this second level interface 
{ 
    ... 
    //MVC doesn't find any of these properties 
    ... 
} 


public class Activity : IActivity 
{ 
    ... 
} 

public interface IActivity : IActivityCore 
{ 
    ILocation Location { get; set; } //MVC finds this and reads its meta type as an ILocation 
    //Also the implementation of this Location within Activity will always return a instance - our IoC takes care of that, so MVC should never have to create the instance 
} 

public interface IActivityCore 
{ 
    ... 
} 

//CONTROLLER 
public ActionResult Create(Activity activity) 
{ 
} 

Quindi quello che ho trovato è che MVC trova la posizione e legge il suo tipo di meta come un ILocation, ma quando GetModelProperties viene eseguito all'interno del DefaultModelBinder il seguente si verifica -

protected virtual PropertyDescriptorCollection GetModelProperties(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
     return GetTypeDescriptor(controllerContext, bindingContext).GetProperties(); 
     //This return no properties 
    } 

    protected virtual ICustomTypeDescriptor GetTypeDescriptor(ControllerContext controllerContext, ModelBindingContext bindingContext) { 
     return new AssociatedMetadataTypeTypeDescriptionProvider(bindingContext.ModelType).GetTypeDescriptor(bindingContext.ModelType); 
     //bindingContext.ModelType - is ILocation 
    } 

Quindi sto assumendo a questo punto che TypeDescriptionProvider non supporta questo stile di ereditarietà, cosa di cui sono abbastanza sorpreso. Anche guardando la sorgente v1 sembra che questo sia stato introdotto con la v2 - ma la v1 potrebbe non essere stata in grado di supportare ciò che sto cercando di fare comunque.

Non direi che questo è davvero un bug, ma ho provato a sostituire le mie interfacce con lezioni concrete e ha funzionato bene. Quindi il comportamento non è proprio quello che mi aspetterei ed è un po 'incoerente.

Qualche idea ??? Avrei pensato che questa eredità non fosse abbastanza standard, ma si sarebbe verificata abbastanza spesso per essere soddisfatta. Grazie per la risposta.

Acclamazioni

+0

interfacce non possono ereditare, solo le classi possono. Le interfacce specificano i requisiti di implementazione. Se dici IFoo: IBar, stai dicendo al compilatore "Qualsiasi classe che implementa l'interfaccia IFoo deve anche implementare l'interfaccia IBar". – ScottKoon

risposta

45

Questo comportamento è dovuto alla progettazione a causa del modo in cui l'ereditarietà dell'interfaccia funziona. Le interfacce non definiscono le implementazioni, quindi ILocation non "eredita" le proprietà di ILocationSource.Piuttosto, ILocation definisce solo ciò che un'implementazione concreta deve implementare.

Per i dettagli completi, tra cui la sezione del CLI (Common Language Infrastructure) spec che definisce questo comportamento, check out: http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

+0

Penso che il commento di Brad Wilson sia come ricordo sempre la differenza e aspetto il comportamento appropriato. "Can Do vs Is A" –

+0

Sì. In effetti, .NET ha sempre mancato l'ereditarietà multipla, con gran frustrazione di molti sviluppatori C++ che arrivano alla piattaforma. Posso consigliare di ottenere una panoramica completa di Object Oriented Design e quindi di leggere un buon libro su C#. Il poster originale sta chiaramente cercando di correre prima che possano camminare, sviluppando su MVC prima che comprendano pienamente C#. Dico che questo è un errore e porterà a molte frustrazioni. – csharpforevermore

3

Vorrei semplicemente riferimento al codice sorgente asp.net MVC2 pubblicato in CodePlex. L'ho fatto, è molto semplice.

Fornirà una migliore comprensione durante il debugging del codice sorgente.

Problemi correlati