0

Creating a dynamic drop down menu for US states that is being called via linq. When I select a state and then click submit i walk though the code and it shows that I am passing null. The list displays as it should, Any guidance will help.

If you need any more information please let me know and ill post it.

Controller

 // GET:
    [AllowAnonymous]
    public ActionResult DealerLogin()
    {

        var results = (from a in db1.States
                       where a.CountryID == 221
                       select new SelectListItem { Value = a.StateID.ToString() , Text = a.Name }).ToList();
    }

View

@using (Html.BeginForm())
    {
@Html.AntiForgeryToken()

 <div class="form-horizontal">

<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })

    <div class="form-group">
        <div class="form-group">
            @Html.LabelFor(model => model.StateId, "States", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.StateId, Model.States.Items as List<SelectListItem>, "-- Select --", new { @class = "form-control" })
            </div>
        </div>
    <div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" value="Create" class="btn btn-default" />
    </div>
   </div>
  </div>

}

Model

 public class EditProfile2
  {
    public int StateId { get; set; }
    public SelectList States { get; set; }
   }

UPDATED

Ok I have updates everything so it matches almost to @Fran answer, seems he was missing a few things but i got it to work. I also took what @Stephen Muecke said and got rid of the validation.

Kiran Desai
  • 1,711
  • 2
  • 19
  • 37
whisk
  • 713
  • 1
  • 10
  • 34
  • Try using `@Html.DropDownListFor()` rather than `@Html.DropDownList()` This will allow you to bind to your model property. Or correct the first parameter passed to `@Html.DropDownList()` to match a valid property from your model (aka: "StateName"). Reference: https://stackoverflow.com/a/8223513/3384612 – chambo Dec 19 '17 at 18:31
  • It is just pointless to use `new SelectList(...)` to create another identical `IEnumerable` from the first one! –  Dec 19 '17 at 21:51
  • And since `States` is `IEnumerable`, then having `@Html.ValidationMessageFor(m => m.States)` makes no sense (you cannot apply validation to a SelectList), as is your `@Html.LabelFor(m => m.States)` since you do not have a form control for `States` –  Dec 19 '17 at 21:55

1 Answers1

2

You seem to be going around all the built in stuff that MVC will give you for free.

Try this

You can use attributes to define what is required and to modify the display names without actually writing into your view.

ViewModel:

 public class EditProfile2
 {    
    [Required]
    [DisplayName("State")]
    public int StateId { get; set; }
    public SelectList States {get;set;}
 }

View: only including the relevant parts

Since we used attributes on our model, we don't have to give the text in the view. we can also use DropDownListFor instead of DropDownList. And also have this declaration add the "--Select State--" option

<div class="form-group">
@Html.LabelFor(model => model.StateId, htmlAttributes: new { @class = "control-label col-md-2" })
  <div class="col-md-10">
    @Html.DropDownListFor(model.StateId, Model.States, "-- Select State --", new { @class = "form-control" })
    @Html.ValidationMessageFor(model => model.StateId, "", new { @class = "text-danger" })
  </div>
</div>

Because of our previous use of attributes and built in framework elements, our action method can slim down.

Controller Action:

[AllowAnonymous]
public ActionResult DealerLogin()
{
   var results = (from a in db1.States
              where a.CountryID == 221
              select new SelectListItem { Value= a.StateID.ToString(), Text = a.Name }).ToList();


    return View(new EditProfile2 { States = new SelectList(results)});
}
Fran
  • 6,440
  • 1
  • 23
  • 35
  • Ok this make a lot more sense, but when I change things to the way you have it it, i get a few errors. In the controller you dont have results set to a type and in the Linq query at the `a.StateID` it says that i cant implicitly convert type 'int ' to 'string. Then for the view side i get a 'The type arg for method '...' cannot be inferred from the usage. Try specifying the type arg explicitly – whisk Dec 19 '17 at 19:14
  • Changed `a.StateID` to `a.StateID.ToString()` fixed one problem. – whisk Dec 19 '17 at 19:23
  • 1
    @whisk Yeah. missed the var in the controller action. updated answer – Fran Dec 19 '17 at 19:33
  • Is there a reason why if i refresh/submit the page and it returns I would get `System.NullReferenceException: 'Object reference not set to an instance of an object.'` error? – whisk Dec 19 '17 at 21:39
  • 1
    @whisk When you post you usually redirect to some index page. See PRG pattern. If your model fails validation you need to reload the list before returning to the view. – Fran Dec 19 '17 at 21:43