 |
BOOK: Professional ASP.NET MVC 2
 | This is the forum to discuss the Wrox book Professional ASP.NET MVC 2 by Jon Galloway, Scott Hanselman, Phil Haack, Scott Guthrie, Rob Conery; ISBN: Professional ASP.NET MVC 2 |
Welcome to the p2p.wrox.com Forums.
You are currently viewing the BOOK: Professional ASP.NET MVC 2 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
|
|
|
|

January 22nd, 2011, 09:27 PM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Quote:
Originally Posted by ebmudder
Hi JMS: Thanks for posting your solution...I tried modifying my pages as per your code, but my update is still failing. What did you do finally to get it to work?
Or can anyone help me figure out how to debug what's happening in the TryUpdateModel?
EDIT: I reverted the code back to "UpdateModel(dinner)" from "UpdateModel(dinner, "Dinner")" and now it works (i.e. the form saves properly). I'm really newbie at this, so if anyone can explain to me why it works one way but not the other, I would appreciate it!
|
OK, final post...I realized that there's no way to "automagically" map a selectList named "Countries" back to the "Country" field in the model. I re-named the select List to "Country" like so:
DinnerFormViewModel.cs
Code:
private static string[] _countries = new[] { "USA", "Canada", "Mexico", "Chile", "Peru" };
//Properties
public Dinner Dinner { get; private set; }
public SelectList Country { get; private set; }
...
//Constructor
public DinnerFormViewModel(Dinner dinner)
{
Dinner = dinner;
Country = new SelectList(_countries, dinner.Country);
}
edit.aspx
Code:
<%: Html.LabelFor(m => m.Country) %>
<%:Html.DropDownListFor(m=>m.Country, Model.Country) %>
and this _almost_ works. It correctly updates the database when updateModel(dinner) is called, but it does not correctly set the selected item in the select List when the page first loads. Instead the first item in the select list is displayed. So close! What am I missing to correctly pass the model's value to the select list when the page first loads?
|

January 22nd, 2011, 10:57 PM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
and for my final, final post...I found a similar thread on forums.asp.net where the user manually mapped the SelectList in the view to the name of the field, which does seem to work:
DinnerFormViewModel.cs
Code:
private static string[] _countries = new[] { "USA", "Canada", "Mexico", "Chile", "Peru" };
//Properties
public Dinner Dinner { get; private set; }
public SelectList Countries { get; private set; }
...
//Constructor
public DinnerFormViewModel(Dinner dinner)
{
Dinner = dinner;
Countries = new SelectList(_countries, dinner.Country);
}
Edit.aspx
Code:
<%: Html.LabelFor(m => m.Countries) %>
<%:Html.DropDownList("Country", Model.Countries)%>
This works, but it seems like a hack that breaks the integrity of the ViewModel.
|

January 24th, 2011, 12:03 PM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 9
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Try this one
Recall that the model is actually the ViewModel (DinnerFormViewModel). The DinnerFormViewModel exposes the Dinner model object as a property, and additionally exposes the Countries string array as another property (specifically for the DropDownList). Hope this makes sense.
Code:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NerdDinner.Models.DinnerFormViewModel>" %>
...
<p>
<%= Html.LabelFor(model => model.Dinner.Country)%>: <br />
<%= Html.DropDownListFor(model => model.Dinner.Country, Model.Countries as SelectList)%>
</p>
|

January 25th, 2011, 11:08 AM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Quote:
Originally Posted by Olin
Recall that the model is actually the ViewModel (DinnerFormViewModel). The DinnerFormViewModel exposes the Dinner model object as a property, and additionally exposes the Countries string array as another property (specifically for the DropDownList). Hope this makes sense.
Code:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<NerdDinner.Models.DinnerFormViewModel>" %>
...
<p>
<%= Html.LabelFor(model => model.Dinner.Country)%>: <br />
<%= Html.DropDownListFor(model => model.Dinner.Country, Model.Countries as SelectList)%>
</p>
|
Thanks Olin: That almost gets me there. I didn't mention that I diverged somewhat from the original code, by exposing all the "dinner" elements as separate properties, with the "Countries" property as a SelectList and not a string (this was recommended in a different thread). So my DinnerFormView Model now looks like:
Code:
public class DinnerFormViewModel
{
private static string[] _countries = new[] { "USA", "Canada", "Mexico", "Chile", "Peru" };
//Properties
public Dinner myDinner { get; private set; }
public SelectList Countries { get; private set; }
// Properties
public string Title
{
get { return myDinner.Title; }
set { myDinner.Title = value; }
}
public DateTime EventDate
{
get { return myDinner.EventDate; }
set { myDinner.EventDate = value; }
}
public string Description
{
get { return myDinner.Description; }
set { myDinner.Description = value; }
}
public string Address
{
get { return myDinner.Address; }
set { myDinner.Address = value; }
}
public string ContactPhone
{
get { return myDinner.ContactPhone; }
set { myDinner.ContactPhone = value; }
}
public string HostedBy
{
get { return myDinner.HostedBy; }
set { myDinner.HostedBy = value; }
}
public Double Latitude
{
get { return myDinner.Latitude; }
set { myDinner.Latitude = value; }
}
public Double Longitude
{
get { return myDinner.Longitude; }
set { myDinner.Longitude = value; }
}
//Constructor
public DinnerFormViewModel(Dinner dinner)
{
myDinner = dinner;
Countries = new SelectList(_countries, dinner.Country);
}
}
So I was implementing the properties on the DinnerForm.ascx partial as:
Code:
<%: Html.TextBoxFor(m => m.ContactPhone) %>
Using your code, I was able to get the select list to work properly:
Code:
<%:Html.DropDownListFor(model =>Model.myDinner.Country, Model.Countries as SelectList)%>
But, it isn't updating properly, because the HTML renders as: name="myDinner.Country" instead of name="Country".
But your comment led me to try adding the "Country" property as well as the "Countries" property to the Model, so I just added:
Code:
public string Country {
get { return myDinner.Country; }
set { myDinner.Country = value; }
}
and updated the view to:
Code:
<%:Html.DropDownListFor(model =>Model.Country, Model.Countries)%>
...and now everything works! Is this correct, or am I still hacking around the problem?
|

January 25th, 2011, 11:29 AM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 9
Thanks: 2
Thanked 0 Times in 0 Posts
|
|
Ebmudder: okay, I didn't realize you had exposed the Dinner properties individually as DinnerFormViewModel properties. That is perfectly fine, in my opinion. Either approach could be used, depending on what you are trying to achieve.
Mine (and the book's) way of exposing the Dinner object as a property is a nice quick and easy implementation. Fewer lines of code since you don't have to list out all the Dinner properties. However it's all or nothing, since everything (including Lat/long, etc.) is now exposed.
Your way (of explicitly exposing certain Dinner properties) might be better in that you have complete control of which Dinner properties are exposed. Given the book's description a ViewModel, maybe they should have taken this approach. (They probably chose the former way in the interest of brevity).
|

January 25th, 2011, 11:34 AM
|
Registered User
|
|
Join Date: Jan 2011
Posts: 13
Thanks: 0
Thanked 0 Times in 0 Posts
|
|
Quote:
Originally Posted by Olin
Ebmudder: okay, I didn't realize you had exposed the Dinner properties individually as DinnerFormViewModel properties. That is perfectly fine, in my opinion. Either approach could be used, depending on what you are trying to achieve.
Mine (and the book's) way of exposing the Dinner object as a property is a nice quick and easy implementation. Fewer lines of code since you don't have to list out all the Dinner properties. However it's all or nothing, since everything (including Lat/long, etc.) is now exposed.
Your way (of explicitly exposing certain Dinner properties) might be better in that you have complete control of which Dinner properties are exposed. Given the book's description a ViewModel, maybe they should have taken this approach. (They probably chose the former way in the interest of brevity).
|
Thanks, Olin! I'm just feeling my way forward at this point, so your comments are extremely helpful...I was "nervous" about having two public properties that related back to the same data, but now looking at it, it makes perfect sense...I really appreciate your helping me work through the logic.
|
|
 |
|