-1

I am building a IEnumerable in my HTTPGet and passing it to my view. My issue is getting the selected info back to the controller using a hiddenfor.

    [HttpGet]
    public ActionResult Index(int id)
    {
        RANKDModel model = new RANKDModel();
        model.thingList = new List<thingsModel>();
        List<SelectListItem> thingRank = new List<SelectListItem>();

        var tblThingGroup = db.tblThingGroup.Where(x => x.thingCollectionID == id).Include(t => t.tblThing).Include(t => t.tblThingCollection).OrderBy(x => x.displayOrder);

        model.thingRank = new SelectList(thingRank, "Value", "Text");

        int i = 1;

        foreach (var thing in tblThingGroup)
        {
            thingRank.Add(new SelectListItem()
            {
                Value = thing.tblThing.thingID.ToString(),
                Text = i.ToString()
            });
            model.thingRank = new SelectList(thingRank, "Value", "Text");

            thingsModel things = new thingsModel();

            things.thingID = thing.tblThing.thingID;
            things.thingName = thing.tblThing.thingName;
            things.thingImgPointer = thing.tblThing.thingImgPointer;

            model.thingList.Add(things);
            i++;
        }

        return View(model);
    }

    [HttpPost]
    public ActionResult Index(RANKDModel model, IEnumerable<SelectListItem> thingRank)
    {
        //check model.Selecteditem
        return View(model);
    }

My view displays the drop downs but I cannot seem to get the values passed back to the controller on Post. Below is my view. The commented lines are failed attempts. I would rather not use ajax here. Since my value and my text fields are all I need, I feel like I should be able to pass them back to the controller even if they are not part of the model (which would be nice but I wasn't successful there either.)

@using (Html.BeginForm())
{
    <div class="col-md-8">
        @Html.TextBoxFor(modelItem => Model.firstName, new { @class = "form-control" })
        @Html.TextBoxFor(modelItem => Model.lastName, new { @class = "form-control" })
    </div>

    <table class="table">
        @Html.HiddenFor(modelItem => Model.thingRank)

        @for (int i = 0; i < Model.thingList.Count; i++)
        {
            string imagePointer = "/Areas/RANKD/thingImages/" + Model.thingList[i].thingImgPointer;
            <tr>
                <td>
                    @Html.HiddenFor(modelItem => Model.thingList[i].thingID)

                    @Html.DropDownListFor(modelItem => modelItem.thingRank, (IEnumerable<SelectListItem>)ViewBag.thingRank, "Rank it Bro.") @*Model.thingRank.Items as IEnumerable<SelectListItem>)*@

                    @*@Html.HiddenFor(modelItem => modelItem.thingRank[Model.thingRank(i)].Value)*@

                    @Html.HiddenFor(modelItem => modelItem.thingRank[Model.thingRank.IndexOf(i)].Value)

                    @*@Html.HiddenFor(modelItem => modelItem.thingRank)*@

                    @Html.DisplayFor(modelItem => Model.thingList[i].thingName)
                </td>
                <td>
                    <img src="@imagePointer" alt="@Model.thingList[i].thingName" height="75" />
                </td>
            </tr>
        }

    </table>

    <input type="submit" value="RANK IT" class="btn btn-default" />
}

Am I just missing something in my hiddenfor?

Adding the code in my RANDModel

[Serializable]
public class RANKDModel
{
    public string firstName { get; set; }
    public string lastName { get; set; }
    public List<thingsModel> thingList { get; set; }
    public IEnumerable<SelectListItem> thingRank { get; set; }
}
joerdie
  • 379
  • 1
  • 6
  • 18
  • There are tons of tutorials on how to use dropdownlist in asp mvc. Why do you need all the items in post? You just need the item the user selected, thats it. – CodingYoshi Feb 19 '18 at 02:10
  • I agree I only need the item selected. In my for loop I am trying to get to that with the hiddenfor. Is that where I am going wrong? And I have seen many of the examples but none seem to work for my case. – joerdie Feb 19 '18 at 02:13
  • The selected item will be in `model.thingRank`. I need to see the code you have in `RANKDModel` – CodingYoshi Feb 19 '18 at 02:18
  • I have added the model at the bottom of my question. Thank you. – joerdie Feb 19 '18 at 02:35
  • There is so much wrong with everything your doing here its impossible to know where to start. You code for generating an `IEnumerable` does not even make sense. I suggest you start by reading the following to at least understand some basics - [Post an HTML Table to ADO.NET DataTable](https://stackoverflow.com/questions/30094047/post-an-html-table-to-ado-net-datatable/30094943#30094943) –  Feb 19 '18 at 04:06
  • and [The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable'](https://stackoverflow.com/questions/34366305/the-viewdata-item-that-has-the-key-xxx-is-of-type-system-int32-but-must-be-o), and [Can the ViewBag name be the same as the Model property name in a DropDownList?](https://stackoverflow.com/questions/37161202/can-the-viewbag-name-be-the-same-as-the-model-property-name-in-a-dropdownlist), –  Feb 19 '18 at 04:09
  • and [MVC5 - How to set “selectedValue” in DropDownListFor Html helper](https://stackoverflow.com/questions/41719293/mvc5-how-to-set-selectedvalue-in-dropdownlistfor-html-helper/41731685#41731685), and [MVC5 Razor html.dropdownlistfor set selected when value is in array](https://stackoverflow.com/questions/37407811/mvc5-razor-html-dropdownlistfor-set-selected-when-value-is-in-array/37411482#37411482) –  Feb 19 '18 at 04:10

1 Answers1

2

You are creating many dropdowns within the for loop. I guess you need them so the user can select something in each row. Right now you have this:

@Html.DropDownListFor(modelItem => modelItem.thingRank, 
    (IEnumerable<SelectListItem>)ViewBag.thingRank, "Rank it Bro.")

So the Razor view engine will create many HTML tags and set the name attribute to thingRank. You do not want that. You want to give each element a unique name. Also when something is selected in each dropdownlist, you will need it later during form submission in your POST method. Therefore, add one more property to your model:

public List<int> SelectedRanks { get; set; }

In the GET action, you will need to set that property to the same number of items as thingList because you need a dropdown for each one of them. Thus do this:

// ...other code
model.SelectedRanks = new List<int>(model.thingList.Count);
return View(model);

Now in your view, use this code in your for loop (please note the indexing operation here):

@Html.DropDownListFor(modelItem => this.Model.SelectedRanks[i], 
    this.Model.thingRank, "Rank it Bro.")

Now each dropdownlist will have a unique name. For example, if you have 3 dropdowns, their names would be: SelectedRanks[0], SelectedRanks[1], and SelectedRanks[2].

When the user submits the form, you can retrieve the selected values from each dropdownlist like this:

[HttpPost]
public ActionResult Index(RANKDModel model)
{
    // model.SelectedRanks will have the value selected
    // For example, model.SelectedRanks[0] will have the value selected
    // in the first dropdown, model.SelectedRanks[1] will have value 
    // selected in the second dropdown and so on.
}

Some Final Suggestions

  1. Please give your properties meaningful names. For example, thingList is not a meaningful name.
  2. Use Pascal Notation for class names and property names. So instead of thingList, it should be ThingList.
  3. If you have an acronym which is 2 chars, use upper case for it, otherwise use Pascal Notation. For example, RANKDModel should be RankdModel (shouldn't it be spelled RankedModel?)
CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • With one other minor change, that did it thank you. In my get method I was assigning the id of each item in the list rather than the integer value. Once I changed that, it worked fine. As for your other suggestions. It is likely I will take them under advisement. This little app started out one evening with some friends and was kind of a joke and I was just interested in pursuing it further. Thank you for the help. As I am sure it is clear, I am no expert at MVC. – joerdie Feb 19 '18 at 15:58