0

I have a small model called GoalTypes which would contain stuff like "Running, Cycling, Weight.." etc

public class GoalType
{
    public int Id { get; set; }
    public string Type { get; set; }
}

I also have a model called Goals public class Goals { public int Id { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime StartDate  { get; set; }

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public  DateTime? EndDate { get; set; }

public string Type { get; set; }
public double Level { get; set; }

} The type field would be populated by the Type field from GoalTypes. In my goals controller I have done:

public ActionResult Create()
{
    ViewBag.listOfGoals = new SelectList(db.GoalTypes, "Id", "Type");
    return View();
}

and in my view

<div class="form-group">
    @Html.LabelFor(model => model.Type, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("listOfGoals", "Select a Goal")
        @Html.ValidationMessageFor(model => model.Type, "", new { @class = "text-danger" })
    </div>
</div>

this populates the dropdown but if i submit it, the type field is left blank

Ceri Westcott
  • 59
  • 1
  • 8
  • 1
    Because you creating form control named `listOfGoals` but your model does not have a property with that name (its `Type`). Your editing data so always use a view model. Refer the code in [this Q/A](https://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o) for a typical example (your using the worst possible overload to generate a ` –  Oct 11 '17 at 21:58
  • You might want to look at this [answer](https://stackoverflow.com/a/37819577/296861). – Win Oct 11 '17 at 22:00
  • When you submit a dropdownlist you are submitting selected value but not the complex type. Can you inspect the formcollection upon submitting? – gardarvalur Oct 11 '17 at 22:00
  • @gardarvalur im happy submitting the selected value, if Im only getting to grips with this stuff so maybe later down the line I will edit it to submit complex types. – Ceri Westcott Oct 11 '17 at 22:05
  • @CeriWestcott well, it sounds as if you need javascript to help you out with that. Maybe I am misunderstand but it sounds as if you would need to hook onto the onselect event of the dropdownlist to update the form with new selected type, perhaps with partialview injected into the form. I am not sure... – gardarvalur Oct 11 '17 at 22:16
  • @gardarvalur, You definitely do NOT need javascript. The view just needs to be be generated correctly - `@Html.DropDownListFor(m => m.Type, (IEnumerable)ViewBag.listOfGoals, "Select a Goal")` (except that the property should be `int Type`, not `string`) –  Oct 11 '17 at 22:23
  • @CeriWestcott What are the parameters of the post action? – gardarvalur Oct 11 '17 at 22:25

2 Answers2

-1

You have to pass you @ViewBag for the @Html.DropDownList, as follow:

@Html.DropDownList("listOfGoals", ViewBag.listOfGoals)

or create a helper:

public class MyHelpers{
   public static SelectList DropDownListGoalTypes(int? selected) {
        var list = db.GoalType.ToList();
        return new SelectList(list, "Id", "Type", selected);
   } 
 } 

View:

@Html.DropDownListFor(x => x.Id, MyHelpers.DropDownListGoalTypes(Model.Id))
Rodrigo de Farias
  • 657
  • 2
  • 8
  • 20
  • That's not necessary if `listOfGoals` is available in `ViewBag` https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/working-with-the-dropdownlist-box-and-jquery/using-the-dropdownlist-helper-with-aspnet-mvc – adiga Oct 12 '17 at 05:18
  • In that case, the View doesn't seem be a typed view. – Rodrigo de Farias Oct 12 '17 at 13:34
  • It's not strongly typed even with the second parameter. I think you misunderstood what I meant. If you populate `ViewBag.listOfGoals` in the controller, and you have `@Html.DropDownList("listOfGoals")` in the view, it will work as it is. No need to add the `(SelectList)ViewBag.listOfGoals` explicitly as you have suggested in the first part of the answer. – adiga Oct 12 '17 at 20:19
  • I get it, there is no need for casting. – Rodrigo de Farias Oct 12 '17 at 21:25
  • I don't know why it was downvoted, once it has given an answer, and the code above works. – Rodrigo de Farias Oct 12 '17 at 22:12
-1

@Html.DropDownList("listOfGoals", "Select a Goal") generates a select element like this:

<select name="listOfGoals" id="listOfGoals"></select> 

But you're trying to bind the dropdown to Type property in your model upon submission,

So, you need to change it to:

@Html.DropDownListFor(model => model.Type, (IEnumerable<SelectListItem>)ViewBag.listOfGoals, "Select a Goal")

or

@Html.DropDownListFor("Type", (IEnumerable<SelectListItem>)ViewBag.listOfGoals, "Select a Goal")

Now, the select is created with name attribute as "Type" and the DefaultModelBinder can bind it to the property in the POST action.

Also, as Stephen suggested, you need to change the Type to an int. Because the value of the selected option is submitted, not the text.

public int Type { get; set; }
adiga
  • 34,372
  • 9
  • 61
  • 83