#asp.net-mvc #asp.net-mvc-3 #razor
#asp.net-mvc #asp.net-mvc-3 #razor
Вопрос:
У меня есть ASP.NET MVC3 Razor view, который отображает редакторы для списка клиентов внутри jQuery UI accordion. На данный момент все идентификаторы на стороне клиента для аналогичных свойств клиента одинаковы в отображаемом html. По очевидным причинам я хотел бы это изменить.
Мой основной вид заключается в следующем:
<div id="accordionKlanten">
@foreach (var customer in Model.Customers)
{
<h3><a href="#">@customer.Name</a></h3>
<div>@{ Html.RenderPartial("CustomerData", customer); }</div>
}
</div>
И на мой CustomerData
взгляд (значительно упрощенный):
@using (Ajax.BeginForm("UpdateCustomer", ajaxOptions))
{
@Html.LabelFor(model => model.Name)
@Html.TextBoxFor(model => model.Name)
<input type="submit" value="Opslaan" />
}
Все это работает отлично: я могу опубликовать в своем UpdateCustomer
методе действия, объект модели привязан и возвращается частичное представление, которое отображается обратно клиенту.
Но когда у меня три клиента, это отображает три поля ввода в моем html с id="Name"
. Одна из ошибок заключается в том, что <label for="Name">...</label>
не работает, поскольку Name
это не уникальный идентификатор.
Есть ли какой-либо способ сообщить, что ASP.NET MVC3 для отображения различных id
атрибутов (оставляя name
атрибуты нетронутыми, поскольку они используются для привязки к модели)?
Для полноты картины, вот два задействованных метода действия:
// Returns view that renders editor for each customer.
public ActionResult Index()
{
var customers = _customerService.GetCustomers();
return View(new CustomersViewModel { Customers = customers });
}
// Updates a customer and returns a partial view.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateCustomer(CustomerDto customer)
{
// Update customer in database.
return PartialView("CustomerData", customer);
}
Ответ №1:
Вместо написания уродливых циклов в представлении:
<div id="accordionKlanten">
@foreach (var customer in Model.Customers)
{
<h3><a href="#">@customer.Name</a></h3>
<div>@{ Html.RenderPartial("CustomerData", customer); }</div>
}
</div>
используйте шаблоны редактора:
<div id="accordionKlanten">
@Html.EditorFor(x => x.Customers)
</div>
и в соответствующем шаблоне редактора ( ~/Views/Shared/EditorTemplates/Customer.cshtml
):
@model Customer
<h3>
<a href="#">@customer.Name</a>
</h3>
<div>
@Html.EditorFor(x => x.FirstName)
</div>
<div>
@Html.EditorFor(x => x.LastName)
</div>
...
Теперь шаблон Customer
редактора будет выполняться автоматически для каждого элемента Customers
свойства collection в вашей модели. Единственное требование — соблюдать соглашение об именовании: оно должно быть расположено в ~/Views/Shared/EditorTemplates
папке и должно быть названо в соответствии с типом элемента коллекции. Так, например, если свойство равно IEnumerable<CustomerViewModel>
, шаблон редактора должен иметь имя CustomerViewModel.cshtml
и, очевидно, быть строго типизированным для CustomerViewModel
.
Вот и все. Теперь вы не только очистили свое представление, но и будете использовать собственные имена.
Комментарии:
1. Хорошо, это работает в том смысле, что теперь генерируются уникальные идентификаторы. Однако моя модель больше не привязана к. У меня есть обновление для каждого
Customer
, поэтому у меня также есть форма (Ajax) для каждого клиента. Правильный метод действия (UpdateCustomer
) по-прежнему вызывается, но егоcustomer
параметр не содержит значений.2. Причина в том, что model binder ожидает свойство с именем
Name
, но получает свойство с именемCustomers[0].Name
. Могу ли я исправить это, не прибегая к пользовательской модели binder?3. Да, пусть ваше действие post принимает тип параметра, который совпадает с вашей моделью представления.
4. Я понимаю это, но я хотел бы иметь действие post для каждого клиента, а не для всего списка клиентов. Никогда не будет обновляться более одного клиента одновременно, так зачем тратить пропускную способность на публикацию списка клиентов?
5. У меня такая же проблема, и я не вижу способа обойти ее, не вникая в глубины mvc, на что у меня нет времени.
Ответ №2:
Используйте for
цикл вместо foreach
loop в вашем основном представлении.
@for (var i = 0; i < Model.Customers.Count; i )
{
<h3><a href="#">@customer.Name</a></h3>
<div>@{ Html.RenderPartial("CustomerData", Model.Customers[i]); }</div>
}
Вам нужно будет настроить это, чтобы использовать a List<Customer>
или an Customer[]
.
Комментарии:
1. Нет, не используйте никаких циклов в представлении.
2. потому что, поскольку ASP.NET 2.0 существуют шаблоны редактирования / отображения. Смотрите мой ответ для получения более подробной информации. Таким образом, циклы были необходимы только в ASP.NET MVC 1.0. С этого времени представления могут быть намного чище.