2013-09-03 18 views
10

Podczas korzystania z zagnieżdżonych szablonów wyświetlania i dodawania elementów wejściowych za pomocą pomocnika HTML, silnik Razor dodaje przedrostek do nazw pól.Jak zabezpieczyć urządzenie Razor przed dodawaniem prefiksów do danych wejściowych podczas korzystania z zagnieżdżonych szablonów wyświetlania?

Rozumiem, że robi się to, aby zagwarantować niepowtarzalność nazwy wejścia na poziomie strony (i przebudować cały model po wysłaniu z powrotem).

Mam jednak wiele małych form, które wykonują czynności ad-hoc, i nie potrzebuję ani nazwy wyjątkowości, ani możliwości odbudowania całego modelu.

Po prostu potrzebuję tej pojedynczej wartości właściwości, a po zmianie nazwy elementów wejściowych Razor łamie model segregatora, gdy przesyłam jeden z formularzy, ponieważ wszystkie nazwy będą różne.

Przykład ten zawiera uproszczoną zagnieżdżonych modelowi

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; } 
} 

i ma Index widok z trzech zagnieżdżonych szablonów graficznych

IndexView 
    StudentDisplayTemplate 
     CourseDisplayTemplate 
      GradeDisplayTemplate 

W szablonie wyświetlacza klasy I dodać przycisk, aby usunąć klasę

@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> 

i po drugiej stronie żądania mój Akcja kontroler otrzymuje identyfikator klasy

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

Gdy próbuję to zrobić przy użyciu modelu pomocnik

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

dostaję elementu HTML

<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" /> 

gdzie nazwa pola dostaje prefiks oparciu na drzewie modelu widoku całego rodzica.

Korzystanie z "Manual" pomocnika

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

daje elementu HTML

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

gdzie prefiks jest wciąż obecny, chociaż z moim nazwiskiem na końcu.

Dodawanie ręcznie ukryte wejście

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

daje element HTML

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

co jest to, co chcę.

Czy można osiągnąć to, co chcę, lub czy otrzymuję błędnie szablony wyświetlania?

+0

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

+0

@MohamadBataineh jak powiedziałem, robię wiesz, dlaczego to robi. Pytam, czy istnieje sposób, aby temu zapobiec, gdy używa się pomocników HTML (nie sądzę, żebym mógł użyć atrybutu Bind na akcji odbiorczej, ponieważ pomocnicy umieszczają indeksy tablicowe w nazwach). – Albireo

Odpowiedz

9

Chcesz ustawić ViewData.TemplateInfo.HtmlFieldPrefix w Grade Szablon:

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

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

To daje pożądaną moc:

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

Rozwiązuje problem z nazwami, ale teraz znacznik jest nieprawidłowy. Wygląda na to, że używa 'List' z' Grade's i wyświetla ją jako listę elementów formularza. Ustawiając 'ViewData.TemplateInfo.HtmlFieldPrefix' na' "" pole 'id pola formularza nie będzie już unikalne. Jakieś pomysły na obejście tego problemu? Oprócz określenia niestandardowego identyfikatora dla każdego wejścia oczywiście. –

0

z twojego pytania, to nie jest jasne, jeśli szukasz, aby móc do przesłania zarówno całego formularza, jak i pojedynczych działań. Jeśli chcesz mieć obie możliwości, myślę, że będziesz musiał użyć rozwiązania opartego na JS, aby ręcznie przesłać żądania podformularza.

Jednakże, jeśli po prostu chcesz się przedstawić podformularze, fragmentaryczne, czytać razem ..

Jeśli składnia Courses_0__Grades_1__Id dla kolekcji jest przyczyną problemów, jest to stosunkowo łatwe do naprawienia, w moim doświadczeniu.

Można uzyskać różne zachowanie dotyczące sposobu generowania nazw/identyfikatorów w obiektach podrzędnych w kolekcjach, używając tradycyjnegozamiast tradycyjnego.

Pozwól mi wyjaśnić:


1) To złamie obowiązujących przy składaniu cała-wzór formularza. Wszystkie dane wejściowe elementów potomnych nie będą miały żadnego kontekstu dla ścieżki nadrzędnej.

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


2) Te uwzględni kontekst nadrzędnego i umożliwiają modelu wiązania składania całej postaci płyty. Wszystkie dane wejściowe dla elementów potomnych MUSZĄ zawierać kontekst swojej ścieżki nadrzędnej.

@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++; 
} 

Jednak

Będzie nadal mają problemy z obiektów nie w kolekcjach, wiszące wyłączyć główny model jak Model.SomeOtherType.AnotherType będzie musiał wejść w zagnieżdżonej EditorFor o nazwach takich jak SomeOtherType.Property1 i SomeOtherType.Property2

W tym celu można przeciągnąć obiekt do tymczasowej zmiennej w maszynce:

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