Bonjour,
je sèche sur ce problème depuis deux jours.. pourriez-vous m'aider svp.
Le but est de faire de l'héritage sur un formulaire de création. On a une classe de base abstraite Personne et deux classes dérivées Etudiant qui expose une prop moyenne professeur qui expose une prop Salaire. Pas très original mais c'est un poc qui ne représente pas du tout l'app finale.
Le modèle :
La vue Create :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace PocHeritage.Models { [JsonConverter(typeof(PersonneJsonConverter))] public abstract class Personne { public long Id { get; set; } public string Nom { get; set; } public string Prenom { get; set; } } public class Etudiant : Personne { public double Moyenne { get; set; } } public class Professeur : Personne { public double Salaire { get; set; } } public abstract class JsonCreationConverter<T> : JsonConverter { public override bool CanWrite { get; } = false; public override bool CanRead { get; } = true; public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { } protected abstract T Create(Type objectType, JObject jObject); public override bool CanConvert(Type objectType) { return typeof(T) == objectType; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); var target = Create(objectType, jObject); serializer.Populate(jObject.CreateReader(), target); return target; } } public class PersonneJsonConverter : JsonCreationConverter<Personne> { protected override Personne Create(Type objectType, JObject jObject) { if(jObject["Salaire"] != null) { return new Professeur(); } else { return new Etudiant(); } } } }
Code CSHTML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 @model PocHeritage.Models.Personne @{ ViewData["Title"] = "Create"; } <h1>Create</h1> <h4>Personne</h4> <hr /> <div class="row"> <div class="col-md-4"> <form method="post" asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <div class="form-group"> <label asp-for="Nom" class="control-label"></label> <input asp-for="Nom" class="form-control" /> <span asp-validation-for="Nom" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Prenom" class="control-label"></label> <input asp-for="Prenom" class="form-control" /> <span asp-validation-for="Prenom" class="text-danger"></span> </div> <select id="selTypePers" onchange="TypePersonneChange()"> <option>-</option> <option>Etudiant</option> <option>Professeur</option> </select> <hr /> <div id="divEtudiant" style="display:none"> <partial name="PartialViewCreateEtudiant" /> </div> <div id="divProfesseur" style="display:none"> <partial name="PartialViewCreateProfesseur" /> </div> <div class="form-group"> <input type="submit" value="Create" class="btn btn-primary" /> </div> </form> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script> function TypePersonneChange() { var selectField = document.getElementById("selTypePers"); var selectedType = selectField.options[selectField.selectedIndex].value; var length = $('#selTypePers option').length; for (var i = 0; i < length; i++) { var type = selectField.options[i].value; var div = document.getElementById("div" + type); if (div != null) { if (type == selectedType) { div.style.display = "block"; } else { div.style.display = "none"; } } } } </script> }
La vue partielle prof :
Code CSHTML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 @model PocHeritage.Models.Professeur <div class="row"> <div class="col-md-4"> <div class="form-group"> <label asp-for="Salaire" class="control-label"></label> <input asp-for="Salaire" class="form-control" /> <span asp-validation-for="Salaire" class="text-danger"></span> </div> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
La vue partielle Etudiant :
Code CSHTML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 @model PocHeritage.Models.Etudiant <div class="row"> <div class="col-md-4"> <div class="form-group"> <label asp-for="Moyenne" class="control-label"></label> <input asp-for="Moyenne" class="form-control" /> <span asp-validation-for="Moyenne" class="text-danger"></span> </div> </div> </div> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} }
Le contrôleur :
En PJ le zip 7z de la solution.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using PocHeritage.Models; namespace PocHeritage.Controllers { [Route("api/[controller]")] [ApiController] public class PersonneController : Controller { public ActionResult Create() { return View(); } [HttpPost] public IActionResult Create([FromForm] Personne p) { return View(p); } } }
Sachant que je me suis inspiré de cette page https://www.tutorialdocs.com/article...a-binding.html
Les vues ne sont pas blindées il y a plein de défauts ok; simplement le but est de récupérer une instance de prof ou etudiant grâce à l'attribut JsonConverter qui préférence le type de classe PersonneJsonConverter.
Je pense avoir réalisé l'exemple assez fidèlement pourtant je reçois une exception :
Signe que le mécanisme de binding model essaye d'instancier la classe Personne au lieu d'utiliser le mécanisme jsonConverter pour instancier un étudiant ou un prof.InvalidOperationException: Could not create an instance of type 'PocHeritage.Models.Personne'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'p' parameter a non-null default value.
Par avance merci pour votre aide.
Cordialement,
Partager