Angenommen, ich möchte die Auswahl unserer Entität (aus einer Dropdown-Liste usw.) auf einer Seite, z. B. "Produkt", ermöglichen. Als Ergebnis könnte ich dies erhalten:
public ActionResult SelectedAction(Guid productId)
{
}
Aber ich möchte die Leistung von Modellbindern nutzen, also schreibe ich stattdessen Modellbinder, um mein Produkt aus dem Repository zu holen und verwende stattdessen
public ActionResult SelectedAction(Product product)
{
if (ModelState.IsValid) {} else {}
}
Mein Model Binder setzt den Modellstatus auf false, wenn das Produkt ungültig ist. Nun, es gibt Probleme mit diesem Ansatz:
- Es ist nicht immer einfach, stark typisierte Methoden wie Html.ActionLink(c => c.SelectedAction(id)) zu verwenden, da wir Product und nicht id übergeben müssen.
- Es ist sowieso nicht gut, Entitäten als Controller-Parameter zu verwenden.
- Wenn der Modellstatus ungültig ist und ich zurückleiten und einen Fehler anzeigen möchte, kann ich das ausgewählte Produkt nicht beibehalten! Denn das gebundene Produkt ist nicht festgelegt und meine ID ist nicht vorhanden. Ich würde gerne RedirectToAction(c => c.Redisplay(product)) machen, aber das ist natürlich nicht möglich.
Jetzt scheint es, als müsste ich wieder "Guid productId" als Parameter verwenden... Allerdings gibt es eine Lösung, die ich gerne vorstellen und diskutieren möchte.
public class EntityViewModel<T> where T : BaseEntity
{
public EntityViewModel(Guid id)
{
this.Id = id;
}
public static implicit operator EntityViewModel<T>(T entity)
{
return new EntityViewModel<T>(entity.Id);
}
public override string ToString()
{
return Id.ToString();
}
public Guid Id { get; set; }
public T Instance { get; set; }
}
Nun, wenn ich
public ActionResult SelectedAction(EntityViewModel<Product> product)
{
if (ModelState.IsValid) {} else {}
}
sind alle Probleme gelöst:
- Ich kann EntityViewModel mit nur Id gesetzt übergeben, wenn ich nur Id haben.
- Ich verwende keine Entität als Parameter. Außerdem kann ich kann EntityViewModel als Eigenschaft innerhalb eines anderen ViewModel verwenden.
- Ich kann das EntityViewModel an RedirectToController zurückgeben und es wird seinen Id-Wert behalten, der sein wird Benutzer zusammen mit den Validierungsmeldungen (dank MVCContrib und ModelStateToTempData / PassParametersDuringRedirect) wieder angezeigt wird.
Der Modellbinder holt sich die Instanz aus dem Repository und setzt Modellstatusfehler wie "Nicht in der Datenbank gefunden" und so weiter. Und ich kann Dinge wie ActionLink(c => c.Action(Model.MyProductViewModelProperty)) verwenden.
Die Frage ist, ob es hier irgendwelche Nachteile gibt. Ich kann nichts Schlechtes erkennen, aber ich bin noch neu in MVC und könnte einige wichtige Dinge übersehen. Vielleicht gibt es bessere und bewährte Wege? Vielleicht ist das der Grund, warum jeder Entity-IDs als Eingabeparameter und Eigenschaften verwendet?