2013-09-03 43 views
10

Khi tôi sử dụng các mẫu hiển thị lồng nhau và thêm các phần tử đầu vào thông qua trình trợ giúp HTML, công cụ Dao cạo sẽ thêm tiền tố vào các tên trường.Làm thế nào để ngăn Razor thêm tiền tố vào đầu vào khi sử dụng các mẫu hiển thị lồng nhau?

Tôi hiểu điều này được thực hiện để đảm bảo tính duy nhất của tên đầu vào ở cấp trang (và để xây dựng lại toàn bộ mô hình trên bài đăng trở lại).

Tuy nhiên, tôi có nhiều biểu mẫu nhỏ thực hiện các hành động đặc biệt và tôi không cần tính duy nhất cũng như khả năng xây dựng lại toàn bộ mô hình.

Tôi chỉ cần một giá trị thuộc tính duy nhất, và việc Razor thay đổi tên mục nhập sẽ phá vỡ trình kết nối mô hình khi tôi gửi một trong các biểu mẫu, vì tất cả các tên sẽ khác nhau.

Ví dụ này chứa một mô hình lồng nhau đơn giản

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

và nó có một cái nhìn Index với ba màn hình mẫu lồng nhau

IndexView 
    StudentDisplayTemplate 
     CourseDisplayTemplate 
      GradeDisplayTemplate 

Trong mẫu hiển thị lớp tôi thêm một nút để loại bỏ các lớp

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

và ở phía bên kia yêu cầu của tôi controller action nhận ID lớp

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

Nếu tôi cố gắng làm điều đó bằng cách sử dụng mô hình helper

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

tôi nhận được phần tử 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" /> 

nơi tên trường được một tiền tố dựa trên cây mô hình xem của toàn bộ cha mẹ.

Sử dụng "bằng tay" helper

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

cung cấp cho các phần tử HTML

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

nơi tiền tố vẫn còn hiện diện, dù với tên của tôi ở cuối.

Thêm bằng tay đầu vào ẩn

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

cung cấp cho các phần tử HTML

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

đó là những gì tôi muốn.

Có thể đạt được những gì tôi muốn hoặc tôi có gặp phải các mẫu hiển thị không?

+0

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

+0

@MohamadBataineh như tôi đã nói, tôi làm biết lý do tại sao nó làm điều đó. Những gì tôi hỏi là nếu có một cách để ngăn chặn nó khi sử dụng các trình trợ giúp HTML (tôi không nghĩ rằng tôi có thể sử dụng thuộc tính Bind trên hành động nhận, vì những người trợ giúp đang đặt các chỉ mục mảng trong các tên). – Albireo

Trả lời

9

Bạn muốn thiết lập ViewData.TemplateInfo.HtmlFieldPrefix trong Grade mẫu của bạn:

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

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

này cung cấp cho các đầu ra mong muốn của:

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

Nó giải quyết vấn đề với tên, nhưng bây giờ đánh dấu là không hợp lệ. Có vẻ như anh ta đang sử dụng một 'Danh sách' của' Lớp 'và hiển thị nó như một danh sách các phần tử biểu mẫu. Bằng cách đặt trường 'ViewData.TemplateInfo.HtmlFieldPrefix' thành' "" 'id của đầu vào biểu mẫu sẽ không còn là duy nhất nữa. Bất kỳ ý tưởng cho workaround? Bên cạnh việc chỉ định id tùy chỉnh cho mọi đầu vào của khóa học. –

0

Từ câu hỏi của bạn, nó không phải là rõ ràng nếu bạn đang tìm kiếm để có thể gửi cả toàn bộ biểu mẫu hoặc chỉ các hành động riêng lẻ. Nếu bạn muốn có thể làm cả hai, tôi nghĩ bạn sẽ phải sử dụng giải pháp dựa trên JS để gửi các yêu cầu biểu mẫu con theo cách thủ công.

Tuy nhiên, nếu bạn chỉ muốn nộp subforms, từng phần, đọc cùng ..

Nếu cú ​​pháp Courses_0__Grades_1__Id cho bộ sưu tập đang gây ra vấn đề, đây là tương đối dễ dàng để sửa chữa, trong kinh nghiệm của tôi.

Bạn có thể nhận được hành vi khác nhau về cách tên/id được tạo trong đối tượng con trong bộ sưu tập bằng cách sử dụng foreach thay vì số for truyền thống.

Hãy để tôi giải thích:


1) này sẽ phá vỡ các mô hình ràng buộc nộp toàn bộ dạng. Tất cả đầu vào cho các mục con sẽ không có ngữ cảnh của đường dẫn gốc.

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


2) Đây sẽ tôn trọng bối cảnh phụ huynh và cho phép mô hình ràng buộc nộp toàn bộ dạng. Tất cả đầu vào cho các mục con Sẽ CÓ ngữ cảnh của đường dẫn gốc.

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

Tuy nhiên

Bạn vẫn sẽ có vấn đề với các đối tượng không trong bộ sưu tập, treo ra khỏi mô hình chính, như Model.SomeOtherType.AnotherType sẽ có đầu vào trong lồng EditorFor với những cái tên như SomeOtherType.Property1SomeOtherType.Property2

Đối với những điều này, bạn có thể kéo đối tượng vào biến tạm thời trong dao cạo:

@var tempObj = Model.SomeOtherType; 
<div class='somemarkup'> 
    @Html.EditorFor(x=> tempObj); 
</div> 
Các vấn đề liên quan