Result of LINQ Query in MVC SelectList as Value and Text - not working
Asked Answered
W

6

7

I am trying to use the result of a LINQ Query to populate a SelectList in a MVC 5 application. The LINQ query returns customer IDs.

Model

public partial class Pricelist
{
    public int CustomerID { get; set; }
    public int SelectedCustomer { get; set; }

    public Pricelist(int customerID, int selectedCustomer)
    {

    }
}

View

@Html.DropDownList("custList")

Controller (1)

var query = ((from s in db.Pricelists
                     select s.CustId).Distinct()).ToList();

int i = 1;
List<Pricelist> CustomerList = new List<Pricelist>();
foreach (var c in query)
{
    int cust = c;
    Pricelist p = new Pricelist(i, cust);
    CustomerList.Add(p);
    i++;
}

SelectList custList = new SelectList(CustomerList); 
ViewBag.custList = custList;

return View(); 

Which returns a drop down populated with the Model class name (I get an exception if I try to return i and cust .ToString() in the foreach.) I tried this because the Controller method below produced the list of distinct CustomerIDs, but returned NULL when it was POSTed (I think because there was no Value specified in the SelectList)

public ActionResult Create()
{
    var query = (from s in db.Pricelists
                 select s.CustId).Distinct(); 

    SelectList CustomerList = new SelectList(query);

    ViewBag.custList = CustomerList;

    return View();
}

Pointers to where I am going wrong, and how to proceed much appreciated.

Worden answered 21/2, 2014 at 15:56 Comment(0)
L
7

I thinks is not so nice to use ViewBag to populate dropdowns in mvc. You shoud change you model to have a list of SelectedListItem and populate it from list of PriceList so it should look like this :

public class Model
{
     public int CustomerID { get; set; }
     public int SelectedCustomer { get; set; }
     public IList<Pricelist> PriceList{get;set;}
     public IList<SelectListItem> PriceListSelectListItem{get;set;}
        {
            get
            {
                   var list = (from item in PriceList
                            select new SelectListItem()
                            {
                                Text = item.customerID.ToString(CultureInfo.InvariantCulture),
                                Value = item.selectedCustomer.ToString(CultureInfo.InvariantCulture)
                            }).ToList();
                return list;
            }
            set{}
        } 

}

and now in view you will be able to do something like this :

 @Html.DropDownListFor(c=>c.CustomerID,Model.PriceList)

Try to use dropdown like this, this will look more profesional than using ViewBag in views.

Controller:

var query = ((from s in db.Pricelists
                     select s.CustId).Distinct()).ToList();

int i = 1;
List<Pricelist> CustomerList = new List<Pricelist>();
foreach (var c in query)
{
    int cust = c;
    Pricelist p = new Pricelist(i, cust);
    CustomerList.Add(p);
    i++;
}

    model.PriceList=result of your query

return View("ViewName",model); 
Laundress answered 21/2, 2014 at 17:2 Comment(1)
Thank you very much for your answer. Do I understand ok: Model must have IList<SelectListItem> to reference in View, and this is what allows POST to work. The <Pricelist> CustomerList I create in the Controller will not work as a model in the Return View("Create", CustomerList) - the error message states that "requires a model item of type 'OnLimeIntegration.Models.Pricelist'". I don't understand what the object in the view needs to be.Worden
C
8

The easiest method is to let Razor worry about the SelectList and just feed it an IEnumerable<SelectListItem>.

ViewBag.custList = CustomerList.Select(m => new SelectListItem { Value = m.Id, Text = m.Name });

Then in your view:

@Html.DropDownListFor(m => m.SomeField, (IEnumerable<SelectListItem>)ViewBag.custList)

You can make that nicer by using a view model that you can strongly type instead of ViewBag. You should really avoid ViewBag as much as possible.

Cruller answered 21/2, 2014 at 16:51 Comment(1)
This worked great for me, but, as a heads up, if Id is an int or long you will need to convert it to a string before passing into the Value property as it only accepts strings.Timon
L
7

I thinks is not so nice to use ViewBag to populate dropdowns in mvc. You shoud change you model to have a list of SelectedListItem and populate it from list of PriceList so it should look like this :

public class Model
{
     public int CustomerID { get; set; }
     public int SelectedCustomer { get; set; }
     public IList<Pricelist> PriceList{get;set;}
     public IList<SelectListItem> PriceListSelectListItem{get;set;}
        {
            get
            {
                   var list = (from item in PriceList
                            select new SelectListItem()
                            {
                                Text = item.customerID.ToString(CultureInfo.InvariantCulture),
                                Value = item.selectedCustomer.ToString(CultureInfo.InvariantCulture)
                            }).ToList();
                return list;
            }
            set{}
        } 

}

and now in view you will be able to do something like this :

 @Html.DropDownListFor(c=>c.CustomerID,Model.PriceList)

Try to use dropdown like this, this will look more profesional than using ViewBag in views.

Controller:

var query = ((from s in db.Pricelists
                     select s.CustId).Distinct()).ToList();

int i = 1;
List<Pricelist> CustomerList = new List<Pricelist>();
foreach (var c in query)
{
    int cust = c;
    Pricelist p = new Pricelist(i, cust);
    CustomerList.Add(p);
    i++;
}

    model.PriceList=result of your query

return View("ViewName",model); 
Laundress answered 21/2, 2014 at 17:2 Comment(1)
Thank you very much for your answer. Do I understand ok: Model must have IList<SelectListItem> to reference in View, and this is what allows POST to work. The <Pricelist> CustomerList I create in the Controller will not work as a model in the Return View("Create", CustomerList) - the error message states that "requires a model item of type 'OnLimeIntegration.Models.Pricelist'". I don't understand what the object in the view needs to be.Worden
L
1

You can change your dropdownlist in your view

@Html.DropDownList("custList", new SelectList(ViewBag.custList, "Id" , "Name"))

And your ViewBag in Controller (1) as

ViewBag.custList = CustomerList;
Lilylilyan answered 21/2, 2014 at 16:7 Comment(2)
You should mention that ViewBag.custList at that point should be the actual list and not an instance of SelectList as the OP currently has. Otherwise, this code here will fail. You'll also need to cast it to a List<PriceList>, or again, it will fail.Cruller
Yes you are right with the Viewbag.custList. But casting it to a List? I'm not sure about that. I think you can directly pass the ViewBag in the new SelectList parameter. If that's what you mean.Lilylilyan
C
0

On your CustomerList object, set DataTextField and DataValueField properties.

Something like this:

SelectList CustomerList = new SelectList(query);
CustomerList.DataTextField = "Name"; // Name property of customer object
CustomerList.DataValueField = "Id"; // id property of customer object

ViewBag.custList = CustomerList;
Civilize answered 21/2, 2014 at 16:3 Comment(2)
This isn't wrong, but why would you do this in three lines when you can just pass two extra params to the SelectList constructor instead?Cruller
Sure you can do that as well. Just thought this way will be more demonstrative with SelectList class. I usually myself use a list of SelectListItem just like in your response.Civilize
S
0

I think this could help:

@Html.DropDownList("custList", (SelectList) ViewBag.custList)
Spradling answered 21/2, 2014 at 16:5 Comment(1)
Thanks for the answer. The CustID is still showing as 0 in the POST though.Worden
W
0

Thanks for all your answers, I understand more about how SelectList works now, but don't have the level of skill to make all these answers work. This worked in the end:

Controller:

 public ActionResult Create()
    {
        var query = (from s in db.Pricelists
                     select s.CustId).Distinct();

        SelectList custList = new SelectList(query);


        ViewBag.custList = custList;

        return View();
    }

View:

    @Html.DropDownListFor(model => model.CustId  , (SelectList)ViewBag.custList, "--Select--")
Worden answered 24/2, 2014 at 14:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.