2 Stimmen

ASP.Net MVC3 Modell Bindung IEnumerable<T> mit Editor Vorlage

Alle, bitte klären Sie meine Verwirrung auf, wie die Modellbindung mit IEnumerables und Editorvorlagen funktioniert.

Ich habe eine Ansicht, Approve.cshtml

@model IEnumerable<MvcWebsite.Models.Approve>
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>

Ein Modell, Approve.cs

public class Approve
{
  public string Name { get;set;}
  public string Role { get; set; }
}

Und eine Editorvorlage

@model MvcWebsite.Models.Approve

@using (Html.BeginForm("Approve", "Registration", FormMethod.Post))
{
<tr>
    <td>
        @Html.HiddenFor(m => m.Name)
        @Html.EditorFor(m => m.Role)
    </td>
    <td>
        <input type="submit" value="Approve" class="submit-button" />            
    </td>
</tr>

}

Das ist alles schön und gut. Es gibt die folgende Ausgabe aus.

        <input name="[0].Name" type="hidden" value="" />
        ....

Jedoch in meinem Controller, kann ich nicht scheinen, um Werte zurück für das Modell (Bindung) zu erhalten.

[HttpPost]
public ActionResult Approve(Approve approveModel)
{
    .... approveModel has all default values
}

Kann mir jemand erklären, was ich hier falsch mache? Ich habe den Code abgekürzt, ich verwende die Editor-Vorlage mit anderen EditorFor und HiddenFor Feldern aus meinem Modell...

Bearbeitet: Ich habe im Grunde ein Tabellenlayout, jeweils mit dem Namen des Benutzers, ein Textfeld, wo ich ihre Rolle (Benutzer oder Admin) und dann eine Schaltfläche Genehmigen eingeben kann, die an meinen Controller sendet. Aus diesem Grund möchte ich nur ein einziges Approve-Objekt zurückgeben. Ich kann die gesamte IEnumerable an meinen Controller zurückgeben, aber wenn ich das tue, wie kann ich sagen, welche der Elemente war die, die ich die Schaltfläche Genehmigen (senden) für geklickt?

EDIT: Ich habe den Code so geändert, dass ich ein einziges Formular habe, das meine gesamte Ansicht Approve.cshtml umgibt

@model IEnumerable<MvcWebsite.Models.Approve>
@using (Html.BeginForm("Approve", "Program", FormMethod.Post))
{
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>
}

Und änderte dann den Controller in

[HttpPost]
public ActionResult Approve(IEnumerable<Approve> approvals)
{
    // ???????????????????????
}

Jetzt weiß ich immer noch nicht, woher ich weiß, für welche Zeile ich auf "Genehmigen" geklickt habe. Ich weiß, dass es andere Möglichkeiten gibt, diese Aufgabe zu erfüllen (erstellen Sie ein Kontrollkästchen für genehmigen, und genehmigen Sie alles markiert, usw.) Jedoch brauche ich die Fähigkeit, eine Schaltfläche klicken und nur 1 Zeile zurück in die Datenbank zu speichern, unabhängig davon, ob der Benutzer Informationen in die anderen Zeilen eingegeben. Ist es bessere Praxis, meine IEnumerable innerhalb der eigenen Modell (d.h. AllApprovals) zu wickeln und dann Hilfseigenschaften zu diesem übergeordneten Modell (SelectedIndex, etc.) hinzufügen? Wenn dies der richtige Ansatz ist, wie setze ich dann den SelectedIndex nach dem Klicken auf eine Genehmigungsschaltfläche? Ist das noch Jquery Magie oder gibt es eine korrekte MVC Weg, dies zu erreichen? Jquery Magie scheint sehr hackish zu mir?

EDIT: Basierend auf Brians Antwort, hier ist meine endgültige Version. Es fühlt sich immer noch nicht ganz richtig an, aber es funktioniert!

Siehe

@model IEnumerable<MvcWebsite.Models.Approve>
<table>
    <tr>
        <th>
            Name
        </th>
    </tr>
    @Html.EditorForModel()
</table>

Editor-Vorlage

@using (Html.BeginForm("Approve", "Registration", FormMethod.Post))
{
<tr>
    <td>
        @Html.HiddenFor(m => m.Name)
        @Html.EditorFor(m => m.Role)
    </td>
    <td>
        <input type="submit" value="Approve" class="submit-button" />            
    </td>
</tr>
}

Controller

[HttpPost]
public ActionResult Approve([Bind(Prefix="approval")]Approve approval)    {
    // WORKS!
}

2voto

Brian Cauthon Punkte 5524

Da Sie nur eine auf einmal ändern, denke ich, dass die folgenden einfacher ist, als zu versuchen, herauszufinden, am Controller, welche Werte geändert, oder eine geänderte Eigenschaft hinzufügen und es über Javascript festlegen.

Ändern Sie Approve.cshtml in

@model IEnumerable<MvcWebsite.Models.Approve> 
<table> 
    <tr> 
        <th colspan=2> 
            Name 
        </th> 
    </tr> 
@foreach(var user in Model){
    @using (Html.BeginForm("Approve", "Registration", FormMethod.Post))         { 
    <tr> 
        <td> 
            @Html.EditorFor(m => user) 
        </td> 
        <td> 
            <input type="submit" value="Approve" class="submit-button" />             
        </td> 
    </tr> 
    }
}
</table> 

Ändern Sie die Approve Editor-Vorlage zu

@Html.HiddenFor(m => m.Name) 
@Html.EditorFor(m => m.Role)

0voto

Martin Booth Punkte 8265

Sie binden sich an die einzelne Approve-Klasse, Sie sollten sich an IEnumerable<Approve>

0voto

Adam Tuliper Punkte 29789

Martin hat recht, ich möchte nur noch ein paar Informationen hinzufügen. Ihr gerendertes HTML mit der [0] ist eine spezielle Syntax, die der Model Binder betrachtet und annimmt, dass Sie mit einer Liste von Objekten arbeiten. Da Ihre Aktionsmethode eine einzelne Approve-Klasse und keine Liste hat, tritt dieses Problem auf.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X