Hi,
I've seen articles and blog posts indicating what I am attempting to do should be supported; however, I have been unable to get it working so hopefully someone can confirm that it does/does not work and/or tell me what I am doing wrong.
I have a "complex" model (Invoice containing a List of InvoiceItem) that I am attempting to bind to and I would only like to update certain attributes and certain items/indexes on the List objects). I believe my issue is primarily with whether or not the include/exclude works for List data. I am attempting to use UpdateModel() with its includeProperties, like so:
Public Function Edit(ByVal id As String, ByVal values As FormCollection)
Dim invoice As Invoice = _getInvoice(id)
UpdateModel(invoice, "", New String() {"InvoiceDate", "CustomerName", "Items[0].Price"})
'Do some stuff...
End Function
All of my code is below...
I have the following model:
Public Class Invoice
Private _invoiceNumber As String
Private _invoiceDate As DateTime
Private _customerName As String
Private _items As List(Of InvoiceItem)
Public Property InvoiceNumber() As String
Get
Return _invoiceNumber
End Get
Set(ByVal value As String)
_invoiceNumber = value
End Set
End Property
Public Property InvoiceDate() As DateTime
Get
Return _invoiceDate
End Get
Set(ByVal value As DateTime)
_invoiceDate = value
End Set
End Property
Public Property CustomerName() As String
Get
Return _customerName
End Get
Set(ByVal value As String)
_customerName = value
End Set
End Property
Public Property Items() As List(Of InvoiceItem)
Get
Return _items
End Get
Set(ByVal value As List(Of InvoiceItem))
_items = value
End Set
End Property
End Class
Public Class InvoiceItem
Private _itemNumber As Integer
Private _description As String
Private _price As Decimal
Public Property ItemNumber() As Integer
Get
Return _itemNumber
End Get
Set(ByVal value As Integer)
_itemNumber = value
End Set
End Property
Public Property Description() As String
Get
Return _description
End Get
Set(ByVal value As String)
_description = value
End Set
End Property
Public Property Price() As Decimal
Get
Return _price
End Get
Set(ByVal value As Decimal)
_price = value
End Set
End Property
End Class
I have the following View:
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of MvcApplication2.Invoice)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Edit</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<%=Html.ValidationSummary()%>
<% Using Html.BeginForm() %>
<fieldset>
<legend>Fields</legend>
<p>
<label for="InvoiceNumber">InvoiceNumber:</label>
<%= Html.TextBox("InvoiceNumber") %>
<%= Html.ValidationMessage("InvoiceNumber", "*") %>
</p>
<p>
<label for="InvoiceDate">InvoiceDate:</label>
<%= Html.TextBox("InvoiceDate") %>
<%= Html.ValidationMessage("InvoiceDate", "*") %>
</p>
<p>
<label for="CustomerName">CustomerName:</label>
<%= Html.TextBox("CustomerName") %>
<%= Html.ValidationMessage("CustomerName", "*") %>
</p>
<%For x As Integer = 0 To ViewData.Model.Items.Count - 1%>
<p>
<label for="Item<%=ViewData.Model.Items(x).ItemNumber %>">Item <%=ViewData.Model.Items(x).ItemNumber%>:</label>
<%=Html.Hidden("Items.Index", x)%>
<%=Html.TextBox(String.Format("Items[{0}].Description", x), ViewData.Model.Items(x).Description)%>
<%=Html.ValidationMessage("Description", "*")%>
<%=Html.TextBox(String.Format("Items[{0}].Price", x), ViewData.Model.Items(x).Price)%>
<%=Html.ValidationMessage("Price", "*")%>
</p>
<%Next x%>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% End Using %>
</asp:Content>
And here is my Controller:
Public Class InvoicingController
Inherits System.Web.Mvc.Controller
Private Function _getInvoice(ByVal id As String) As Invoice
Dim invoice As New Invoice
invoice.InvoiceNumber = id
invoice.CustomerName = "John Doe"
invoice.InvoiceDate = DateTime.Now
invoice.Items = New List(Of InvoiceItem)
For x As Integer = 1 To 5
Dim item As InvoiceItem = New InvoiceItem
item.ItemNumber = x
item.Description = String.Format("Item {0}", x)
item.Price = 100 + x
invoice.Items.Add(item)
Next
Return invoice
End Function
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal id As String) As ActionResult
Dim invoice As Invoice = _getInvoice(id)
Return View(invoice)
End Function
'UpdateModel(invoice, "", New String() {"InvoiceDate", "CustomerName", "Items"}) 'NOTE: THis line appears to update any InvoiceItem attributes that are supplied
UpdateModel(invoice, "", New String() {"InvoiceDate", "CustomerName", "Items[0].Price"}) 'This line does not allow the first item's Price to be updated.
Return View()
End Function
End Class
Thanks in advance!