Héritage de modèle de vue MVC et création d’une action

J’essaie de définir la meilleure architecture pour gérer les hiérarchies de types de modèles dans une application MVC.

Étant donné le modèle hypothétique suivant –

public abstract class Person { public ssortingng Name { get; set; } } public class Teacher : Person { public ssortingng Department { get; set; } } public class Student : Person { public int Year { get; set; } } 

Je pourrais simplement créer un contrôleur pour chaque type. Personne ne disposerait que de l’index et de l’action de détail, les vues utilisant des modèles d’affichage, Professeur et Étudiant ne disposant que des actions Créer / Modifier. Cela fonctionnerait, mais semblerait inutile et n’évoluerait pas vraiment car un nouveau contrôleur et des vues seraient nécessaires si un autre type était ajouté à la hiérarchie.

Existe-t-il un moyen de créer une action plus générique Créer / Modifier dans le contrôleur Personne? J’ai cherché la réponse pendant un certain temps, mais je n’arrive pas à trouver exactement ce que je cherche, alors toute aide ou tout pointeur serait apprécié 🙂

Bien sûr, mais cela demande un peu de travail aux jambes.

Tout d’abord, dans chacune de vos vues de modification / création, vous devez émettre le type de modèle que vous modifiez.

Deuxièmement, vous devez append un nouveau classeur pour la classe de personnes. Voici un exemple de ce que je ferais pour ça:

 public class PersonModelBinder :DefaultModelBinder { protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) { PersonType personType = GetValue(bindingContext, "PersonType"); Type model = Person.SelectFor(personType); Person instance = (Person)base.CreateModel(controllerContext, bindingContext, model); bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, model); return instance; } private T GetValue(ModelBindingContext bindingContext, ssortingng key) { ValueProviderResult valueResult =bindingContext.ValueProvider.GetValue(key); bindingContext.ModelState.SetModelValue(key, valueResult); return (T)valueResult.ConvertTo(typeof(T)); } } 

Enregistrez-le dans le début de votre application:

 ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder()); 

Le PersonType est ce que j’ai tendance à utiliser dans chaque modèle et est une énumération qui dit ce que chaque type est, je l’émets dans un HiddenFor pour qu’il revienne avec les données de publication.

SelectFor est une méthode qui renvoie un type pour l’énumération spécifiée.

 public static Type SelectFor(PersonType type) { switch (type) { case PersonType.Student: return typeof(Student); case PersonType.Teacher: return typeof(Teacher); default: throw new Exception(); } } 

Vous pouvez maintenant faire quelque chose comme ça dans votre contrôleur

 public ActionResult Save(Person model) { // you have a teacher or student in here, save approriately } 

Ef est capable de gérer cela très efficacement avec l’inheritance de style TPT

Juste pour compléter l’exemple:

 public enum PersonType { Teacher, Student } public class Person { public PersonType PersonType {get;set;} } public class Teacher : Person { public Teacher() { PersonType = PersonType.Teacher; } }