dropdownlistfor not displaying correct value - asp.net-mvc

My query is getting all the correct values and the selectlist is populated, but my dropdownlist only shows the first value in the selectlist. how can i get it to show the returned value of Captain?
Viewmodel:
public class EditTeamsView : BaseCommunityView
{
...
public IList<Domain.Team> ExistingTeams { get; set; }
...
public EditTeamsView()
{
ExistingTeams = new List<Domain.Team>();
}
}
public class Team
{
...
public string Captain { get; set; }
public IEnumerable<SelectListItem> MemberSelectList { get; set; }
}
View:
#for (var c = 0; c < Model.ExistingTeams.Count; c++)
{
#Html.DropDownListFor(x => x.ExistingTeams[c].Captain, Model.ExistingTeams[c].MemberSelectList,
new { #class = "form-control "})
}

Each option in the dropdown will need a value property and a display property so you may need to change up your Team class's MemberSelectList object to IEnumerable that contains value and text properties.
To set the default value of a drop down list based on a string value like what you have, new up a SelectList that requires an IEnumerable list of objects like what you have, a value property, a text property, and then the default value object.
See here: https://msdn.microsoft.com/en-us/library/system.web.mvc.selectlist.selectlist(v=vs.118).aspx#M:System.Web.Mvc.SelectList.
#Html.DropDownListFor(x => x.ExistingTeams[c].Captain,
new SelectList(Model.MemberSelectList, "Value", "Text", Model.Captain)
)

Related

MVC DisplayTemplate for Lookup list

I am calling a partial view on which I want to collapse a few dropdown controls(previously created by using DropDownListFor). Because the controls are readonly, I just need to show the selected value on each control. I have created a list called "salutations" in the controller, and pass it as ViewData to my partial view. On the partial view I need to see the selected salutation (e.g.. Mr/Miss/Dr)in my div using #Html.DisplayFor. I tried creating a DisplayTemplate according to an online posting, but I am still having issues getting this to work.
Lookup list declared like this in controller:
var salutations = (IEnumerable<lu_Salutation>)ViewData["salutations‌​"];
Here's my DisplayTemplate named LookupList.cshtml:
#model int
#using System.Linq
#vEmployee.SelectList1.Single(s => s.Value == Model.ToString()).Text
Of course, there's something wrong with the last line of the above code. vEmployee is the name of my model. How do I correct it?, and can I have a generic display template like the GridForeignKey Kendo EditorTemplate so I could easily pass the foreign key, the DisplayTemplate, and the lookup list to get just the text of the selected lookup value displayed?
Ideally, I will just like to have in my partial view, something like:
#Html.DisplayFor(model => model.id, "LookupList", SelectList((IEnumerable)ViewData["salutationList"], "TitleID", "Title"))
where TitleID and Title are respectively the value and text in the lookup list.
Models
public class lu_Salutation
{
public int TitleID { get; set; } // e.g. 1
public string Title { get; set; } // e.g. Mrs
}
ViewModel Class - I want to use just IDs here, but display the matching Texts from the lookup tables (e.g lu_Salutation) when needed
public class vEmployee
{
[Key]
public int EmployeeID { get; set; }
public int SalutationID { get; set; }
}
Controller
[HttpGet]
public ActionResult EmployeeDetails(int employeeID)
{
vEmployee SelectedEmployee = GetEmployees(employeeID).First();
ViewData["salutations"] = _db.lu_Salutation.OrderBy(e => e.Title);
return PartialView("_EmployeeDetails", SelectedEmployee);
}
private IEnumerable<vEmployee>GetEmployees(int employeeID)
{
IEnumerable<vEmployee> emp = (from e in _db.Employees
join c in _db.Contacts on e.EmployeeID equals c.EmployeeID
join u in _db.lu_Salutation on c.SalutationID equals u.TitleID into sal
from u in sal.DefaultIfEmpty()
where (e.EmployeeID == employeeID))
select new vEmployee
{
EmployeeID = e.EmployeeID,
SalutationID = c.SalutationID
}).AsEnumerable().OrderBy(m => m.EmployeeNumber).ThenBy(m => m.FirstName);
return emp;
}

Dropdownlistfor returns null value

I have a customer class with a property Gender. I created a list of Gender type which contains and id number and Gender type. When form is submitted, I am getting null value.
View
#model MovieRentals.ViewModel.CustomerView
<div class="form-group">
<h4>#Html.LabelFor(l => l.Customer.BirthDate)</h4>
#Html.DropDownListFor(l => l.CustomerGender, new SelectList(Model.CustomerGender, "GenderId", "GenderType"), "Select Gender", new { #class = "form-control" })
</div>
Model
public class CustomerView
{
public IEnumerable<MembershipType> MembershipTypes{ get; set; }
public Customer Customer { get; set; }
public List<GenderClass> CustomerGender{ get; set; }
}
public class GenderClass
{
public int GenderId { get; set; }
public string GenderType { get; set; }
}
Controller
public ActionResult New()
{
var MembershipTy = _context.MemebershipType.ToList();
var ViewModel = new CustomerView();
ViewModel.CustomerGender = new List<GenderClass>()
{
new GenderClass(){ GenderId = 1, GenderType = "Male"},
new GenderClass() { GenderId = 2, GenderType = "Female"}
};
ViewModel.MembershipTypes = MembershipTy;
return View(ViewModel);
}
You need two properties: one to hold the selected value and one to hold the options. The one that holds the options should be IEnumerable<SelectListItem>. Your GenderClass class is completely superfluous.
Also, using an integer id as the value doesn't make sense when the meaning of that value is not obvious. Here, the fact that 1 means Male only exists in the New action. Anywhere else, you will then have to repeat this logic (which introduces opportunities for errors, e.g. was male 1 or 0). Further, if you decide to change those values, you must remember to change them everywhere. If you want to use an integer id, then you should abstract away the meaning somewhere, be it an enum, static class, database table, etc. The far better choice is to just keep it a string, and use the dropdown merely to enforce normalization of that string value.
public string CustomerGender { get; set; }
public IEnumerable<SelectListItem> CustomerGenderChoices
{
get
{
return new List<SelectListItem>
{
new SelectListItem { Value = "Male", Text = "Male" },
new SelectListItem { Value = "Female", Text = "Female" }
}
}
}
Then, in your view:
#Html.DropDownListFor(m => m.CustomerGender, Model.CustomerGenderChoices, "Select Gender", new { #class = "form-control" })
Alternatively, if you were to use an enum:
public enum Genders
{
Male = 1,
Female = 2
}
Then, in your view model, you would only need one property, just to store the value:
public Genders CustomerGender { get; set; }
Then, in your view, you can make use of EnumDropDownListFor:
#Html.EnumDropDownListFor(m => m.CustomerGender, "Select Gender", new { #class = "form-control" })
As an enum, the value stored would be an int, but the benefit here is that you have a strongly-typed association between those integer values and what they mean. For example, rather than doing something like:
if (customer.CustomerGender == 1) // Male
You can do:
if (customer.CustomerGender == Genders.Male)
Obviously, the second version is much more obvious in meaning.

Is it possible to create an Html.DropDownListFor directly from an entity model?

I have an IEnumerable of managers Model.managers from this I want to grab the ID value which would be managers.manager_id and the text value which would be managers.manager_name I also have a selected manager value at Model.SelectedManager which holds the manager_id
What I am trying to do is to stuff all of these values into an Html.DropDownListFor
It would need to be a list of all of the manager_id and manager_name and then automatically select the manager stored at Model.SelectedManager is this possible the way I have set it up?
public string SelectedManager { get; set; }
public virtual IEnumerable<managements> managers { get; set; }
I believe you are trying to do the following:
In a service layer (or the controller), you grab a List of SelectListItem from that managers IEnumerable:
model.ManagerList = managers.Select(i => new SelectListItem()
{
Text = i.manager_name,
Value = i.manager_id.ToString()
}).ToList());
Then, in your view model, you need that SelectedManager for Id and this manager list (of SelectListItem):
public string SelectedManager { get; set; }
public List<SelectListItem> ManagerList {get; set;}
and in your view, you use the ManagerList object with the razor helper:
#Html.DropDownListFor(m => Model.SelectedManager, Model.ManagerList,
new {#class = "form-control input-sm whatever-css-class"})
Hope this helps.
Edit: I have always used the selected id as an int and not a string. So I have not tested it as a string actually, and you may want to use it as int if string does not work.

Formatting a Drop Down List in ASP.NET MVC

I'm building an app with ASP.NET MVC 4. I'm binding my model to a view. In my view, I need a drop down list. That drop down list needs to show quarters. The quarters should be displayed as "Q1", "Q2", "Q3", and "Q4". My model, only has quarter numbers. They are defined like this:
public List<short> Quarters = new List<short>() { get; set; }
public short? SelectedQuarter = null;
public void Initialize() {
Quarters.Add(1);
Quarters.Add(2);
Quarters.Add(3);
Quarters.Add(4);
}
Somehow, I need to prepend "Q" to each value. However, I'm not sure how to do this in ASP.NET MVC. How does someone do this?
Thanks!
Create a SelectList to be used by DropdownListFor() so that you bind the selected option to property SelectedQuarter, but display the 'friendly' name.
View model
public class MyViewModel
{
[Display(Name = "Quarter")]
[Required]
public short? SelectedQuarter { get; set; } // must be a property, not a field!
IEnumerable<SelectListItem> QuarterList { get; set; }
}
Controller
public ActionResult Edit()
{
MyViewModel model = new MyViewModel();
ConfigureViewModel(model);
return View(model);
}
public ActionResult Edit(MyViewModel model)
{
if(!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// model.SelectedQuarter contains the selected value
}
private void ConfigureViewModel(model)
{
model.SelectedQuarter = new List<SelectListItem>()
{
new SelectListItem() { Value = "1", Text = "Q1" },
new SelectListItem() { Value = "2", Text = "Q2" },
new SelectListItem() { Value = "3", Text = "Q3" },
new SelectListItem() { Value = "4", Text = "Q4" },
}
}
View
#model MyViewModel
#using(Html.BeginForm())
{
#Html.LabelFor(m => m.SelectedQuarter)
#Html.DropDownListFor(m => m.SelectedQuarter, Model.QuarterList, "-Please select-")
#Html.ValidationMessageFor(m => m.SelectedQuarter)
<input type="submit" />
}
Assuming you have this property:
public List<short> Quarters { get; set; }
Then in your view or any other consuming code you can generate a list of strings with something like:
model.Quarters.Select(q => "Q" + q)
or:
model.Quarters.Select(q => string.Format("Q{0}", q))
However, semantically it really feels like this belongs on a view model and not in consuming code. Ideally the view should only ever need to bind directly to properties on the view model, not transform those properties. Something like this:
public IEnumerable<string> QuartersDisplay
{
get { return Quarters.Select(q => string.Format("Q{0}", q)); }
}
Then consuming code can just bind to that property:
model.QuartersDisplay
(If the model is a domain model then I'd recommend introducing a view model between the domain and the view, since this wouldn't belong on a domain model.)
Thinking about this a little more... Do you want one property with both the displays and the backing values for the drop down list? That would likely be a IDictionary<short, string>, I imagine? Something like this:
public IDictionary<short, string> QuartersOptions
{
get { return Quarters.ToDictionary(q => q, q => string.Format("Q{0}", q)); }
}
In which case you'd bind to that property:
model.QuartersOptions
Keep in mind that a drop down list often binds to two things. The property which holds the list of possible values (which is what we've built here) and the property which holds the selected value (which remains your SelectedQuarter property).

MVC3 cannot validate dropdownfor

Not sure if i'm populating my dropdown correctly but I'm having issue validating the values in my dropdownlist. When a value has been selected it's still showing error 'The value x is invalid'. The type is of int? as I know int doesn't work with the validator.
View model code:
[Display(Name = "Category")]
[Required(ErrorMessage = "Category is required.")]
public AWS.DTO.Lookup Category { get; set; }
public IEnumerable<AWS.DTO.Lookup> Categories { get; set; }
Controller code:
[PageOptions(Title = "Create FMR")]
public ActionResult Create()
{
var model = new FMRRequestViewModel();
model.Categories = new AWS.BL.Lookup().GetFMRCategories();
return View(model);
}
Lookup Type:
public class Lookup
{
public int? ID { get; set; }
public string Description { get; set; }
}
View code:
#Html.DropDownListFor(m => m.Category, new SelectList(Model.Categories, "ID", "Description", -1), "-- Please Select -- ")
Thanks in advance for any help.
DropDown's don't work that way. A dropdown can only send the ID, not the text. You are passing the whole Category object to DropDownListFor, which it won't understand.
#Html.DropDownListFor(m => m.Category.ID, new SelectList(Model.Categories, "ID", "Description", -1), "-- Please Select -- ")
It's not going to bind to a Lookup model once selected. MVC doesn't work like ASP where you receive back an object (ASP you'd "bind" an enumerable of objects and, when selected, the whole object was returned--this is not the case in mvc, only the key will be returned (or whatever property was mapped as the dropdown's value)).
Instead you'd have to accept an Int32 then in your action retrieve the matching Lookup. So, in short:
change your ViewModel so Category is an Int32/int (and not a Lookup object).
in the receiving action map the Lookup based on what Category has for a populated value.

Resources