ASP.NET MVC cannot get dropdownlist to set selected value - asp.net-mvc-4

In my ASP.NET MVC application, I have a drop-down list in a form on a page, where the dropdown list item that should be selected when the page loads don't get selected.
The ViewModel for the page has a property for the list of SelectListItems that should be used to populate the drop-down list:
See below for the View model and illustration of the "Index" class, which has HeaderItemID as one of it's properties:
public class IndexItemResult
{
public Index FocalIndex { get; set; }
public string FocalIndexHeaderItemText { get; set; }
public List<Item> IndexItems { get; set; }
public List<SelectListItem> ItemSelectList { get; set; }
public List<Item> ItemList { get; set; }
public IndexItemResult() { }
}
public class Index
{
public int IndexID { get; set; }
public string IndexName { get; set; }
public int IndexHeaderItemID { get; set; }
}
I set the "text", "value", and "selected" properties of items in the SelectListItems from a database LINQ query in my controller. This method also sets the "FocalIndex" property of the ViewModel. As HeaderItemID is a property of FocalIndex, I therefore assumed that "HeaderItemID" is available as a field that can be bound to.
"HeaderItemID" is the item that should be selected. When I look at the list of SelectListItems that gets generated, everything looks ok - the "text" and "value" properties are all fine, and the correct item is specified as "selected".
private IndexItemResult GetIndexItemResult(int? indexID)
{
IndexItemResult indexItemResult = new IndexItemResult();
Index focalIndex = db.Indexes.Find(indexID);
indexItemResult.FocalIndex = focalIndex;
int HeaderItemID = focalIndex.IndexHeaderItemID;
indexItemResult.ItemSelectList = db.ItemTexts.
Where(it => it.LanguageID == 1).
Select(iText =>
new SelectListItem
{
Selected =
(
iText.ItemID == HeaderItemID ? true : false
),
Value = iText.ItemID.ToString(),
Text = String.Concat(iText.ID.ToString(), " ", iText.Text)
}).ToList();
return indexItemResult;
}
I then have a form on the page, where I specify the dropdown list with the #Html.DropDownList helper. I pass the list of SelectListItems from the ViewModel in the second parameter.
#Html.DropDownList("IndexHeaderItemID", Model.ItemSelectList,
htmlAttributes: new { #class = "form-control", #id = "HeaderItemDDL" })
The drop-down list renders with all the items as expected, but the item that should be set at "selected" is not selected. Instead, the first item is selected. Any suggestions for what I'm missing here?

I see no place where you're actually setting anything in ModelState named IndexHeaderItemID. Since that is the name you're binding to, then one of Request["IndexHeaderItemID"], ViewData["IndexHeaderItemID"], ViewBag.IndexHeaderItemID or Model.IndexHeaderItemID must be set to the value you expect to be selected.

Related

MVC Filter Drop Down List Based on user response

I'm brand new to MVC and i'm trying get my dropdown list to dynamically change based on the value a user selects from a list before. The change is just a filter of the list based on the value chosen. I feel like there should be a way to filter my list based on the drop down picked i just am not sure how to do that. It seems like I should be able to write a js function on the view that does something like this:
function
{
selectedItem()
if x == "ListItemValue"
var CatListItems = new List<SelectListItem>();
CatListItems.Add(new SelectListItem { Text = String.Empty, Value = String.Empty });
foreach (var ZCategory in ViewBag.ZCategory)
if CaTlistItems.CategoryForeignKeyID = 3
{
CatListItems.Add(new SelectListItem { Text = ZCategory, Value = ZCategory });
}
}
Here is my code so far:
Model
public class ArmyRace
{
[Key]
public int RaceID { get; set; }
public string Race { get; set; }
public virtual ItemCategory ItemCategory { get; set; }
}
public class ItemCategory
{
[Key]
public int CategoryID { get; set; }
public string ArmyCategory { get; set; }
}
Controller:
List<string> Category = new List<string>(2);
var ICategory = from i in db.ItemCategory
select i;
foreach (var x in ICategory)
{
Category.Add(x.ArmyCategory);
}
ViewBag.ZCategory = Category;
View
var CatListItems = new List<SelectListItem>();
CatListItems.Add(new SelectListItem { Text = String.Empty, Value = String.Empty });
foreach (var ZCategory in ViewBag.ZCategory)
{
CatListItems.Add(new SelectListItem { Text = ZCategory, Value = ZCategory });
}
What I ended up doing for this one is creating 4 seperate lists. One with everything in the dropdown and 3 with the filters i wanted. I then used the simple $jquery.hide() and show functions to show or hide the ones I wanted. Finally i had to change the ID using the $jquery.attr() function for the list that is not active so the POST method would add the correct item to the database.
I believe this is not the ideal way, if I could have somehow brought my lists over with some type of identifier so i could parse through them on the view that would have been ideal but i didn't see a way of doing this.

Dynamically binding Drop Down List in MVC 4

I trying to create a drop down list and bind it to the values fetched from database.
How can I do this. I have done following till now. I want the value of the items of the dropdown ie c.ID in following code to be bind with the Currency_ID of the CountryVM.
public CountryVM()
{
[DisplayName("Country ID")]
[Required]
public string ID { get; set; }
[Required]
[DisplayName("Description")]
public string Description { get; set; }
[DisplayName("Currency Id")]
public Nullable<int> Currency_ID { get; set; }
}
//Controller
DAL library = new DAL();
var items = library.GetAllCurrency(Library.Filter.CURRENCY_SYMBOL);
IEnumerable<SelectListItem> list = items.Select(c => new SelectListItem { Text = c.CURRENCY_SYMBOL, Value = c.ID.ToString() });
ViewBag.curr_symbol = list;
return View();
//In View I am trying to access my DropDown as follows :
#Html.DropDownListFor(model => model.Currency_ID,"curr_symbol" )// how to write this.
Do like this in view:
#
{
SelectList CurrencyList = (SelectList)ViewBag.curr_symbol;
}
#Html.DropDownListFor(model => model.Currency_ID,CurrencyList)
and in action:
IEnumerable<SelectListItem> list = items.Select(c => new SelectListItem { Text = c.CURRENCY_SYMBOL, Value = c.ID.ToString() }).ToList();
or:
var list = (from c in items
select new SelectListItem {Text = c.CURRENCY_SYMBOL,
Value = c.ID.ToString() }).ToList();
Update:
As you told in discussion that it is throwing exception on form post so what you need is to fill the List again and put it in ViewBag in post action as from ViewBag it is removed.

ASP.NET MVC Populating dropdownlist

I've been trying to populate a dropdownlist for a while now and would appreciate some help. I have my model and viewmodel and my trying to populate the Dropdownlist and send it to the view so a user can choose a cartype and click submit.
public class Cars
{
public int CarId { get; set; }
public string Name { get; set; }
}
public class CarViewModel
{
public int SelectedCarId { get; set; }
public IEnumerable<SelectListItem> CarTypes;
}
public ActionResult FillDropDown()
{
var model = new ViewModel();
model.CarTypes = (from s in context.CarTypes
select new SelectListItem()
{
Text = s.Name,
Value = SqlFunctions.StringConvert((double)s.Id).Trim(),
}).ToList<SelectListItem>();
return View(model);
}
So I would like some help how to render this in the view. I tried the following but I get a nullreference exception.
#Html.BeginForm("FillDropDownList","Home", FormMethod.Post,null)
{
#Html.DropDownListFor(x => x.SelectedCarId, Model.CarTypes);
<input type="submit" value="submit" />
}
Try to use CarViewModel instead of ViewModel.
public ActionResult FillDropDown()
{
var model = new CarViewModel(); //CarViewModel instead of ViewModel
model.CarTypes = (from s in context.CarTypes
select new SelectListItem()
{
Text = s.Name,
Value = SqlFunctions.StringConvert((double)s.Id).Trim(),
}).ToList<SelectListItem>();
return View(model);
}
EDIT:
Change your IEnumerable property in CarViewModel into SelectList
public class CarViewModel
{
public int SelectedCarId { get; set; }
public SelectList CarTypes;
}
Make sure the SelectListItem is not null, in the FillDropDown() method.

Can't get ASP.Net MVC Edit Action to worth with my ViewModel

I am trying to use the following ViewModel
public class ProjectViewModel
{
public Project Project { get; set; } //bulk of the information
public int SelectedGovernmentClientId { get; set; } //selected ID for the dropdown
public IEnumerable<SelectListItem> GovernmentClients { get; set; } //dropdown values
}
Here's my project class
public class Project
{
public int ID { get; set; }
public string Title { get; set; }
//omitting extra fields
public virtual GovernmentClient GovernmentClient { get; set; }
}
Here's the action that I have
[HttpPost]
public ActionResult Edit(ProjectViewModel projectViewModel)
{
if (ModelState.IsValid)
{
//i am getting the following from debugging
//projectViewModel.Project.GovernmentClient.Name is NULL
//projectViewModel.Project.GovernmentClient.ID is the correct ID from the dropdown
db.Entry(projectViewModel.Project).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(projectViewModel);
}
All the values are getting updated EXCEPT the government client. Why is this happening?
projectViewModel.Project.GovernmentClient =
db.GovernmentClients.Find(projectViewModel.SelectedGovernmentClientId);
You are retrieving the value from database and setting its state to modified. However, there is no modification at all.
After a whole day of playing around with this, I think I might've solved it
I added the following to my Project model
[ForeignKey("GovernmentClient")]
public int GovernmentClient_ID { get; set; }
To render the dropdown, I used this
#Html.DropDownListFor(model => model.Project.GovernmentClient_ID, Model.GovernmentClients)
To generate the GovernmentClients list, I used the following method
private IEnumerable<SelectListItem> GetGovernmentClientsList(int selectedItem = -1)
{
var defaultItem = Enumerable.Repeat(new SelectListItem
{
Value = "-1",
Text = " - Select a government client - ",
Selected = (selectedItem == -1)
}, count: 1);
var clients = db.GovernmentClients.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.ClientName,
Selected = (selectedItem == -1) ? false : (x.ID == selectedItem)
});
return defaultItem.Concat(clients);
}
Overall, I am happy with this, because I am not hardcoding any property names, which I know would come back and bite me.

Best pratice for completing MVC model properties which aren't bound?

I am trying to find the best way to use MVC for models which are only partially edited.
Below is an simple example.
Model
using System.ComponentModel.DataAnnotations;
public class SimpleModel
{
public int Id { get; set; }
public string Parent { get; set; }
[Required]
public string Name { get; set; }
}
View
using System.ComponentModel.DataAnnotations;
public class SimpleModel
{
public int Id { get; set; }
public string Parent { get; set; }
[Required]
public string Name { get; set; }
}
Controller
using System.Web.Mvc;
public class SimpleController : Controller
{
public ActionResult Edit(int id)
{ return View(Get(id)); }
[HttpPost]
public ActionResult Edit(int id, SimpleModel model)
{
if (model.Name.StartsWith("Child")) //Some test that is not done client-side.
{
Save(model);
//Get the saved data freshly.
//model = Get(id);
}
else
{
ModelState.AddModelError("", "Name should start with 'Child'");
}
//Is this the way to set the Parent property?
//var savedModel = Get(id);
//model.Parent = savedModel.Parent;
return View(model);
}
//Mock a database.
SimpleModel savedModel;
private void Save(SimpleModel model)
{ savedModel = new SimpleModel() { Id = model.Id, Name = model.Name }; }
private SimpleModel Get(int id)
{
if (savedModel == null)
{ return new SimpleModel() { Id = id, Parent = "Father", Name = "Child " + id.ToString() }; }
else
{ return new SimpleModel() { Id = savedModel.Id, Parent = "Father", Name = savedModel.Name }; }
}
}
The Name field is editable. The Parent field is only for reference and should not be updated. Therefore, it is rendered using DisplayFor.
Upon post, I receive a model with property Parent set to null. That's no problem as it will not be saved. However, when I simply return the received model to the view, the Parent field will no longer be displayed. When the model is valid, I can easily get it again from the database and thus get the Parent field's value back.
When the model is not valid, I would like to allow the user to correct input and attempt to save once more. There, I the received model's values that are input should be used, but the displayed values should be shown as well.
In reality, there are many more fields to be shown for reference, most often from different database entities than the one that is being edited.
I have seen suggestions to pass the fields as hidden fields in the view, but I feel very reluctant to read data from the client that should not be updated.
Is there a more elegant way to do this than copying these values into the model manually or passing them as hidden fields?
What about giving those un-editable properties to another model and let it take care of those properties?
View Model
public class PersonViewModel
{
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public PersonDetailsModel DetailsModel { get; set; }
}
Details Model
public class PersonDetailsModel
{
public string Mother { get; set; }
public string Father { get; set; }
public PersonDetailsModel() { }
public PersonDetailsModel(int personId)
{
// pull required model data from databases
var db = DBParentContext;
Mother = db.Parent.Where(m => m.ChildId == personId)
Father = db.Parent.Where(m => m.ChildId == personId)
}
}
Controller
public class PersonController : Controller
{
[HttpPost]
public ActionResult Edit(PersonViewModel viewModel)
{
viewModel.DetailsModel = new PersonDetailsModel(viewModel.Id)
if (ModelState.IsValid) {
// ~
}
return View(viewModel)
}
}
View
#model PersonViewModel
#Html.DisplayFor(m => m.DetailsModel.Mother)
#Html.DisplayFor(m => m.DetailsModel.Father)
#Html.TextBoxFor(m => m.FirstName)
#Html.TextBoxFor(m => m.LastName)
Since details like your Mother are un-editable then they're not really part of the "Edit" model, so I'd box like that away and try to let something else take care of them.
If you aren't going to update the Parent field, then it really doesn't matter if it's a hidden or not, since you won't update it on post.
I would use the hidden in this case, just make sure not to update that field.