2013-09-03 7 views
10

Wenn ich verschachtelte Anzeigevorlagen verwende und Eingabeelemente über den HTML-Helfer hinzufüge, fügt die Razor-Engine den Feldnamen ein Präfix hinzu.Wie kann verhindert werden, dass Razor bei Verwendung von verschachtelten Anzeigevorlagen den Eingaben Präfixe hinzufügt?

Ich verstehe, dass dies getan wird, um die Eindeutigkeit des Eingabe-Namens auf Seitenebene zu garantieren (und das gesamte Modell beim Post-Back neu aufzubauen).

Allerdings habe ich viele kleine Formulare, die Ad-hoc-Aktionen ausführen, und ich brauche weder die Eindeutigkeit des Namens noch die Fähigkeit, das ganze Modell neu zu erstellen.

Ich brauche nur diese einzelne Eigenschaft Wert, und mit Razor ändern die Eingabe Elemente Namen bricht das Modell Binder, wenn ich eines der Formulare einreichen, da alle Namen unterschiedlich sein werden.

Dieses Beispiel enthält ein vereinfachtes verschachteltes Modell

public class Student 
{ 
    public Guid Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public List<Course> Courses { get; set; } 
} 

public class Course 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public List<Grade> Grades { get; set; } 
} 

public class Grade 
{ 
    public Guid Id { get; set; } 
    public DateTime Date { get; set; } 
    public decimal Value { get; set; } 
} 

und es hat eine Index Ansicht mit drei verschachtelten Anzeigeschablonen

IndexView 
    StudentDisplayTemplate 
     CourseDisplayTemplate 
      GradeDisplayTemplate 

In der Klasse Anzeigevorlage ich einen Knopf fügen Sie die Klasse entfernen

@model Playground.Sandbox.Models.Home.Index.Grade 

<li> 
    @this.Model.Date: @this.Model.Value 

    @using (Html.BeginForm("Remove", "Home", FormMethod.Post)) 
    { 
     <input name="GradeId" type="hidden" value="@this.Model.Id" /> 

     <input type="submit" value="Remove" /> 
    } 
</li> 

und auf der anderen Seite der Anfrage mein Controller-Aktion erhält die ID-Klasse

public ActionResult Remove(Guid id) 
{ 
    // Do various things. 
    return this.RedirectToAction("Index"); 
} 

Wenn ich versuche, es zu tun mit dem Modell Helfer

@Html.HiddenFor(x => x.Id) 

ich das HTML-Element

<input data-val="true" 
     data-val-required="The Id field is required." 
     id="Courses_0__Grades_1__Id" 
     name="Courses[0].Grades[1].Id" 
     type="hidden" 
     value="76f7e7ed-a479-42cb-add5-e58c0090770c" /> 

, wo der Feldname ein Präfix wird basierend auf dem Modellbaum des gesamten Elternteils.

die "manuellen" Helfer Mit

@Html.Hidden("GradeId", this.Model.Id) 

gibt das HTML-Element

<input id="Courses_0__Grades_0__GradeId" 
     name="Courses[0].Grades[0].GradeId" 
     type="hidden" 
     value="bbb3c11d-d2d0-464a-b33b-ff7ac9815601" /> 

wo das Präfix immer noch vorhanden ist, wenn auch mit meinem Namen am Ende.

manuell den versteckten Eingang Hinzufügen

<input name="GradeId" type="hidden" value="@this.Model.Id" /> 

gibt das HTML-Element

<input name="GradeId" 
     type="hidden" 
     value="a1a35e81-29cd-41b5-b619-bab79b767613" /> 

das ist, was ich will.

Ist es möglich zu erreichen, was ich will, oder bekomme ich die Anzeige Vorlagen etwas falsch?

+0

http://stackoverflow.com/questions/14157376/why-does-html-helper-add-prefix-to-attributes-for-child-item-of-view-model –

+0

@MohamadBataineh wie gesagt, tue ich weiß warum es so ist. Ich frage, ob es eine Möglichkeit gibt, das zu verhindern, wenn ich die HTML-Helfer verwende (ich glaube nicht, dass ich das Bind-Attribut für die Empfangsaktion verwenden kann, da die Helfer Array-Indizes in die Namen einfügen). – Albireo

Antwort

9

Sie ViewData.TemplateInfo.HtmlFieldPrefix in Ihrem Grade Vorlage festlegen möchten:

@model Playground.Sandbox.Models.Home.Index.Grade 

@{ 
    ViewData.TemplateInfo.HtmlFieldPrefix = ""; 
} 

Dadurch wird die gewünschte Ausgabe von ergibt:

<input id="GradeId" name="GradeId" type="hidden" /> 
+0

Es löst das Problem mit Namen, aber jetzt ist das Markup ungültig. Es sieht so aus, als ob er eine 'Liste' von' Noten' verwendet und diese als Liste von Formularelementen rendert. Durch Setzen von 'ViewData.TemplateInfo.HtmlFieldPrefix' auf' "" wird das ID-Feld der Formulareingaben nicht mehr eindeutig sein. Irgendwelche Ideen zur Problemumgehung? Neben der Angabe der benutzerdefinierten ID für jede Eingabe natürlich. –

0

Aus Ihrer Frage, es ist nicht klar, ob Sie suchen Lage sein, um das gesamte Formular oder nur die einzelnen Aktionen zu übermitteln. Wenn Sie beides tun möchten, müssen Sie eine JS-basierte Lösung verwenden, um die Teilformularanforderungen manuell zu übermitteln.

Wenn Sie jedoch nur die subforms einreichen möchten, Stück für Stück, mitlesen ..

Wenn die Syntax Courses_0__Grades_1__Id für Sammlungen Probleme verursacht, ist dies relativ einfach zu beheben, in meiner Erfahrung.

Sie können ein unterschiedliches Verhalten bei der Generierung der Namen/IDs in untergeordneten Objekten in Auflistungen erhalten, indem Sie foreach anstelle eines traditionellen verwenden.

Lassen Sie mich erklären:


1) Dies wird das Modell brechen verbindlich für die Einreichung gesamte Form. Alle Eingaben für untergeordnete Elemente haben keinen Kontext ihres übergeordneten Pfads.

@foreach(var child in Model.Children) 
{ 
    @Html.EditorFor(x=> child) 
} 


2) Diese werden geordneten Kontexts achten und Modell ermöglichen gesamte Form Vorlage binden. Alle Eingaben für untergeordnete Elemente haben Kontext ihres übergeordneten Pfades.

@for(var i = 0; i < Model.Children.Count(); i++) 
{ 
    @Html.EditorFor(x=> Model.Children[i]) 
} 
// or.. 
var i = 0; 
@foreach(var child in Model.Children) 
{ 
    @Html.EditorFor(x=> Model.Children[i]) 
    i++; 
} 

jedoch

Sie immer noch Probleme mit Objekten nicht in einer Sammlung haben, das Hauptmodell hängen, wie Model.SomeOtherType.AnotherType Eingänge in den verschachtelten EditorFor mit Namen wie SomeOtherType.Property1 und SomeOtherType.Property2

haben Für diese können Sie das Objekt in eine temporäre Variable im Rasierer ziehen:

@var tempObj = Model.SomeOtherType; 
<div class='somemarkup'> 
    @Html.EditorFor(x=> tempObj); 
</div> 
Verwandte Themen