I can't seem to find a good blog post that shows how to bind a model to a view without the magic strings "ViewData" (using a strongly-typed view is the approach I'm trying to take)
Does anyone know what I need to alter in the below to bind this directly to my model?
View
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable (Of MvcApplication1.Category))" %>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
<%=Html.DropDownList("CategoryList")%>
</asp:Content>
Controller
Function Index() As ActionResult
Dim list As New List(Of Category)
list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"})
list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"})
Return View()
End Function
EDIT
The final solution in VB is shown below, thanks for the big response!
Controller
Function Index() As ActionResult
Dim id As Integer = 1
Dim ProductObject As Product = mProductService.GetProductById(id)
Return View(ProductObject)
End Function
View
<%=Html.DropDownList("Category", New SelectList(Model.Categories, "CategoryID", "CategoryName"))%>
Product Class (w/ a IEnumeralbe property for the categories)
Public Class Product
Public Sub New()
End Sub
Private mProductID As Integer
Public Property ProductID() As Integer
Get
Return mProductID
End Get
Set(ByVal value As Integer)
mProductID = value
End Set
End Property
ReadOnly Property Categories() As IEnumerable(Of Category)
Get
Dim list As New List(Of Category)
list.Add(New Category With {.CategoryID = 1, .CategoryName = "Test1"})
list.Add(New Category With {.CategoryID = 2, .CategoryName = "Test2"})
Return list
End Get
End Property
End Class
The dropdown list helper takes an IEnumerable<SelectListItem>
, not an IEnumerable<Category>
. Typically what you do is have your page have a particular model. The model includes a property for the selected value from the dropdown, not the collection. You supply the collection to select from via ViewData. You could have a view-only model that includes both the properties and the collection(s) to select from, but that might mean a proliferation of classes. There's some debate as to whether proliferating classes or magic strings are worse design.
My take on your code would be something like:
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of Foo)" %>
<asp:Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
<%=Html.DropDownList("Category", ViewData("CategoryList"))%>
</asp:Content>
Function Index() As ActionResult
Dim list As New List(Of SelectListItem)
list.Add(New SelectListItem With {.Value = 1, .Text = "Test1"})
list.Add(New SelectListItem With {.Value = 2, .Text = "Test2"})
ViewData("CategoryList") = list
Return View()
End Function
where Foo is a class that contains a property Category of type int.
If you wanted to do a strongly-typed view, then have Foo have a property Categories of type SelectListItem, then change:
<%=Html.DropDownList("Category", ViewData("CategoryList"))%>
to
<%=Html.DropDownList("Category", Foo.Categories )%>
and
ViewData("CategoryList") = list
Return View()
to
Dim foo as New Foo
foo.Categories = list
Return View(foo)