2009-11-04 3 views
21

J'ai plus que un peu de difficulté à essayer de déboguer pourquoi MVC ne lie pas correctement dans un cas donné ...ASP.net MVC v2 - Déboguer les problèmes de liaison de modèle - BUG?

Fondamentalement, j'ai mon action qui reçoit un objet complexe qui à son tour a un enfant complexe object - Activity.Location.State (où Activity est l'objet complexe que l'action attend, Location est un objet enfant complexe et State est juste une chaîne).

Maintenant, j'ai mis en place un projet de test qui, pour autant que je puisse dire, imite exactement le scénario que j'ai, dans ce test la liaison fonctionne ... Mais dans mon projet, la liaison à Activity fonctionne mais pas Emplacement ... En plaçant des points d'arrêt dans la propriété Locaiton, je peux dire que MVC récupère l'objet Location complexe de l'activité, mais ne définit aucune des propriétés ...

J'essaye de déboguer le problème mais J'ai besoin d'accéder à l'aperçu de MVC v2 2 symboles que je n'arrive pas à retrouver ... Je voudrais voir ce qu'il fait réellement une fois qu'il sort l'objet de localisation (pour une raison quelconque, je pense qu'il pourrait échouer en interne mais avaler l'exception).

Toutes les idées sur ce que je pouvais faire ici ...

Vive Anthony

MISE À JOUR:

Ok je l'ai fait ce que J.W. suggéré et référence directe le projet MVC ...

J'ai trouvé le problème et il y avait une très petite différence que j'ai ignorée ... Comme résultat, j'ai découvert que MVC ne supporte pas actuellement plusieurs niveaux d'héritage INTERFACE quand il vient au modèle de liaison ... Voir la suite ...

//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) 
{ 
} 

d'où ce que j'ai trouvé est que MVC trouve l'emplacement et lit son type méta comme ILocation, mais quand GetModelProperties est exécuté dans le DefaultModelBinder les suivantes se produit -

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 
    } 

Par conséquent, je suppose à ce stade que TypeDescriptionProvider ne supporte pas ce style d'héritage, dont je suis assez surpris. En regardant la source v1, on dirait que cela a été introduit avec v2 - mais v1 pourrait ne pas être capable de supporter ce que j'essaie de faire de toute façon.

Je ne dirais pas que c'est vraiment un bug, mais j'ai essayé de remplacer mes interfaces par des classes concrètes et ça a bien fonctionné. D'où le comportement n'est pas vraiment ce que je m'attendais et est un peu incohérent.

Des pensées? J'aurais pensé que cet héritage n'était pas assez standard mais se produirait assez souvent pour être pris en compte. Merci pour la réponse.

Vive

+0

interfaces ne peuvent pas hériter, seules les classes peuvent. Les interfaces spécifient les exigences de mise en œuvre. Si vous dites IFoo: IBar, vous dites au compilateur "Toute classe qui implémente l'interface IFoo doit aussi implémenter l'interface IBar". – ScottKoon

Répondre

45

Il s'avère que ce problème est inhérent à la conception en raison du fonctionnement de l'héritage de l'interface. Les interfaces ne définissent pas les implémentations, donc ILocation n'hérite pas des propriétés de ILocationSource.Au contraire, ILocation ne définit que ce qu'une implémentation concrète doit implémenter.

Pour tous les détails, y compris la section de la CLI (de Common Language Infrastructure) spec qui définit ce comportement, consultez: http://haacked.com/archive/2009/11/10/interface-inheritance-esoterica.aspx

+0

Je pense que le commentaire de Brad Wilson est comment je me souviens toujours de la différence et attend le comportement approprié. "Peut faire vs est un" –

+0

Oui - en fait .NET a toujours manqué d'héritage multiple - beaucoup à la frustration de nombreux développeurs C++ venant à la plate-forme. Puis-je vous recommandons d'avoir une vue d'ensemble complète de la conception orientée objet, puis de lire un bon livre sur C#. L'affiche originale essaye clairement de courir avant qu'ils puissent marcher, en développant sur MVC avant qu'ils comprennent complètement C#. Je dis que c'est une erreur et conduira à beaucoup de frustration. – csharpforevermore

3

Je voudrais simplement faire référence au code source asp.net MVC2 publiée dans CodePlex. Je l'ai fait, c'est très simple.

Cela vous permettra de mieux comprendre lorsque vous déboguez le code source.

Questions connexes