locked
DropDownListFor validation RRS feed

  • Question

  • User371048076 posted

    Hi all ,

    I don't know how to retrieve a DropDownListFor value on form post and how to validate it.

    This is my scenario:

    HTML markup:


    <div>
    <%= Html.LabelFor(m => m.Location) %>
    <%= Html.DropDownListFor(m => m.Location, Model.Location, string.Empty) %>
    <%= Html.ValidationMessageFor( m => m.Location, "*") %>
    </div>



    Model:


    public class ProjectModel
    {
      [DisplayName("Location:")]
      [Required(ErrorMessage = "*")]
      public List<SelectListItem> Location { get; set; }
    }
    

    I'm not able to validate this dorpdown and when I test if the Model is valid I have to re-fill the Location property


    [HttpPost]
    public ActionResult Index(ProjectModel project)
    {
      if (ModelState.IsValid)
      {
        // do something ...
        return View("/");
      }
      else
      {
        project.Location = rep.LocationList(); // rep is my db repository
        return View(project);
      }
    



    otherwise I get an "object reference not set" error on post-back.

    Any idea?

    thanks,

    Davide



    Sunday, July 18, 2010 12:39 PM

Answers

  • User1738250506 posted

    The error occurs because the model binder is trying to assign the value of the selected item to your Location property which is a List<SelectListItem>

    I suggest you to change your code in this way

    The error occurs because the model binder is trying to assign the value of the selected item to your Location property which is a List<SelectListItem>
    
    I suggest you to change your code in this way
    
    // Model Class
    public class ProjectModel
    {
    	public List<SelectListItem> LocationList { get; set; }
    
    	[DisplayName("Location:")]   
    	[Required(ErrorMessage = "*")]   
    	public string Location { get; set; }
    }
    
    // Controller Methods
    public ActionResult Index()
    {
    	ProjectModel projectModel = new ProjectModel ();
    
    	// Assign your list
    	projectModel.LocationList = rep.LocationList();
    
    	// Send model to view
    	ViewData.Model = projectModel;
    }
    
    [HttpPost]   
    public ActionResult Index(ProjectModel project)   
    {   
    	if (ModelState.IsValid)
    	{
    		return View();
    	}   
    	else
    	{
    		// Here the property of Location property will be filled with the Value property of the selected ListItem
    		return View (project);
    	}
    }
    <!-- View -->
    <div>
    	<%= Html.LabelFor(m => m.Location) %>
    	<%= Html.DropDownListFor(m => m.Location, Model.LocationList, string.Empty) %>
    	<%= Html.ValidationMessageFor( m => m.Location, "*") %>
    </div>

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 19, 2010 4:37 AM
  • User1738250506 posted

    Rhe view data is a bridge to transfer your model to the view. In your original example, by calling the View method like "View (project)", you are passing your model to the View method which in turn assigns it to the ViewData.Model before rendering the view.

    If you do not like accessing the ViewData object at all, you can replace the two statements with one as in

    public ActionResult Index()   
    {   
        ProjectModel projectModel = new ProjectModel ();   
      
        // Assign your list   
        projectModel.LocationList = rep.LocationList();   
      
        // Send model to view   
        return View (projectModel);   
    }
     
    I am glad that I could be of some help. Can mark my posts as answer please?
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 19, 2010 6:28 PM

All replies

  • User1738250506 posted

    The first and second parameters of teh DropDownListFor method are independent values. An example, in which I have used it in one of my projects to populate a country dropdown,

    Html.DropDownListFor (p => p.Country, geoMgr.Countries.Select (p => new SelectListItem () { Text = p.getName (), Value = p.getName (), Selected = string.Equals (p.getCode (), currentCountryCode, StringComparison.OrdinalIgnoreCase) }).OrderBy (p => p.Text))

    The first parameter is the property selector for your model to indicate which property to fill with the post data. The second parameter is just a list of items used to populate the dropdown loist box.

     

    My model

    [Required (AllowEmptyStrings = false, ErrorMessage = "Country is required")]
    public string Country
    {
    	get;
    	set;
    }
    


    If you want to use the model object to supply the drop down list items, use a separate property like

    Html.DropDownListFor(m => m.Location, Model.LocationListItemsstring.Empty)

     

     

    Sunday, July 18, 2010 5:13 PM
  • User371048076 posted

    Thank you.

    Which kind of object "Countries" is?


    I tried to change from a List of SelectListItems to a Dictionary. anyway now I get this error:


    The parameter conversion from type 'System.String' to type 'System.Web.Mvc.SelectListItem' failed because no type converter can convert between these types


    even if I use this code:


    <%= Html.DropDownList("Location", new SelectList(Model.Location, "Key", "Value")) %>



    Sunday, July 18, 2010 5:41 PM
  • User1738250506 posted

    The error occurs because the model binder is trying to assign the value of the selected item to your Location property which is a List<SelectListItem>

    I suggest you to change your code in this way

    The error occurs because the model binder is trying to assign the value of the selected item to your Location property which is a List<SelectListItem>
    
    I suggest you to change your code in this way
    
    // Model Class
    public class ProjectModel
    {
    	public List<SelectListItem> LocationList { get; set; }
    
    	[DisplayName("Location:")]   
    	[Required(ErrorMessage = "*")]   
    	public string Location { get; set; }
    }
    
    // Controller Methods
    public ActionResult Index()
    {
    	ProjectModel projectModel = new ProjectModel ();
    
    	// Assign your list
    	projectModel.LocationList = rep.LocationList();
    
    	// Send model to view
    	ViewData.Model = projectModel;
    }
    
    [HttpPost]   
    public ActionResult Index(ProjectModel project)   
    {   
    	if (ModelState.IsValid)
    	{
    		return View();
    	}   
    	else
    	{
    		// Here the property of Location property will be filled with the Value property of the selected ListItem
    		return View (project);
    	}
    }
    <!-- View -->
    <div>
    	<%= Html.LabelFor(m => m.Location) %>
    	<%= Html.DropDownListFor(m => m.Location, Model.LocationList, string.Empty) %>
    	<%= Html.ValidationMessageFor( m => m.Location, "*") %>
    </div>

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 19, 2010 4:37 AM
  • User371048076 posted

    That works, thank you very much.

    Anyway I'm not completly satisfied because I prefer avoid the use of ViewData.

    I'll use your solution, but if there is something better ...

    thanks,

    Davide

    Monday, July 19, 2010 1:04 PM
  • User1738250506 posted

    Rhe view data is a bridge to transfer your model to the view. In your original example, by calling the View method like "View (project)", you are passing your model to the View method which in turn assigns it to the ViewData.Model before rendering the view.

    If you do not like accessing the ViewData object at all, you can replace the two statements with one as in

    public ActionResult Index()   
    {   
        ProjectModel projectModel = new ProjectModel ();   
      
        // Assign your list   
        projectModel.LocationList = rep.LocationList();   
      
        // Send model to view   
        return View (projectModel);   
    }
     
    I am glad that I could be of some help. Can mark my posts as answer please?
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, July 19, 2010 6:28 PM
  • User1738250506 posted

    Please mark my post(s) as answer(s) to help me build my community recognition as well as others to easily find solution to their similar problems. 

    Tuesday, July 20, 2010 1:37 PM
  • User-1166080021 posted

    Hi maybe yo can use the Html.ValidationSummary like this:

    public ActionResult Index()

    {

           var modelState = new ModelState();

           modelState.Errors.Add("Ouch");

           ModelState["Name"] = modelState;

     

          return View();

    }

     

    or maybe the Html.ValidationMessage

     

    public ActionResult Index()

    {

            var modelState = new ModelState();

            modelState.Errors.Add("Ouch");

            ModelState["Name"] = modelState;

     

            return View();

    }

     

    I hope this can help you, good luck!!!!

    Wednesday, July 21, 2010 12:02 PM