1

I can't seem to find any examples anywhere that fit my situation (using MVC4 just directly getting data from the DB using Stored Procedures without using Entity Framework) to set the SELECTED value of the DropDownListFor to the currently selected value of what is listed for that specific item in the DB).

More specifically, here are extracts from my code (hopefully sufficient to isolate what this ignorant newbie is doing wrong) - that will hopefully help anyone else struggling to set the default listed value in DropDownListFor to what is already stored in the DB for what is being edited.

CONTROLLER

[HttpGet]
    [Authorize] 
    public ActionResult Edit(string id, string ProdName, UpdateProductModel updateproductmodel)
    {
        int ProductID = Convert.ToInt32(id);
        ViewBag.ProdName = ProdName;
        SqlConnection cn = new SqlConnection(@"Data Source=D;User ID=user;Password=pswrd;Initial Catalog=cat");
        SqlCommand cmd = new SqlCommand("sp_GetProduct", cn);
        cn.Open();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@ProductID", ProductID));

        SqlDataReader dr = cmd.ExecuteReader();
        if (dr == null)
        {
            return HttpNotFound();
        }
        if (dr.Read())
        {
            DataSet dst = updateproductmodel.GetProducts_ByTypes();
            ViewBag.UpProdTypes = dst.Tables[0];

            List<SelectListItem> items = new List<SelectListItem>();

            foreach (System.Data.DataRow dru in ViewBag.UpProdTypes.Rows)
            {
                items.Add(new SelectListItem { Selected = (Convert.ToInt32(@dru["ProdTypeID"].ToString()) == Convert.ToInt32(dr["ProdTypeID"].ToString())), Text = @dru["ProdTypeDescr"].ToString(), Value = @dru["ProdTypeID"].ToString() });

            }

            ViewBag.UpProdTypes = items;

             if (Request.Cookies["OIDCookie"].Value == dr["OrganisationID"].ToString())
        {

            updateproductmodel.ProductID = Convert.ToInt32(dr["ProductID"].ToString());
            updateproductmodel.ProdTypeID = Convert.ToInt32(dr["ProdTypeID"].ToString());
            updateproductmodel.ProdTypeDescr = dr["ProdTypeDescr"].ToString();
            updateproductmodel.ProductName = dr["ProductName"].ToString();
            updateproductmodel.ProductDescription = dr["ProductDescription"].ToString();
            updateproductmodel.ProductComments = dr["ProductComments"].ToString();
            updateproductmodel.ProductProfileLocation = dr["ProductProfileLocation"].ToString();
            updateproductmodel.ProductProfileName = dr["ProductProfileName"].ToString();
            updateproductmodel.ProductMIMEType = dr["ProductMIMEType"].ToString();
            updateproductmodel.ProductSerialNumber = dr["ProductSerialNumber"].ToString();
            updateproductmodel.UpdateBy = Convert.ToInt32(Request.Cookies["UIDCookie"].Value);
        }
             else
             {
                 return RedirectToAction("Index", "Home");
             }
        }
        else
        {
            //dr.Close();
        }
        //dr.Close();
        //cn.Close();
        return View(updateproductmodel);
    }

When I step through this there is a stage where the Convert.ToInt32(dr["ProdTypeID"].ToString()) -

(which is the value of the existing ProductTypeID captured previously in the DB for a particular Product)

is 3 (Pumps) and the value of Convert.ToInt32(@dru["ProdTypeID"].ToString() -

(which is the value of the type of product in a table listing the various product types that is iterated through to generate the list in DropDownListFor)

is also 3 (Pumps).

I assumed that would cause the related Product Type Description for the ID of 3 (i.e. "Pumps") to be set as the selected default value that would be displayed in the DropDownListFor in the EDIT view - but instead just the first type in the list is displayed, without the SELECTED taking effect - and when updated the value stored in the DB then naturally gets set to the value of the first type in the list (which happens to be DISPENSERS - and not the desired PUMPS - which could obviously then be changed to DISPENSERS if there was a data capture error initially - but obviously it should remain what it was if not wrong).

VIEW (well what I assume is all that is needed of it)

<div class="editor-label">      
        @Html.LabelFor(model => model.ProdTypeID)             
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ProdTypeDescr) <br />

        @Html.DropDownListFor(model => model.SelectedProdTypeID, (IEnumerable<SelectListItem>)ViewBag.UpProdTypes, new { @class="form-control"})

        @Html.ValidationMessageFor(model => model.ProdTypeID)
    </div>  

I've just displayed the value of the Product Type in the view before the DropDownListFor for simple comparison to check it the value displayed in each differs or not - it will obviously be removed in once I get the correct default listed in the DropDownListFor.

I've commented out the various Closes at the bottom of the Controller Action because of getting an error that an open connection was required - WHERE and WHEN is it safe to close the connections? (I obviously don't want to accumulate open connections that are never closed).

I will really appreciate any suggestions that get the default selection in the DropDownListFor set to the existing value for a particular product that was captured in the DB, when editing that particular product.

Thank you for sharing your expertise with a clueless newbie.

Alan

user1554359
  • 23
  • 1
  • 6

2 Answers2

1

Use SelectList most probably you need to use this contructor of it following way:

foreach (System.Data.DataRow dru in ViewBag.UpProdTypes.Rows)
{
  items.Add(new SelectListItem {  
                                Text = @dru["ProdTypeDescr"].ToString(),
                                Value = @dru["ProdTypeID"].ToString() 
                               });
}

ViewBag.UpProdTypes = new SelectList(items,"Value","Text", "3");

Now in dropdownlist you will have item selected in View which has value 3 means ProdTypeID 3.

and in View:

 @Html.DropDownListFor(model => model.SelectedProdTypeID,
                                ViewBag.UpProdTypes as SelectList, 
                                new { @class="form-control"})
Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
  • Thanks Ehsan - I'll have to try that tomorrow - unfortunately, I have to leave right now (actually already a bit late) - but 3 was just an example - I don't ALWAYS want to set the selected value to 3 - but I'll try substituting the value for the particular product from the DB in place of 3 - which should hopefully get it to work tomorrow. I really apprciate your prompt reply, Ehsan! – user1554359 Jan 28 '15 at 14:47
  • @user1554359 3 is example as you said in question, can pass dynamic value from a variable – Ehsan Sajjad Jan 28 '15 at 14:55
  • Thanks Ehsan, yes, as I said, I'll obviously try that once I can get it to work with the hard coded 3. However, the list in ViewBag.UpProdTypes = new SelectList(list,"Value","Text", 3); is rejected - ("Using the generic type 'System.Collections.Generic.List' requires 1 type arguments." ) - I tried replacing it with items - which is accepted - However, the first item in the list is still selected, instead of 3's value. – user1554359 Jan 29 '15 at 09:32
  • ``ViewBag.UpProdTypes = new SelectList(items,"Value","Text", 3);`` – Ehsan Sajjad Jan 29 '15 at 09:43
  • @user1554359 do like this ``ViewBag.UpProdTypes = new SelectList(items,"Value","Text", 3);`` it was typo mistake by me – Ehsan Sajjad Jan 29 '15 at 09:49
  • Hi Ehsan Thanks for following up, but as I already said, "I tried replacing it with items - which is accepted - However, the first item in the list is still selected, instead of 3's value." – user1554359 Jan 30 '15 at 07:28
  • can you reprooduce in a dotnetfiddle? – Ehsan Sajjad Jan 30 '15 at 07:44
  • @user1554359 and also put 3 in double quotes as string as we are converting value to string so may be it is culprit – Ehsan Sajjad Jan 30 '15 at 07:45
  • Thanks Ehsan. Got it working by just following Stephen's advice above - i.e. "in the controller set the value of SelectedProdTypeID to something that matches one of the options." so, if I simply assign it the value of the ProdTypeID in the DB for a specific Product using Convert.ToInt32(dr["ProdTypeID"].ToString()), it works fine as it was (without the Selected bit, of course) - (but just not using best practices - seems I should rather have used ViewModels than viewBag). I appreciate your help Ehsan, but now it is solved (well using ViewBag that is). – user1554359 Jan 31 '15 at 17:27
  • so 3 was not coming from db when you were populating first @user1554359 – Ehsan Sajjad Jan 31 '15 at 17:42
  • No - 3 was always coming from the DB - but I simply needed to assign what came from the DB - (i.e. Convert.ToInt32(dr["ProdTypeID"].ToString())) to SelectedProdTypeID apart in the Controller and then it worked (without needing to specifically make it part of the ViewBag). But at least that is sorted out now - so, thank you for your help, Ehsan, but the method suggested by Stephen has already provided a working solution and I'm not going to spend more time trying to get your suggestion to also work. But I really appreciate your helpfulness and particularly your persistent follow ups. Thanks. – user1554359 Feb 01 '15 at 20:31
0
    public ActionResult Create()
    {
        ViewBag.int_usertype_id = new SelectList(db.tbl_usertype.Where(x => x.int_usertype_id != 4).ToList(), "int_usertype_id", "Str_usertype");
        return View();
    }
hitesh
  • 1