asp.net-mvc-3 - partialview - render partial view mvc 5
Anidado BeginCollectionItem (1)
Estoy usando el enfoque BeginCollectionItem de Steve Sanderson para agregar contenido dinámico. Todo funciona bien cuando lo hago en el primer nivel. Sin embargo, cuando intenta implementar una colección anidada que significa BeginCollectionItem en otro BeginCollectionItem, parece que no funciona.
Mis modelos son los siguientes:
public class Order
{
[Key]
[HiddenInput]
public int id { get; set; }
[Display(Name = "Order number")]
public string number { get; set; }
...
[Display(Name = "Payment method")]
public List<PaymentMethod> payment_methods { get; set; }
...
}
public class PaymentMethod
{
public MethodOfPayment method { get; set; }
public CC cc { get; set; }
public CASH cash { get; set; }
public TT tt { get; set; }
}
public class TT
{
[Key]
public int id { get; set; }
[Required(ErrorMessage = "{0} is required.")]
[Display(Name = "Total amount")]
public double? total_value { get; set; }
...
[Display(Name = "Transfers")]
public List<Transfer> transfers { get; set; }
}
public class Transfer
{
[Key]
public int id { get; set; }
[Display(Name = "Payment")]
public int payment_id { get; set; }
[Required(ErrorMessage = "{0} is required.")]
[Display(Name = "SWIFT")]
public string swift { get; set; }
[Required(ErrorMessage = "{0} is required.")]
[Display(Name = "Amount transferred")]
public double? transfer_amount { get; set; }
[Required(ErrorMessage = "{0} is required.")]
[Display(Name = "Date transferred")]
public DateTime transfer_date { get; set; }
...
}
Ahora lo que tengo es un pedido que podría tener varios métodos de pago, y si uno de los métodos de pago es un TT (transferencia télex) podría tener varias transferencias involucradas. Implementar varios métodos de pago en un orden como una colección funciona, pero cuando trato de implementar varias transferencias dentro de un TT, ninguna de estas transferencias pasa al controlador.
Así es como se ve mi vista:
@model prj.Models.Model.Order
@using (Html.BeginForm("Create")){
@Html.ValidationSummary(true, "Creation was unsuccessful. Please correct the errors and try again.")
...
@Html.TextBoxFor(m => m.number, new { id = "txtnumber" })
...
<div id="editorPaymentRows">
@foreach (var payment in Model.payment_methods)
{
@Html.Partial("_NewPayment", payment)
}
</div>
}
En el parcial de _NewPayment:
@using prj.Helpers
@model prj.Models.Model.PaymentMethod
<div class="editPaymentRow">
@using (Html.BeginCollectionItem("payment_methods"))
{
...
<div class="editor-label">
@Html.LabelFor(m => m.tt.total_value)<req>*</req>
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.tt.total_value)
</div>
...
<div id="editorTransferRows">
@if (Model.tt != null)
{
foreach (var transfer in Model.tt.transfers)
{
@Html.Partial("_NewTransfer", transfer)
}
}
...
</div>
}
</div>
y finalmente en el parcial de _NewTransfer:
@using prj.Helpers
@model prj.Models.Model.Transfer
...
<div class="editTransferRow">
//using (Html.BeginCollectionItem("transfers"))
@using (Html.BeginCollectionItem("tt.transfers"))
{
...
<div class="editor-label">
@Html.LabelFor(m => m.swift)<req>*</req>
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.swift, new { @class = "t_swift" })
</div>
...
<div class="editor-label">
@Html.LabelFor(m => m.transfer_amount)<req>*</req>
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.transfer_amount, new { @class = "t_transfer_amount" })
</div>
...
}
</div>
Así que todo funciona, excepto en el controlador que la lista de transferencias que está en la propiedad TT de PaymentMethods es siempre nula. No se está pasando al controlador correctamente. ¿Se me escapa algo?
¿No funciona el BeginCollectionItem anidado? ¿Hay algún paso adicional que debo hacer? Por favor, arroja algo de luz. Gracias
Lo descubrí usando el método de Joe Stevens que se muestra en el siguiente enlace:
http://www.joe-stevens.com/2011/06/06/editing-and-binding-nested-lists-with-asp-net-mvc-2/
Aclamaciones
Para obtener el prefijo con un Html.BeginCollectionItem
, puede acceder a ViewData.TemplateInfo.HtmlFieldPrefix
(estoy usando el paquete nuget). Estás en el camino correcto con tt.transfers
, pero en su lugar necesitas el prefijo específico.
En lugar de simplemente
Html.BeginCollectionItem("tt.transfers")
también necesitará el prefijo del método de pago actual.
@{
var paymentMethodPrefix = ViewData.TemplateInfo.HtmlFieldPrefix;
}
@using (Html.BeginCollectionItem(paymentMethodPrefix + ".tt.transfers"))
y una prueba rápida parece que también puedes simplemente:
@using (Html.BeginCollectionItem(ViewData.TemplateInfo.HtmlFieldPrefix + ".tt.transfers"))