locked
Dropdown list in MVC view RRS feed

  • Question

  • User-501297529 posted

    I'm trying to create a dropdown list and I am getting error ' There is no argument given that corresponds to the required formal parameter 'htmlAttributes' of 'IHtmlHelper<ManageItemsStatusesEditViewModel>.DropDownListFor<TResult>(Expression<Func<ManageItemStatusesEditViewModel, TResult>>, IEnumerable<SelectListItem>, string, object)'. 

    My dropdown code in the View:

    <div class="row">
                            <div class="col-md-2">Color : <label for="Color" /></div>                        
                            @Html.DropDownListFor(model => model.StatusToEdit.Color.Name, Model.AvailableColors, new { @class = "form-control" })                        
                           
                        </div>

    Wednesday, July 31, 2019 2:06 PM

Answers

  • User475983607 posted

    bootzilla

    Not sure what is confusing.

    The problem you are trying to solve is not clear given the code.

    bootzilla

    I posted the code in the Model, View and a class file that has mocked list. I'm using both MVC and Razor? Not sure what you mean. The View is a Razor page, the model is the model and so on. I'm also following the link you provided in the second post as far as building the dropdown/select list.

    The code you posted has all the earmarks of Razor Pages which is another ASP.NET Core framework.  It appears you are copying and pasting code snippets without taking the time to understand the code.

    ASP.NET MVC Example.

    Models

        public class ItemStatus
        {
            public int StatusId { get; set; }
            public string Name { get; set; }
            public int ColorId { get; set; }
        }
    
        public class StatusColor
        {
            public int ColorId { get; set; }
            public string Name { get; set; }
        }

    Controller.Action

        public class HomeController : Controller
        {
    
            private static List<ItemStatus> _mockStatuses = new List<ItemStatus>
            {
                new ItemStatus  { StatusId = 1, Name = "Complete", ColorId = 1},
                new ItemStatus  { StatusId = 2, Name = "Complete, Ongoing",ColorId = 2},
                new ItemStatus  { StatusId = 3, Name = "In Process", ColorId = 3}
            };
    
            private static List<StatusColor> _mockColors = new List<StatusColor>()
            {
                new StatusColor() { ColorId = 1, Name = "Auto" },
                new StatusColor() { ColorId = 2, Name = "Green" },
                new StatusColor() { ColorId = 3, Name = "Yellow" }
            };
    
            public IActionResult Index()
            {
                List<SelectListItem> options = (from o in _mockColors
                                                select new SelectListItem()
                                                {
                                                    Text = o.Name,
                                                    Value = o.ColorId.ToString()
                                                }).ToList();
                ViewBag.Options = options;
                return View(_mockStatuses);
            }

    View

    @model List<MvcApiCore20Identity.Models.ItemStatus>
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h2>Index</h2>
    
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                    <th>
    
                        @Html.DisplayNameFor(model => Model[0].StatusId)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].ColorId)
                    </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @for (var i = 0; i < Model.Count(); i++)
            {
                <tr>
                    <td>
                        <input asp-for=@Model[i].StatusId />
                    </td>
                    <td>
                        <input asp-for="@Model[i].Name" />
                    </td>
                    <td>
                        <select asp-for="@Model[i].ColorId" asp-items="@ViewBag.Options as List<SelectListItem>"></select>
                    </td>
                    <td>
                        @Html.ActionLink("Edit", "Edit", new {  id=@Model[i].StatusId  }) |
                        @Html.ActionLink("Details", "Details", new { id=@Model[i].StatusId }) |
                        @Html.ActionLink("Delete", "Delete", new {  id=@Model[i].StatusId })
                    </td>
                </tr>
            }
        </tbody>
    </table>
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 31, 2019 6:28 PM

All replies

  • User475983607 posted

    You are not using the correct overload.

    The following link explains how to implement select lists in ASP.NET Core.

    https://www.learnrazorpages.com/razor-pages/forms/select-lists

    Wednesday, July 31, 2019 3:38 PM
  • User-501297529 posted

    I'm trying this but I get a null value error on it.

    <select asp-for="StatusToEdit.Color.Name"
                                    asp-items="@(new SelectList(Model.AvailableColors))">
                                <option>Please select one</option>
                            </select>

    I have this set in the model

    public IEnumerable<StatusColor> AvailableColors { get; set; }

    Tried this too. This at least I don't get an error but I get nothing in the dropdown except 'Please select..'

    <select asp-for="StatusToEdit.Color.Name"
                                    asp-items="Model.AvailableColors">
                                <option>Please select one</option>
                            </select>
     public SelectList AvailableColors { get; set; }
            public void OnGet()
            {
                AvailableColors = new SelectList(nameof(StatusColor.Name));
            }

    Wednesday, July 31, 2019 3:51 PM
  • User-474980206 posted

    the docs are pretty clear. the asp-items should be a IEnumerable od SelectListItems. The SelectList class has several overloads for building one.  You don't define what AvailableColors properties you want from to be the value and text of  select options. 

     asp-items="@(new SelectList(Model.AvailableColors, "Name", "Name"))">

     though if you made Model.AvailableColor a collection of SelectListItems (best practice), then its just:

     asp-items="Model.AvailableColors">
    Wednesday, July 31, 2019 5:11 PM
  • User-501297529 posted

    bruce (sqlwork.com)

    the docs are pretty clear. the asp-items should be a IEnumerable od SelectListItems. The SelectList class has several overloads for building one.  You don't define what AvailableColors properties you want from to be the value and text of  select options. 

     asp-items="@(new SelectList(Model.AvailableColors, "Name", "Name"))">

     though if you made Model.AvailableColor a collection of SelectListItems (best practice), then its just:

     asp-items="Model.AvailableColors">

    I've tried that first option and it still doesn't work.

    Let me show you all the essential code so you can see what i'm missing.

    This is what I've tried so far:

    Model:

    public SelectList AvailableColors { get; set; }
            public void OnGet()
            {
                AvailableColors = new SelectList(nameof(StatusColor.ColorId), nameof(StatusColor.Name));
            }

    Mocklist in class file:

     private static List<ItemStatus> _mockStatuses = new List<ItemStatus>
            {
                new ItemStatus  { StatusId = 1, Name = "Complete", Color = new StatusColor{ ColorId = 1, Name = "Auto" } },
                new ItemStatus  { StatusId = 2, Name = "Complete, Ongoing", Color = new StatusColor{ ColorId = 2, Name = "Green" }},
                new ItemStatus  { StatusId = 3, Name = "In Process", Color = new StatusColor{ ColorId = 3, Name = "Yellow" }}
            };

    View:

    <select name="ColorId" asp-for="StatusToEdit.Color.Name"
                                    asp-items="Model.AvailableColors">
                                <option>Please select one</option>
                            </select>

    Wednesday, July 31, 2019 5:22 PM
  • User475983607 posted

    The code is a bit confusing.  Are you building a Razor Pages application or MVC?  Are you trying to populate a select with a list of colors?  If so, where are you populating a list of colors as this is not part of the code.

    The constructor overload is not valid.  What do you expect the code below is doing?  Seems you are not using the Visual Studio debugger?

            public SelectList AvailableColors { get; set; }
            public void OnGet()
            {
                AvailableColors = new SelectList(nameof(StatusColor.ColorId), nameof(StatusColor.Name));
            }
    

    Wednesday, July 31, 2019 5:43 PM
  • User-501297529 posted

    mgebhard

    The code is a bit confusing.  Are you building a Razor Pages application or MVC?  Are you trying to populate a select with a list of colors?  If so, where are you populating a list of colors as this is not part of the code.

    The constructor overload is not valid.  What do you expect the code below is doing?  Seems you are not using the Visual Studio debugger?

            public SelectList AvailableColors { get; set; }
            public void OnGet()
            {
                AvailableColors = new SelectList(nameof(StatusColor.ColorId), nameof(StatusColor.Name));
            }

    Not sure what is confusing. I posted the code in the Model, View and a class file that has mocked list. I'm using both MVC and Razor? Not sure what you mean. The View is a Razor page, the model is the model and so on. I'm also following the link you provided in the second post as far as building the dropdown/select list.

    I have tried debugging and it doesn't get to that part of the code to see what is going on. I expect that code to populate a dropdown list of colors based off my mocked list. The  nameof(StatusColor.Name) I'm expecting that to populate the name of the color from the mock.

    Wednesday, July 31, 2019 5:54 PM
  • User475983607 posted

    bootzilla

    Not sure what is confusing.

    The problem you are trying to solve is not clear given the code.

    bootzilla

    I posted the code in the Model, View and a class file that has mocked list. I'm using both MVC and Razor? Not sure what you mean. The View is a Razor page, the model is the model and so on. I'm also following the link you provided in the second post as far as building the dropdown/select list.

    The code you posted has all the earmarks of Razor Pages which is another ASP.NET Core framework.  It appears you are copying and pasting code snippets without taking the time to understand the code.

    ASP.NET MVC Example.

    Models

        public class ItemStatus
        {
            public int StatusId { get; set; }
            public string Name { get; set; }
            public int ColorId { get; set; }
        }
    
        public class StatusColor
        {
            public int ColorId { get; set; }
            public string Name { get; set; }
        }

    Controller.Action

        public class HomeController : Controller
        {
    
            private static List<ItemStatus> _mockStatuses = new List<ItemStatus>
            {
                new ItemStatus  { StatusId = 1, Name = "Complete", ColorId = 1},
                new ItemStatus  { StatusId = 2, Name = "Complete, Ongoing",ColorId = 2},
                new ItemStatus  { StatusId = 3, Name = "In Process", ColorId = 3}
            };
    
            private static List<StatusColor> _mockColors = new List<StatusColor>()
            {
                new StatusColor() { ColorId = 1, Name = "Auto" },
                new StatusColor() { ColorId = 2, Name = "Green" },
                new StatusColor() { ColorId = 3, Name = "Yellow" }
            };
    
            public IActionResult Index()
            {
                List<SelectListItem> options = (from o in _mockColors
                                                select new SelectListItem()
                                                {
                                                    Text = o.Name,
                                                    Value = o.ColorId.ToString()
                                                }).ToList();
                ViewBag.Options = options;
                return View(_mockStatuses);
            }

    View

    @model List<MvcApiCore20Identity.Models.ItemStatus>
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h2>Index</h2>
    
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                    <th>
    
                        @Html.DisplayNameFor(model => Model[0].StatusId)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].ColorId)
                    </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @for (var i = 0; i < Model.Count(); i++)
            {
                <tr>
                    <td>
                        <input asp-for=@Model[i].StatusId />
                    </td>
                    <td>
                        <input asp-for="@Model[i].Name" />
                    </td>
                    <td>
                        <select asp-for="@Model[i].ColorId" asp-items="@ViewBag.Options as List<SelectListItem>"></select>
                    </td>
                    <td>
                        @Html.ActionLink("Edit", "Edit", new {  id=@Model[i].StatusId  }) |
                        @Html.ActionLink("Details", "Details", new { id=@Model[i].StatusId }) |
                        @Html.ActionLink("Delete", "Delete", new {  id=@Model[i].StatusId })
                    </td>
                </tr>
            }
        </tbody>
    </table>
    

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, July 31, 2019 6:28 PM
  • User-501297529 posted

    bootzilla

    Not sure what is confusing.

    The problem you are trying to solve is not clear given the code.

    bootzilla

    I posted the code in the Model, View and a class file that has mocked list. I'm using both MVC and Razor? Not sure what you mean. The View is a Razor page, the model is the model and so on. I'm also following the link you provided in the second post as far as building the dropdown/select list.

    The code you posted has all the earmarks of Razor Pages which is another ASP.NET Core framework.  It appears you are copying and pasting code snippets without taking the time to understand the code.

    ASP.NET MVC Example.

    Models

        public class ItemStatus
        {
            public int StatusId { get; set; }
            public string Name { get; set; }
            public int ColorId { get; set; }
        }
    
        public class StatusColor
        {
            public int ColorId { get; set; }
            public string Name { get; set; }
        }

    Controller.Action

        public class HomeController : Controller
        {
    
            private static List<ItemStatus> _mockStatuses = new List<ItemStatus>
            {
                new ItemStatus  { StatusId = 1, Name = "Complete", ColorId = 1},
                new ItemStatus  { StatusId = 2, Name = "Complete, Ongoing",ColorId = 2},
                new ItemStatus  { StatusId = 3, Name = "In Process", ColorId = 3}
            };
    
            private static List<StatusColor> _mockColors = new List<StatusColor>()
            {
                new StatusColor() { ColorId = 1, Name = "Auto" },
                new StatusColor() { ColorId = 2, Name = "Green" },
                new StatusColor() { ColorId = 3, Name = "Yellow" }
            };
    
            public IActionResult Index()
            {
                List<SelectListItem> options = (from o in _mockColors
                                                select new SelectListItem()
                                                {
                                                    Text = o.Name,
                                                    Value = o.ColorId.ToString()
                                                }).ToList();
                ViewBag.Options = options;
                return View(_mockStatuses);
            }

    View

    @model List<MvcApiCore20Identity.Models.ItemStatus>
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h2>Index</h2>
    
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                    <th>
    
                        @Html.DisplayNameFor(model => Model[0].StatusId)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => Model[0].ColorId)
                    </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @for (var i = 0; i < Model.Count(); i++)
            {
                <tr>
                    <td>
                        <input asp-for=@Model[i].StatusId />
                    </td>
                    <td>
                        <input asp-for="@Model[i].Name" />
                    </td>
                    <td>
                        <select asp-for="@Model[i].ColorId" asp-items="@ViewBag.Options as List<SelectListItem>"></select>
                    </td>
                    <td>
                        @Html.ActionLink("Edit", "Edit", new {  id=@Model[i].StatusId  }) |
                        @Html.ActionLink("Details", "Details", new { id=@Model[i].StatusId }) |
                        @Html.ActionLink("Delete", "Delete", new {  id=@Model[i].StatusId })
                    </td>
                </tr>
            }
        </tbody>
    </table>

    This isn't exactly what I'm looking for. This is what I have after a few moderations. I'm not sure what exactly goes in the SelectList that will populate the dropdown in the View.

    Controller:

     [HttpGet]
            public IActionResult ManageStatusesEdit(int id)
            {
               
    
                var editManageStatusesEditViewModel = new ManageStatusesEditViewModel
                {
                  
                    AvailableColors = new SelectList()
                };
               
                return View(editManageStatusesEditViewModel);
            }

    View:

     <select name="Color" asp-for="StatusToEdit.Color.Name"
                                    asp-items="Model.AvailableColors">
                                <option>Please select one</option>
                            </select>

    Model:

      public SelectList  AvailableColors { get; set; }

    Something has to be passed in the SelectList and I know it is Text and Value but I'm not exactly sure how to code that.

    Wednesday, July 31, 2019 7:47 PM
  • User-474980206 posted

    you never show where the list of data from from. simpling your mock code its:

            private static List<StatusColor> _mockColors = new List<StatusColor>()
            {
                new StatusColor() { ColorId = 1, Name = "Auto" },
                new StatusColor() { ColorId = 2, Name = "Green" },
                new StatusColor() { ColorId = 3, Name = "Yellow" }
            };
    
            public IActionResult Index()
            {
                ViewBag.Options = new SelectList(_mockColors, "ColorId", "Name"); 
                ...
            }

    Wednesday, July 31, 2019 8:10 PM
  • User475983607 posted

    bootzilla

    I'm not sure what exactly goes in the SelectList that will populate the dropdown in the View.

    I provided this example in the previous post.  I think the issue is you do quite understand an HTML select element.  The select element is made up of two parts.  A list of options that the user can select and a name/value pair.  In contrast a text input is only a name/value pair.

    You have to populate both parts; the option and the name/value.  The ASP.NET Core tag helpers make this very easy to do.  The name/value is defined by the asp-for and the options by asp-items.  

    Here is another example that expands the example above.   Click the edit link (View above).  To edit an item.

    Added Edit actions

            [HttpGet]
            public IActionResult Edit(int id)
            {
                //Populate the select options
                List<SelectListItem> options = (from o in _mockColors
                                                select new SelectListItem()
                                                {
                                                    Text = o.Name,
                                                    Value = o.ColorId.ToString()
                                                }).ToList();
                ViewBag.Options = options;
    
                //Populate the item to edit
                ItemStatus item = _mockStatuses.Where(x => x.StatusId == id).FirstOrDefault();
    
                return View(item);
            }
    
            [HttpPost]
            public IActionResult Edit(ItemStatus input)
            {
                //Populate the select options
                List<SelectListItem> options = (from o in _mockColors
                                                select new SelectListItem()
                                                {
                                                    Text = o.Name,
                                                    Value = o.ColorId.ToString()
                                                }).ToList();
                ViewBag.Options = options;
    
                //erturn the user inpu to the UI 
                //In a real app you would save the user's inputs
                return View(input);
            }

    Edit View

    @model MvcApiCore20Identity.Models.ItemStatus
    
    @{
        ViewData["Title"] = "Edit";
    }
    
    <h2>Edit</h2>
    
    <h4>ItemStatus</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Edit">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="StatusId" class="control-label"></label>
                    <input asp-for="StatusId" class="form-control" />
                    <span asp-validation-for="StatusId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Name" class="control-label"></label>
                    <input asp-for="Name" class="form-control" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="ColorId" class="control-label"></label>
                    <select asp-for="ColorId" asp-items="@ViewBag.Options as List<SelectListItem>" class="form-control"></select>
                    <span asp-validation-for="ColorId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Save" class="btn btn-default" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    Or if you want to use the SelectList rather than List<SelectListItem> as suggested above.

            [HttpGet]
            public IActionResult Edit(int id)
            {
                //Populate the select options
                ViewBag.Options = new SelectList(_mockColors, "ColorId", "Name");
    
                //Populate the item to edit
                ItemStatus item = _mockStatuses.Where(x => x.StatusId == id).FirstOrDefault();
    
                return View(item);
            }
    
            [HttpPost]
            public IActionResult Edit(ItemStatus input)
            {
                //Populate the select options
                ViewBag.Options = new SelectList(_mockColors, "ColorId", "Name");
    
                //return the user input to the UI so we can varify the inputs 
                //In a real app you would save the user's inputs
                return View(input);
            }
    @model MvcApiCore20Identity.Models.ItemStatus
    
    @{
        ViewData["Title"] = "Edit";
    }
    
    <h2>Edit</h2>
    
    <h4>ItemStatus</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Edit">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="StatusId" class="control-label"></label>
                    <input asp-for="StatusId" class="form-control" />
                    <span asp-validation-for="StatusId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Name" class="control-label"></label>
                    <input asp-for="Name" class="form-control" />
                    <span asp-validation-for="Name" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="ColorId" class="control-label"></label>
                    <select asp-for="ColorId" asp-items="@ViewBag.Options as SelectList" class="form-control"></select>
                    <span asp-validation-for="ColorId" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Save" class="btn btn-default" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    Keep in mind this concept is covered in every getting started tutorial.

    Wednesday, July 31, 2019 8:28 PM
  • User-1764593085 posted

    Hi bootzilla,

    Something has to be passed in the SelectList and I know it is Text and Value but I'm not exactly sure how to code that.

    You could use `List<SelectListItem>` instead of `SelectList`

    1.Model:

     public class ManageStatusesEditViewModel
        {
            public List<SelectListItem> AvailableColors { get; set; }
        }
    
        public class ItemStatus
        {
            public int StatusId { get; set; }
            public string Name { get; set; }
    
            public StatusColor Color { get; set; }
        }
    
        public class StatusColor
        {
            public int ColorId { get; set; }
            public string Name { get; set; }
        }

    2.Action:

    public IActionResult ManageStatusesEdit(int id)
            {
                var dropdownData = new List<SelectListItem>();
    
                _mockStatuses.ForEach(d => dropdownData.Add(new SelectListItem()
                {
                    Value = d.Color.Name,
                    Text = d.Color.Name
                }));
                
                var editManageStatusesEditViewModel = new ManageStatusesEditViewModel
                {
    
                    AvailableColors = dropdownData
                };
                return View(editManageStatusesEditViewModel);
            }

    3.View

    <select asp-for="StatusToEdit.Color.Name" asp-items="Model.AvailableColors">
        <option>Please select one</option>
    </select>

    4.Result

    Best Regards,

    Xing

    Thursday, August 1, 2019 6:21 AM