Cannot change selected value for SelectList - MVC - c#

I'm trying to generate a DropDownList for each record in a table in a View. I have trouble setting the selected value for the dropdownlist.
In the controller each user's access level list in the model is populated by calling a method in the Repository. I can't seem to get this method quite right. I can change the selected value on item, and accessLevels has correct value selected. But in the view this is not the selected value. How can I set the selected value of a selectlist?
I've tried this:
Repository:
public IEnumerable<SelectListItem> GetSelectListAccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
IEnumerable<SelectListItem> accessLevelsFromDB = DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name
});
SelectListItem item = null;
foreach (SelectListItem a in accessLevelsFromDB)
{
if (a.Value == selectedAccessLevelID)
{
item = a;
a.Selected = true;
}
}
var accessLevels = new SelectList(accessLevelsFromDB, item.Value);
return accessLevels;
}
And also tried returning accessLevelsFromDB:
return accessLevelsFromDB;
View:
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels"})
Have I used, SelectList Constructor (IEnumerable, Object), correctly? Or what else am I missing? I have tried to google but still don't understand what I'm doing wrong. I Looked at this question SelectList Selected Value Issue - Stack Overflow but that doesn't seem to work.
Update:
this is the model:
public class EditCustomerViewModel
{
public Customer Customer { get; set; }
public int CustomerID { get; set; }
public List<User> Users { get; set; }
public List<UserToView> UsersToView { get; set; }
public IEnumerable<SelectListItem> AccessLevelListForSelectedUser { get; set; }
}
Update 2:
I've got it working now and have updated my model and repository.
Model:
public class EditCustomerViewModel
{
public Customer Customer { get; set; }
public int CustomerID { get; set; }
public List<UserToView> UsersToView { get; set; }
}
Repository:
public IEnumerable<SelectListItem> GetSelectListAccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
IEnumerable<SelectListItem> accessLevelsFromDB = DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name,
Selected = x.AccessLevelID.ToString() == selectedAccessLevelID
});
return accessLevelsFromDB;
}

This should give you the selected item for your dropdown:
public IEnumerable<SelectListItem> AccessLevelsWithSelectedItem(string selectedAccessLevelID)
{
return DB.AccessLevels
.Select(x => new SelectListItem
{
Value = x.AccessLevelID.ToString(),
Text = x.Name,
Selected = x.AccessLevelID.ToString() == selectedAccessLevelID
});
}

It would be helpful if we could see the model your view is using. Regardless, you're making this far too difficult.
First, DropDownList needs only IEnumerable<SelectListItem>. Razor will take care of creating a SelectList instance and binding the appropriate selected value. In fact, it does that anyways, which is why your own attempts at selecting an item will be fruitless until you find what's causing the wrong or no value to be bound.
In that regard, everything revolves around ModelState, which is composed of values from Request, ViewBag/ViewData, and finally Model. That "finally" part is important, because anything in the request or view data will always override anything set on your model.
In other words, if your action has a parameter like accessLevels or you're setting something in something like ViewBag.AccessLevels. Those values will be used as the "selected" value for the dropdown.
Again, seeing the view model would be helpful here, but generally speaking, you should be using the *For family of helpers in conjunction with a view model. Ideally, you should have a property on your model like AccessLevels, and then do something like:
#Html.DropDownListFor(m => m.AccessLevels, Model.AccessLevelOptions)
Where AccessLevelOptions would be IEnumerable<SelectListItem> and contain the available access levels. With that, you'll never have any issues with the selected value, because Razor will handle everything and you're strongly bound to a particular property on your model. It's only when you start playing with string names, with no real ties to anything that things start to go awry.

You can just pass in a value attribute of a hardcoded string or the model value for that property:
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels", Value = "something" })
or
#Html.DropDownList("Accesslevels", user.AccessLevelsWithSelectedItem, new { #class = "form-control", #name = "accessLevels", Value = Model.MyProperty })

Related

MVC5 Razor Value cannot be null or empty. Parameter name: name

Source error: Line 22: #Html.TextBoxFor(model =>
model.DailyCurrencyRates___BuyingCurrency, new { #id = "test", #class
= "form-control" })
I am stuck on this issue for days and cannot get round this error. I simply want to render a partial view with the items for parent class. below is my code: Please ask for more info if needed.
Controller
public ActionResult AddRecord(int index)
{
return PartialView("_AddItem", new ForexItem { Index = index});
}
Parent View
#foreach (ForexItem item in Model.ForexItems)
{
Html.RenderPartial("_AddItem", item);
}
Partial View
#model F.Models.Entities.ForexItem
#Html.TextBoxFor(model => model.DailyCurrencyRates___BuyingCurrency, new { #id = "test", #class = "form-control" })
Model
public partial class ForexItem
{
public int ID { get; set; }
[NotMapped]
[StringLength(1000)]
[Display(Name = "Buying")]
public string DailyCurrencyRates___BuyingCurrency { get; set; }
[NotMapped]
public int Index { get; set; }
}
I obtained that same vague, obscure error when I increased the number of underscores in a model property name from 1 to 2. Note that the error did not occur for the LabelFor Helper directly before the TextBoxFor helper, but just in the TextBoxFor helper, same as you got. (I notice your property name ("DailyCurrencyRates___BuyingCurrency") has 3 underscores.) It then went away when I removed the extra underscore from the property name. It was as though with the extra underscore, Razor could not find the property name, so it just searched for (generic) "name" instead, which it also could not find.
It may be a typo, but it seems to me that you should change Model.ForexItems to Model.ForexItem - no s. Based on your submitted code.
… or maybe just use Model since you already put ForexItem in as that?
Parent View
#foreach (ForexItem item in Model)
{
Html.RenderPartial("_AddItem", item);
}

I Can't get a DropDownList to populate from table. EF and MVC4

I believe this will create a list in my HomeController. But not sure what calls it or where it goes in the Controller beside maybe the first Add ActionResult (GET method).
public static IEnumerable<SelectListItem> items()
{
using (oesacEntities_compact db = new oesacEntities_compact())
{
var query = from s in db.tblSponsors select new { s.SponsorID, s.BizName };
return query.AsEnumerable()
.Select(x => new SelectListItem
{
Value=x.SponsorID.ToString(),
Text = x.BizName
}).ToList();
}
}
I can't seem to send it to the Add view or to reference it from the Add view:
<div class="editor=field">
#Html.DropDownListFor(model => model.SponsorID,IEnumerable<SelectListItem> SelectList);
</div>
It seems so simple in other coding languages. I want to populate a pulldown with about 200 sponsor ID's for value, BizNames for text. For now at least. God help me after that when I want to show an Edit view with the value selected.
thankyou stackoverflow
You need to pass the SelectList to your view. Ideally your view model should include a property for the SelectList but you can (yuk) use ViewBag, for example
View Model
public class MyViewModel
{
public int SponsorID { get; set; }
// other properties
public SelectList SponsorList { get; set; }
}
Controller
public ActionResult SomeThing()
{
MyViewModel model = new MyViewModel();
// assign the select list
var sponsors = from s in db.tblSponsors;
model.SponsorList = new SelecList(sponsors, "SponsorID", "BizName");
return View(model);
}
View
#Html.DropDownListFor(model => model.SponsorID, Model.SponsorList);
or if you assigned the select list to ViewBag
#Html.DropDownListFor(model => model.SponsorID, (SelectList)ViewBag.SponsorList);

Create DropDownList for an ASP.NET MVC5 Relation [duplicate]

This question already has answers here:
Populating a razor dropdownlist from a List<object> in MVC
(9 answers)
Closed 8 years ago.
I'm stuck creating a proper create/edit view in ASP.NET MVC5. I've got two models Dog and Human. A dog belongs to one Human. I'm trying to create a dropdown in the create and edit views for Dog that'll allow me to select a Human by name for that particular Dog. Here are my models:
Human:
public class Human
{
public int ID { get; set; }
public string Name { get; set; }
}
Dog:
public class Dog
{
public int ID { get; set; }
public string Name { get; set; }
public Human Human { get; set; }
}
My create action:
// GET: /Dog/Create
public ActionResult Create()
{
ViewBag.HumanSelection = db.Humen.Select(h => new SelectListItem
{
Value = h.ID.ToString(),
Text = h.Name
});
return View();
}
And here is the relevant part of my view:
<div class="form-group">
#Html.LabelFor(model => model.Human.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Human, ViewBag.HumanSelection);
</div>
</div>
I get the following error when I run this:
Compiler Error Message: CS1973: 'System.Web.Mvc.HtmlHelper<Test.Models.Dog>' has no applicable method named 'DropDownListFor' but appears to have an extension method by that name. Extension methods cannot be dynamically dispatched. Consider casting the dynamic arguments or calling the extension method without the extension method syntax.
I'm new to C# & the Entity framework. What am I doing wrong? Is there a way of doing this without manually querying the database? Something like the collection form helpers in Rails?
I've followed a bunch of tutorials that are either old or too complicated for me to follow.
Important to note is that if you use DropDownListFor(x => x.Human), the returned value of the dropdownlist should be a Human object.
It isn't. In your own code snippet, you set the value of the SelectListItem to the ID of the Human. Therefore, when you submit your form, you will receive the ID that you selected.
Add the following to your model:
public int HumanId { get; set; }
Bind your dropdownlist to that int:
#Html.DropDownListFor(model => model.HumanId, (SelectList)ViewBag.HumanSelection);
Now, when you get back to the controller, use that ID to look up the actual Human you want:
[HttpPost]
public ActionResult Create (CreateModel model)
{
if(model.HumanId > 0)
{
model.Human = GetHumanByID(model.HumanId);
//or however you want to get the Human entoty from your database
}
}
It's a simplified solution, but I suspect your main confusion stems from the fact that you're expecting to receive a Human from the DropDownList, while it will actually only return an int (the ID).
Edit
I don't have much information on your data model, but if you're using entity framework, odds are that your Dog class will have a foreign key property called HumanId. If that is the case, you don't even need to get the Human entity like I showed you before. If you put the selected ID in the HumanId property, Entity Framework should be able to use that to create the relation between Human/Dog you want.
If this is the case, it would seems best to elaborate on this in your question, as this would otherwise be more guesswork than actual confirmation.
Edit 2 going offtopic here
Your code:
db.Humen
The plural form of man is men, woman is women; but for human, it's humans :) Humen does sounds like an awesome suggestion though ;)
The problem is that you are attempting to bind a Human type to a dropdown in the UI, a dropdown whose values are strings (the IDs of Human instances) and text are also strings (the names of Human instances).
What you should be binding to the dropdown instead is the ID of the Human, to match the fact that the ID is being used as the value. So with a view model such as
public class CreateDogModel
{
public string Name { get; set; }
[Range(0, int.MaxValue)]
public int Human { get; set; }
public IEnumerable<Human> Humans { get; set; }
}
And the GET controller action
[HttpGet]
public ActionResult Create()
{
var model = new CreateDogModel
{
Humans = db.Human.ToList()
};
return View(model);
}
The view then becomes
#Html.DropDownListFor(
model => model.Human,
Model.Humans.Select(h => new SelectListItem
{
Text = h.Name,
Value = h.ID.ToString()
}),
"Please select a Human");
In your POST controller action, you now look up the chosen human by the Human property value from the View model
[HttpPost]
public ActionResult Create(CreateDogModel model)
{
if (!ModelState.IsValid)
{
// fetch the humans again to populate the dropdown
model.Humans = db.Human.ToList();
return View(model);
}
// create and persist a new dog
return RedirectToAction("Index");
}

.Net MVC 4 Dropdownlistfor SelectedItem (Not just selected value, but the selected text)

I have a for loop to generate IEnumerable list:
public static IEnumerable<SelectListItem> loadData()
{
DataTable dt = load_from_database;
List<SelectListItem> list = new List<SelectListItem>();
foreach (DataRow dr in dt.Rows)
{
SelectListItem listItem = new SelectListItem();
listItem.Text = dr["name"].ToString();
listItem.Value = dr["id"].ToString();
list.Add(listItem);
}
return list;
}
And I have the following model:
public class Models
{
public string selectedUserApp { get; set; }
public IEnumerable<SelectListItem> userApps { get; set; }
}
And the controller:
public ActionResult Index()
{
var model = new UserApplicationModels();
userAppsList = loadData();
model.userApps = userAppsList;
model.selectedUserApp = model.userApps.First().Value;
return View(model);
}
Then the view:
#model Models
#Html.DropDownListFor(x=>x.selectedUserApp , Model.userApps)
What I got is the value of the selected item, but I need to get the text of selected item.
What can I do?
The right way is to requery databse after submit and search for the item text by item value.
You can cache load_from_database result values (in Session or HttpCache) and search item text from there.
Another approach is to append your model with another string field (like:
public string selectedUserAppText { get; set; }
pass it to your View:
#Html.HiddenFor(m => m.selectedUserAppText)
Set its value with jQuery code like:
$("#your_dropdown_id").change(function(e) {
var selectedText = $("#your_dropdown_id").children("option:selected").text();
$('#your_hidden_for_id').val(selectedText);
});
after submitting this form your selectedUserAppText field will get selected item text.
Please check this in action at:
http://jsfiddle.net/m4zuH/1/
MVC must use the standard HTTP posting mechanism, and this mechanism does not contain the text of a dropdownlist. It only contains the value. Thus, you must.. on the server, lookup that value based on the id.
How you do that, depends on your app. One option would be to call loadData() again, and then do a simple linq query to return the text.
var data = loadData();
var text = data.Where(x => x.Value == value).Single().Text;
If you want to have a custom selected value, then you need a little bit more of code in your dropdownlistfor
#Html.DropDownListFor(m => m.selectedUserApp , new SelectList(Model.userApps, "Name", "Name"))
The SelectList is what you need because you can set which properties of your object will be the value or will be the text:
public SelectList(IEnumerable items, string dataValueField, string dataTextField);

Getting SelectedValue back from a DropDown in ASP.NET MVC (C#) using Entity Framework

Sorry if this is a repeated question, I scanned the related questions and didn't see anything obvious.
I'm using an EditModel with an Entity object, along with two SelectLists in it. The problem is, once I reach my POST action, the SelectedValues for both drop downs are still the same default values I set in the constructor for the model, no matter what I actually select on the browser.
My constructor sets some default values for the SelectedValues, but they are just 0 and "" (which aren't valid values in the dropdowns). I have a feeling the problem revolves around that somehow, but I'll give more details.
Here is a stripped down version of the model:
public class UserAccountModel
{
public UserAccount UserAccountData { get; set; } // Entity from EF
public SelectList Organizations { get; set; }
public SelectList Roles { get; set; }
public UserAccountModel() : this(null)
{
}
public UserAccountModel(UserAccount obj)
{
UserAccountData = (obj == null) ? new UserAccount() : obj;
// default selected value
int orgChildId = (UserAccountData.Organization == null) ? 0 : UserAccountData.Organization.ID;
string roleChildId = (UserAccountData.Role == null) ? "" : UserAccountData.Role.Name;
// go get the drop down options and set up the property binding
using (UserAccountRepository rep = new UserAccountRepository())
{
Organizations = new SelectList(rep.GetOrganizationOptions(), "ID", "ID", orgChildId);
Roles = new SelectList(rep.GetRoleOptions(), "ID", "Name", roleChildId);
}
}
public void UpdateModel()
{
UserAccountData.Organization = Organizations.SelectedValue as Organization;
UserAccountData.Role = Roles.SelectedValue as Role;
}
}
This is the Dropdowns portion of the view:
<div class="field">
<label for="ID">Organization:</label>
<%= Html.DropDownList("ID", Model.Organizations) %>
</div>
<div class="field">
<label for="Name">Role:</label>
<%= Html.DropDownList("Name", Model.Roles) %>
</div>
I might have done something stupid and obvious here. The examples are much more straight forward when using the ViewData dictionary, but I couldn't find too many examples trying to use straight model binding for SelectLists.
Any help is greatly appreciated!
Chris
Select elements only post back the actual value of the selected it. In this case, the parameters will be received back at the server/controller as ID (organization) and Name (role). The model you use for the update action should either contain these as properties or your controller action should accept them directly as parameters. The lists on the model won't be repopulated -- and the names don't match in any event.
Modify your model by adding:
public int ID { get; set; }
public string Name { get; set; }
with controller action as:
public ActionResult Update( UserAccountModel userAccount )
{
...
}
Note that if there is a validation error, you'll need to repopulate the SelectList properties (reconstituting the menus).
You simply forgot the navigational path to the ID property :)
<%= Html.DropDownList("Organization.ID", Model.Organizations) %>

Categories