MVC3 DropDownListFor not populating selectedValue - asp.net-mvc-3

I feel like I'm taking crazy pills. I have a dropdownlist for a view that reads from our database all of the wine producers we have. I want to set the selectedValue to a particular ID driven by the referring page. I can see it picks up the selectedValue in debug, I see the selected value populated (906 for this example), but it doesn't set the dropdownlist to the correct value when the page is rendered, it always defaults to 1 for the default value. I've tried creating the selectList in razor as opposed to my controller, but nothing works. Any help on this would be appreciated, I'm guessing it is something small.
Controller:
if (User.IsInRole("admin"))
{
if (ID != 0)
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name", ID);
}
else
{
ViewBag.ProducerSelect = new SelectList(db.Producers.OrderBy(p => p.Name), "ProducerID", "Name");
}
}
View:
if (User.IsInRole("producereditor"))
{
<h3>#ViewBag.ProducerName</h3>
}
else
{
<div class="editor-label">
#Html.LabelFor(m => m.Wine.ProducerID, "Producer")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.Wine.ProducerID, ViewBag.ProducerSelect as SelectList)
</div>
}
Tried the below but no success:
ViewBag.ProducerSelect = new SelectList(from p in db.Producers
orderby p.Name
select new { p.ProducerID, p.Name }
, "ProducerID", "Name", ID);

If you want to preselect an item, You set that value to your ProducerId property.
var yourViewModelObj=new YourViewModel;
yourViewModelObj.Wine.ProducerId=906; //or whatever value you want
return View(yourViewModelObj);
Suggestion : For better code readablity/Maintenance, Try to avoid ViewBag / ViewData and use a ViewModel to pass the data.
I would add a Property to my ViewModel to hold the Collection of Producers
public class WineViewModel
{
//Other Existing properties also
public IEnumerable<SelectListItem> Producers{ get; set; }
public string SelectedProducer { get; set; }
}
Then in yout GetAction method, you can set the value like this, If you want to set one select option as the default selected one.
public ActionResult CreateWine()
{
var vm=new WineViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.Producers= new[]
{
new SelectListItem { Value = "1", Text = "Prodcer A" },
new SelectListItem { Value = "2", Text = "Prodcer B" },
new SelectListItem { Value = "3", Text = "Prodcer C" }
};
//Now let's set the default one's value
vm.SelectedProducer = "2";
return View(vm);
}
And in your Strongly typed View,
#Html.DropDownListFor(x => x.SelectedProducer,
new SelectList(Model.Producers, "Value", "Text"), "Select Producer")
The HTML Markup generated by above code will have the HTML select with the option with value 2 as selected one.

I figured this out. I had ViewModel.wine.ProducerID elsewhere on the page in a hidden field, and that defaults to 1, so I just assigned that to passed in value, and it worked great. I knew it was something like that. Thanks!

User a ViewModel ex WineViewModel
public class WineViewModel
{
public Wine Wine { get; set; }
public SelectList PProducerList { get; set; }
public WineViewModel() { }
public WineViewModel(Wine wine)
{
this.Wine = wine;
}
}
Try the following in your controller
var model = new WineViewModel( selectwine);
model.ProjectTypeList = new SelectList( from p in db.Producers
orderby p.Name
select new { p.ID, p.Name }, "ID", "Name")
notice how I am exclusively declaring which is the ID and which is the Value in my SelectList
Then in your view do
#Html.DropDownListFor(model => model.Wine.ProducerID, Model.ProjectTypeList)

Related

MVC 3 dropdownfor populated but cannot get user's selection

I'm new to MVC 3. I want 3 dropdown lists. The user picks an item from each list and then retrieves the selections based on the matches. For my problem I'm just using 2 dropdowns and code snippets. I have all 3 dropdowns populated - the first two from Linq to Sql and the 3rd is an option list created with Razor (A-Z).
I'm missing the step of setting the values of what was chosen into MemberSetup.SelectedProgramID and MemberSetup.SelectedOrganizationID. I'd like the text stored in MemberSetup.SelectedProgramName and MemberSetup.SelectedOrganizationName respectively. I think if I can get the selected ids into the model, I can pass them through ActionLink and not deal with #Html.Hidden variables. However, no matter what is selection the model SelectedProgramID and SelectedOrganizationID are zero (expect 1, 2, 3 or 4 for Program ID and 1, 2, 5, or 6 for Organization ID).
Any help / corrections would be appreciated.
Model:
{
public int SelectedProgramID { get; set; }
public string SelectedProgramName {
get { return this._myProgramName; }
set { this._myProgramName = value; }
}
public IEnumerable<SelectListItem> ProgramList { get; set; }
public int SelectedOrganizationID { get; set; }
public string SelectedOrganizationName
{
get { return this._myOrganizationName; }
set { this._myOrganizationName = value; }
}
public IEnumerable<SelectListItem> OrganizationList { get; set; }
}
Controller:
{
var db = new STARDataContext();
MemberSetup setupModel = new MemberSetup();
setupModel.ProgramList = db.ProgramAlls.ToList()
.Select(p => new SelectListItem
{
Value = p.ProgramID.ToString(),
Text = p.ProgramName.ToString()
});
setupModel.OrganizationList = db.AreaAlls.ToList()
.Select(p => new SelectListItem
{
Value = p.AreaID.ToString(),
Text = p.AreaName.ToString()
});
return View(setupModel);
}
View:
{
#using ( Html.BeginForm() ) {
#Html.DropDownListFor(model => model.SelectedProgramID, Model.ProgramList)
#Html.DropDownListFor(model => model.SelectedOrganizationID, Model.OrganizationList, "Please select Organization", new { #class = "DropDownList" } )
#Html.Hidden("SelectedProgramID", Model.SelectedProgramID)
#Html.Hidden("SelectedProgramName", Model.SelectedProgramName)
#Html.Hidden("SelectedOrganizationID", Model.SelectedOrganizationID)
#Html.Hidden("SelectedOrganizationName", Model.SelectedOrganizationName)
#Html.ActionLink("Get Members", "Select", new {programID=Model.SelectedProgramID,orgID=Model.SelectedOrganizationID })
}
}
use hiddenFor instead of hidden,so your syntax should look like this
#Html.HiddenFor(a=>a.SelectedProgramName)
Since you have SelectedProgramID and SelectedOrganizationID defined, you won't need to use hidden field for it. To construct the dropdown, you should do something like this
Html.DropDownListFor(x=>x.ID,
new SelectList(Model.Products,"ID", "Sku", Model.ID), " select ")
For your reference: Use Html.DropDownListFor to get a selected value
The above class, controller and view are correct for presenting the drop-downs. This is why I was perplexed.
However, I had the SelectMember in the Get section. [HttpPost] and SelectMember can see what was selected.

How to keep DropDownList values between a server call in ASP.NET MVC3

I have an ASP.NET MVC3 application. I have the following ViewModel:
public class MyViewModel
{
public string Year { get; set; }
public string Month {get; set; }
public IEnumerable<SelectListItem> Years
{
get
{
return Enumerable.Range(2000, DateTime.Now.Year - 2000).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = x.ToString()
});
}
}
}
And the following View:
#model MyNamespace.MyViewModel
#Html.DropDownListFor(
x => x.Year,
new SelectList(Model.Years, "Value", "Text"),
"-- select year --"
)
#Html.DropDownListFor(
x => x.Month,
Enumerable.Empty<SelectListItem>(),
"-- select month --"
)
I fill the DropDownList for Month with a jQuery function that is triggered onchange from the DropDownList for Year, which works perfectly. When the form is posted to the server and then the view is rendered back I want to keep the values in the 'Month' DropDownList as it happens correctly for Year. Therefore I tried (besides the jQuery script):
public class MyViewModel
{
public string Year { get; set; }
public string Month {get; set; }
public IEnumerable<SelectListItem> Months
{
get
{
if(Year != null)
{
return Enumerable.Range(1, 12).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = x.ToString()
});
}
}
}
And in the View:
#Html.DropDownListFor(
x => x.Month,
new SelectList(Model.Months, "Value", "Text"),
"-- select month --"
)
I left Years out of the code to make things shorter. This code throws a NullReferenceException at the first run because the IEnumerable is empty. how can I achieve my goal?
You have to repopulate the month list in your action.
The POST is stateless is not like asp.net webforms.
Just do something like this in your code:
public ViewResult MyAction(MyViewModel model)
{
if (ModelState.IsValid)
{
//.. do your stuff ...
//return redirect to index if everything went ok
}
//something went wrong return the model
model.Years = new SelectList(/* code to populate years */, "Value", "Text", Model.Year);
model.Months = new SelectList(/* code to populate months */, "Value", "Text", Model.Month);
}
As a side note I prefer to use SelectList instead of IEnumerable<SelectListItem> beacuse I can set the default value in the controller (a better fit for the controller responsibility in my opinion) and not in the View.

How to display bool values in a view and save the value to DB

I have a table that has bit values (true/false)
Table Definition:
CharacterID int
isActive bit
UserId uniqueidentifier
I have 2 problems:
How to display the existing selected option in the edit view in a Dropdown
I need to save the value (yes/No) as true and false in the database.
Here is what I have attempted so far:
<div class="editor-label">
#Html.LabelFor(model => model.IsActive)
</div>
<div class="editor-field">
#Html.DropDownList("", new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "true", Selected = Model.IsActive }, new SelectListItem() { Text = "No", Value = "false", Selected = !Model.IsActive }})
</div>
Assuming that model.IsActive is declared as bool:
Wouldn't using a CheckBox be a bit more intuitive to the user and require less clicks?
In that case you could just use:
#Html.EditorFor(model => model.IsActive)
If you really want dropdowns, then this SO might provide a working implementation: https://stackoverflow.com/a/4036922/1373170
Applied to your context, I believe it would be:
#Html.DropDownListFor(model => model.IsActive, new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}}, model.IsActive.ToString())
Now, for saving it to the database I'd have to know if you are using EF, L2S, etc.
But I imagine you already have an action in your controller set up for saving. In that case it is probably already receiving an instance of your model as parameter. Using DropDownListFor instead of DropDownList, your model should be bound automatically by MVC's default ModelBinder, and you should be able to map that to your database entity and store it.
There are couple things you need to setup for drop-down and viewmodel property to make this work.
1) Your view model:
public class MyModel
{
public MyModel()
{
BoolSelectList = new List<SelectListItem>();
}
public int CharacterID { get; set; }
public bool isActive { get; set; }
public Guid UserId { get; set; }
public IList<SelectListItem> BoolSelectList { get; set; }
}
2) In controller you need to assign value to bool Value and List
public MyModel viewmodel = new MyModel();
// Set other properties of viewmodel
// ....
// Set Drop-down List values
viewModel.BoolSelectList = new SelectList(new SelectListItem[] { new SelectListItem() { Text = "Yes", Value = "True" }, new SelectListItem() { Text = "No", Value = "False"}};
3) In your view :
#Html.LabelFor(model => model.isActive, "Is Active ")
#Html.DropDownListFor(model => model.isActive, Model.BoolSelectList, model.IsActive.ToString())
On your Post action, the value of IsActive should be True/False depending on your selection.

MVC-3 DropdownList or DropdownListFor - Can't save values in controller POST

I searches for hours (or days) and didn't find a solution yet. I want to edit a customer with a DropdownListFor for the salutation with the right preselected value.
I've got 3 entities (Database first concept, this is not my own design...): customer, address, salutation
A CUSTOMER has an address_id (f_key) and an ADDRESS has got a salutation_id (f_key). The ADDRESS holds the first and last name for example. Inside the SALUTATION entity there is a column sal1 which holds all possible salutations.
Now, I want to edit my customer via a ViewModel which looks like this:
public class CustomerViewModel
{
public CUSTOMER cust { get; set; }
public SelectList salutationList { get; set; }
CustomerRepository repository = new CustomerRepository();
public CustomerViewModel(int id)
{
cust = repository.GetCustomerByIdAsQueryable(id).Single();
salutationList = new SelectList(repository.GetSalutations(), cust.ADDRESS.SALUTATION.SAL1);
}
// Some more
}
The CutsomerRepository methods:
public class CustomerRepository
{
private MyEntities db = new MyEntities();
public IQueryable<CUSTOMER> GetCustomerByIdAsQueryable(int id) {...}
public IQueryable<CUSTOMER> GetCustomersByName(string firstName, string lastName, int maxCount) {...}
public List<string> GetSalutations()
{
var salutationList = new List<string>();
var salutationListQry = from s in db.SALUTATION
select s.SAL1;
salutationListTemp.AddRange(salutationListQry);
return salutationList;
}
// ...
}
This is my controller method:
[HttpPost]
public ActionResult CustomerData(int id, FormCollection fc)
{
var vm = new CustomerViewModel(id);
// Why do I need the following line?
vm.cust = repository.GetCustomerByIdAsQueryable(id).Single();
try
{
UpdateModel(vm, fc);
repository.Save();
return View("CustomerData", vm);
}
catch (Exception e)
{
return View();
}
}
And finally the part from my View:
#model WebCRM.ViewModels.CustomerViewModel
#using (Html.BeginForm())
{
// ...
<div class="editor-label">
#Html.Label("Salutation:")
#Html.DropDownListFor(model => model.cust.ADDRESS.SALUTATION.SAL1, Model.salutationList)
// #Html.DropDownList("Salutation", Model.salutationList)
</div>
<div class="editor-label">
</div>
<div class="editor-field">
#Html.Label("Last name:")
#Html.EditorFor(model => model.cust.ADDRESS.LASTNAME)
#Html.ValidationMessageFor(model => model.cust.ADDRESS.LASTNAME)
</div>
<p>
<input type="submit" value="Speichern" />
</p>
}
Changing and saving last names works fine. But when saving the salutation it changes the SAL1 value in the SALUTATION entity to the one I've chosen in the DropdownListFor. What I want is to change the salutation_id inside the ADDRESS entity for my customer. Why isn't that working?
Another strange behavoior: When removing the marked line in my CustomerController, I can't even change and save the last name. Normally the constructor of the CustimerViewModel sets the customer. So why do I have to have the line of code for setting the customer inside my ViewModel? It's duplicated, but has to be there...
Thanks in advance.
You need to have Selected property in your list.
I can show you my working example:
public static IEnumerable<SelectListItem> GetCountries(short? selectedValue)
{
List<SelectListItem> _countries = new List<SelectListItem>();
_countries.Add(new SelectListItem() { Text = "Select country...", Value = "0", Selected = selectedValue == 0 });
foreach (var country in ObjectFactory.GetInstance<DataRepository>().GetCountries())
{
_countries.Add(new SelectListItem()
{
Text = country.Name,
Value = country.ID.ToString(),
Selected = selectedValue > 0 && selectedValue.Equals(country.ID)
});
}
return _countries;
}
In controller i store this into viewbag:
ViewBag.Countries = CompanyModel.GetCountries(0);
In view:
#Html.DropDownListFor(m => m.CompanyModel.CountryId, (IEnumerable<SelectListItem>)ViewBag.Countries)

How do you properly create a MultiSelect <select> using the DropdownList helper?

(sorry, there are several item here but none seems to allow me to get this working.)
I want to create a DropDownList which allows multiple selection. I am able to populate the list but I can't get the currently selected values to seem to work.
I have the following in my controller:
ViewBag.PropertyGroups = from g in db.eFinGroups
where g.GroupType.Contents == "P"
select new
{
Key = g.Key,
Value = g.Description,
Selected = true
};
ViewBag.SelectedPropertyGroups = from g in company.Entities
.First().Properties.First().PropertyGroups
select new {
g.eFinGroup.Key,
Value = g.eFinGroup.Description };
In the view I have:
#Html.DropDownListFor(model => model.PropertyGroupsX,
new MultiSelectList(ViewBag.PropertyGroups
, "Key", "Value"
, ViewBag.SelectedPropertyGroups),
new { #class = "chzn-select", data_placeholder = "Choose a Property Group", multiple = "multiple", style = "width:350px;" })
PropertyGroupX is a string[] in the model.
I have tried all types of iterations with the selected properties... passing just the value, just the key, both, etc.
Also, what type is PropertyGroupX supposed to be? Is string array correct? Or should it be a dictionary that contains the current propertygroups? I really am having a hard time finding doc on this.
Someone suggested I should be using ListBoxFor. I have changed to that and still have the same issue. The selected values are not being set as selected when the option tags are rendered. Here is what I have tried:
#Html.ListBoxFor(model => model.PropertyGroups, new MultiSelectList(ViewBag.PropertyGroups, "Key", "Value"))
I have tried the model.PropertyGroups as a collection of string matching the Values, as a collection of Guid matching this IDs and as an anonymous type with both a Key and Value to match the items in the ViewBag. Nothing seems to work.
You don't use DropDownListFor if you want to create a multiselect list. You use the ListBoxFor helper.
View model:
public class MyViewModel
{
public string[] SelectedIds { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
Controller:
public ActionResult Index()
{
var model = new MyViewModel
{
// preselect the first and the third item given their ids
SelectedIds = new[] { "1", "3" },
// fetch the items from some data source
Items = Enumerable.Range(1, 5).Select(x => new SelectListItem
{
Value = x.ToString(),
Text = "item " + x
})
};
return View(model);
}
View:
#model MyViewModel
#Html.ListBoxFor(x => x.SelectedIds, Model.Items)

Resources