I am trying to use a DropdownlistFor in MVC to add an object to my database. I am able to populate the dropdown fine, but when I post the form I get an error as the ID of the dropdown (which is a foreign key to the Team object) is populated but not the actual value. Here is my code :
[HttpGet]
public ActionResult FixtureAdd()
{
IEnumerable<SelectListItem> teams = _repository.GetTeams()
.Select(c => new SelectListItem
{
Value = c.TeamId.ToString(),
Text = c.TeamName
}).ToList();
IEnumerable<SelectListItem> weeks = _repository.GetWeeks()
.Select(c => new SelectListItem
{
Value = c.ToString(),
Text = c.ToString()
}).ToList();
ViewBag.Teams = new SelectList(teams, "Value", "Text");
ViewBag.Weeks = new SelectList(weeks, "Value", "Text");
string apiUri = Url.HttpRouteUrl("DefaultApi", new { controller = "fixture", });
ViewBag.ApiUrl = new Uri(Request.Url, apiUri).AbsoluteUri.ToString();
return View();
}
[HttpPost]
public ActionResult FixtureAdd(Fixture fx)
{
if (ModelState.IsValid)
{
try
{
//TODO: Add insert logic here
_repository.AddFixture(fx);
return RedirectToAction("FixtureAdd");
}
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
return View(fx);
}
}
else
{
IEnumerable<SelectListItem> teams = _repository.GetTeams()
.Select(c => new SelectListItem
{
Value = c.TeamId.ToString(),
Text = c.TeamName
}).ToList();
ViewBag.Teams = new SelectList(teams, "Value", "Text");
IEnumerable<SelectListItem> weeks = _repository.GetWeeks()
.Select(c => new SelectListItem
{
Value = c.ToString(),
Text = c.ToString()
}).ToList();
ViewBag.Weeks = new SelectList(teams, "Value", "Text");
return View(fx);
}
}
public IEnumerable<Team> GetTeams()
{
return _db.Teams.ToArray();
}
public partial class Fixture
{
public int FixtureId { get; set; }
public string Season { get; set; }
public byte Week { get; set; }
//foreign key
public int AwayTeamId { get; set; }
//navigation properties
public virtual Team AwayTeam { get; set; }
//foreign key
public int HomeTeamId { get; set; }
//navigation properties
public virtual Team HomeTeam { get; set; }
public byte? AwayTeamScore { get; set; }
public byte? HomeTeamScore { get; set; }
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Fixture</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Season)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Season)
#Html.ValidationMessageFor(model => model.Season)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Week)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Week, (SelectList)ViewBag.Weeks)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AwayTeam.TeamId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.AwayTeam.TeamId, (SelectList)ViewBag.Teams)
#Html.ValidationMessageFor(model => model.AwayTeam.TeamId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AwayTeamScore)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AwayTeamScore)
#Html.ValidationMessageFor(model => model.AwayTeamScore)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HomeTeam.TeamId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.HomeTeam.TeamId, (SelectList)ViewBag.Teams)
#Html.ValidationMessageFor(model => model.HomeTeam.TeamId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.HomeTeamScore)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HomeTeamScore)
#Html.ValidationMessageFor(model => model.HomeTeamScore)
</div>
<p>
<button data-bind='click: save'>Add fixture</button>
</p>
</fieldset>
}
The TeamId foreign key field gets populated in the post but the TeamName does not. Any ideas why? This is my first attempt at this so I expect I am possibly making more than one error with this.
MVC, unlike traditional ASP, is light-weight and doesn't store all those objects in a hidden field. That is to say, if you had the following:
class Customer {
public Int32 Id { get; set; }
public String Name { get; set; }
}
In normal ASP you could map a collection of these objects to a dropdown list and on the post back you'd get the original object that was referenced in the result. MVC doesn't work this way because it's not storing these objects any more. So if you want that intended object you're going to need to use the passed ID and re-retrieve the desired result.
Picture the following EditorTemplate for a CustomerId property on your model:
#model Int32
#Html.DropDownListFor(x => x, new SelectList(
Customers.GetAllCustomers().Select(y => new SelectListItem {
Value = y.Id,
Text = y.Name,
Selected = Model == y.Id
})
);
And of course:
#Html.EditorFor(x => x.CustomerId) #* Use above EditorTemplate *#
Then in your submit action:
[HttpPost]
public ActionResult(MyViewModel model)
{
if (ModelState.IsValid)
{
// ID was passed, re-fetch the customer based on selected id
Customer customer = Customers.GetById(model.CustomerId)
/* ... */
}
/* ... */
return View();
}
Related
i'm new to asp.net mvc and i would like to know why ModelState.IsValid=false ??
in edit view when using
if (ModelState.IsValid)
{
//code
}
the complete code listed here:
model classes:
public class Departments
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employeesss { get; set; }
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string City { get; set; }
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public virtual Departments Id { get; set; }
}
public class dropdownDbContext : DbContext
{
public DbSet<Departments> Departments { get; set; }
public DbSet<Employee> Employees { get; set; }
}
in controller these are the edit controller
public ActionResult Edit(int id = 0)
{
Employee employee = db.Employees.Find(id);
if (employee == null)
{
return HttpNotFound();
}
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name", employee.DepartmentId);
return View(employee);
}
//
// POST: /empttttttttttttttttt/Edit/5
[HttpPost]
public ActionResult Edit(Employee employee)
{
if (!ModelState.IsValid)
{
var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));
// Breakpoint, Log or examine the list with Exceptions.
}
if (ModelState.IsValid)
{
db.Entry(employee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "Name", employee.DepartmentId);
return View(employee);
}
in view
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Employee</legend>
#Html.HiddenFor(model => model.EmployeeId)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.City)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.City)
#Html.ValidationMessageFor(model => model.City)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DepartmentId, "Id")
</div>
<div class="editor-field">
#Html.DropDownList("DepartmentId", String.Empty)
#Html.ValidationMessageFor(model => model.DepartmentId)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
it doesn't show error but the edit didn't work properly in this logic when using
if (ModelState.IsValid)
{
db.Entry(employee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
and i would like to know why ModelState.IsValid=false ??
this is error snapshot
The parameter conversion from type 'System.String' to type 'dropdown.Models.Departments' failed because no type converter can convert between these types.
Change:
if (!ModelState.IsValid)
{
var errors = ModelState.SelectMany(x => x.Value.Errors.Select(z => z.Exception));
// Breakpoint, Log or examine the list with Exceptions.
}
To:
if (!ModelState.IsValid)
{
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new { x.Key, x.Value.Errors })
.ToArray();
}
Then you put your breakpoint on errors instead
EDIT:
Change your model like this:
public class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string City { get; set; }
[ForeignKey("Departments")]
public int DepartmentId { get; set; }
public virtual Departments department { get; set; }
}
I am creating one registration form which contains details like:
FullName:Textbox
Email:Textbox
Skills:checkbox playing
checkbox dancing
checkbox programming
I want to display my view like this.but only problem i am getting is with my checkbox.
My Model:
public class EmployeeModel
{
public int Id { get; set; }
public string Fullname { get; set; }
public List<SelectedSkillsModel> Skills { get; set; }
}
public class SelectedSkillsModel
{
public bool Selected { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
My Controller:
public ActionResult Index()
{
var employeeModel = new EmployeeModel();
employeeModel.Skills = GetSkills();
return View(employeeModel);
}
private List<SelectedSkillsModel> GetSkills()
{
var Skills = new List<SelectedSkillsModel>();
Skills.Add(new SelectedSkillsModel { Name = "Playing", Id = 1, Selected = false });
Skills.Add(new SelectedSkillsModel { Name = "Dancing", Id = 2, Selected = false });
Skills.Add(new SelectedSkillsModel { Name = "Music", Id = 3, Selected = false });
Skills.Add(new SelectedSkillsModel { Name = "Programming", Id = 4, Selected = false });
return Skills;
}
This is my View:
<fieldset>
<legend>EmployeeModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Fullname)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Fullname)
#Html.ValidationMessageFor(model => model.Fullname)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
//What should i do here to display checkbox with appropraite skills???
<div class="editor-label">
#Html.LabelFor(model => model.Skills)
</div>
<div class="editor-field">
#foreach (var item in Model.Skills)
{
#Html.CheckBox();
}
</div>
When i will submit my registration form then i should get appropriate skills with Id,Selected and Name value in my EmployeeModel model.
Note:I want to use Only Razor checkbox
How do i do this???
You have to use Html.CheckBoxFor() use bool parameter which Selected property in your SelectedSkillsModel and use Html.HiddenFor() to post the id of the skill this way:
#for (int i = 0; i < Model.Skills.Count; i++)
{
#Html.CheckBoxFor(m => m.Skills[i].Selected , new { id = "sikll_" + i })
#Html.HiddenFor(m => m.Skills[i].Id)
#Html.HiddenFor(m => m.Skills[i].Name)
#Html.DisplayFor(m => m.Skills[i].Name)
}
You need a for loop or a custom EditorTemplate for typeof SelectedSkillsModel
Using a loop
for (int i = 0; i < Model.Skills.Count; i++)
{
#Html.LabelFor(m => m.Skills[i].Selected)
#Html.CheckBoxFor(m => m.Skills[i].Selected)
#Html.HiddenFor(m => m.Skills[i].Id)
....
}
Using an editor template (/Views/Shared/EditorTemplates/SelectedSkillsModel.cshtml)
#model SelectedSkillsModel
#Html.LabelFor(m => m.Selected)
#Html.CheckBoxFor(m => m.Selected)
#Html.HiddenFor(m => m.Id)
and in the main view
#model EmployeeModel
....
#Html.EditorFor(m => m.Skills)
This question already has answers here:
ASP.NET MVC 4 - for loop posts model collection properties but foreach does not
(2 answers)
Closed 8 years ago.
I am new in ASP.MVC4 and I am facing with problem to pass object from view to controller:
Let me explain my problem from beginning:
My class which is used by is for example: UserAndRolesModel
public class UserAndRolesModel
{
public user User { get; set; }
public IEnumerable<UserAndRoles> AsignedRoles { get; set; }
}
As You can see class UserAndRolesModel persists of 2 objects: user and Enumerable
public class user
{
[HiddenInput(DisplayValue=false)]
public virtual int user_id { get; set; }
[Required(ErrorMessage = "Please provide name")]
[Display(Name = "Name")]
public virtual string user_name { get; set; }
[Display(Name = "Is active?")]
public virtual bool user_active { get; set; }
}
public class UserAndRoles
{
public string RoleName { get; set; }
public bool IsAssigned { get; set; }
}
My controller action is simple, it assign user to UserWithRoles.User and creates tempList with UserAndRoles objects.
public ActionResult Edit(int userid=0)
{
//object which will be passed to View
UserAndRolesModel UserWithRoles = new UserAndRolesModel();
//user
UserWithRoles.User = repoUsers.Users.FirstOrDefault(x => x.user_id == userid);
//roles
IList<UserAndRoles> tempList = new List<UserAndRoles>();
UserAndRoles temp1 = new UserAndRoles();
temp1.RoleName="Admin";
temp1.IsAssigned=true;
UserAndRoles temp2 = new UserAndRoles();
temp2.RoleName="User";
temp2.IsAssigned=false;
tempList.Add(temp1);
tempList.Add(temp2);
//assign tempList to model
UserWithRoles.AsignedRoles = tempList;
return View(UserWithRoles);
)
At this stage I am successfully passing to View:
UserWithRoles.User.user_id=1;
UserWithRoles.User.user_name="UserName1";
UserWithRoles.User.user_active=true;
UserWithRoles.AsignedRoles[1].RoleName = "Admin";
UserWithRoles.AsignedRoles[1].IsAssigned = true ;
UserWithRoles.AsignedRoles[2].RoleName = "User";
UserWithRoles.AsignedRoles[2].IsAssigned = false;
I am able to display above View properly:
#model Models.UserAndRolesModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-field">
#Html.EditorFor(model => model.User.user_id)
#Html.ValidationMessageFor(model => model.User.user_id)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.user_name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.user_name)
#Html.ValidationMessageFor(model => model.User.user_name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.User.user_active)
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.User.user_active)
#Html.ValidationMessageFor(model => model.User.user_active)
</div>
<br /> ROLES below is piece of code which makes me cry<br />
#foreach (var item in Model.AsignedRoles)
{
<div class="editor-field">
<div class="editor-field">
#Html.LabelFor(model => item.RoleName)
#Html.CheckBoxFor(model => item.IsAssigned)
</div>
</div>
}
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
When i Click submit all data regarding user was passed properly but IEnumerable AsignedRoles is always null.
Here is my controller method on post:
[HttpPost]
public ActionResult Edit(UserAndRolesModel UserWithRoles)
{
if (ModelState.IsValid)
{
if (UserWithRoles.AsignedRoles==null)
Console.WriteLine("I am still crying");
else
Console.WriteLine("Got it!");
}
return View(UserWithRoles);
}
In View I tried to use other loops for example:
#for (int i = 0; i < Model.AsignedRoles.Count(); i++)
{
<div class="editor-field">
#Html.LabelFor(model => item[i].IsAssigned)
#Html.CheckBoxFor(model => item[i].IsAssigned)
</div>
}
But above also does not pass IEnumerable.
Can anyone help me to resolve this issue? How can I pass back to controller UserAndRolesModelwhich contains IEnumerable?
I will be very grateful. Advance thanks for the help!
You do need the for loop, but the one you tried you have referenced item[i], yet item[i] no longer exists. Try this, note that I have also added a HiddenFor for RoleName otherwise that won't get passed back:
#for (int i = 0; i < Model.AsignedRoles.Count(); i++)
{
<div class="editor-field">
#Html.LabelFor(model => model.AssignedRoles[i].IsAssigned)
#Html.CheckBoxFor(model => model.AssignedRoles[i].IsAssigned)
#Html.HiddenFor(model => model.AssignedRoles[i].RoleName)
</div>
}
I'm trying to make very simple forum, but I have problem with DropDownList. I have two models:
ForumThread.cs
public partial class ForumThread
{
public ForumThread()
{
this.ForumCategory = new HashSet<ForumCategory>();
}
public int TH_ID { get; set; }
public System.DateTime DATE { get; set; }
public string TOPIC { get; set; }
public string USER { get; set; }
public virtual ICollection<ForumCategory> ForumCategory { get; set; }
}
ForumCategory.cs
public partial class ForumCategory
{
public ForumCategory()
{
this.ForumThread = new HashSet<ForumThread>();
}
public int CA_ID { get; set; }
public string CATEGORY { get; set; }
public bool isSelected { get; set; }
public virtual ICollection<ForumThread> ForumThread { get; set; }
}
I tried to make "Create" function with view:
Create
#model AnimeWeb.Models.ForumThread
#{
ViewBag.Title = "Create";
}
<h2>New Thread</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-field">
#Html.HiddenFor(model => model.TH_ID)
</div>
<div class="editor-label">
TOPIC
</div>
<div class="editor-field">
#Html.EditorFor(model => model.TOPIC)
#Html.ValidationMessageFor(model => model.TOPIC)
</div>
<div class="editor-label">
CATEGORY
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ForumCategory)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
And PartialView for ForumCategory:
ForumCategory
#model AnimeWeb.Models.FORUMCATEGORY
#Html.HiddenFor(model => model.CA_ID)
#Html.HiddenFor(model => model.CATEGORY)
<div>
#Html.DropDownListFor(item => Model.CA_ID, ViewBag.CA_ID as SelectList, "-- Select --")
</div>
ForumController
public ActionResult Create()
{
var db = new MainDatabaseEntities();
var viewModel = new ForumThread
{
ForumCategory = db.ForumCategory.Select(c => new { CA_ID = c.CA_ID, CATEGORY = c.CATEGORY, isSelected = false }).ToList().Select(g => new ForumCategory
{
CA_ID = g.CA_ID,
CATEGORY = g.CATEGORY,
isSelected = false
}).ToList(),
};
return View(viewModel);
}
//
// POST: /Forum/Create
[HttpPost]
public ActionResult Create(ForumThread forumthread, String user, int id)
{
var db = new MainDatabaseEntities();
var newthread = new ForumThread
{
TH_ID = forumthread.TH_ID,
DATE = DateTime.Now,
TOPIC = forumthread.TOPIC,
USER = forumthread.USER,
ForumCategory = new List<ForumCategory>()
};
foreach (var selectedCategory in forumthread.FORUMCATEGORY.Where(c => c.isSelected))
{
var category = new ForumCategory { CA_ID = selectedCategory.CA_ID };
db.ForumCategory.Attach(category);
newthread.ForumCategory.Add(category);
}
db.ForumThread.Add(newthread);
db.SaveChanges();
return RedirectToAction("Index");
}
And it obviously doesn't work. I tried to use other threads on this forum but nothing helped. Could someone explain me how to make this work?
The error is in partial view of ForumCategory:
The ViewData item that has the key 'CA_ID' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
In your PartialView for ForumCategory, your cast is not correct:
#Html.DropDownListFor(item => Model.CA_ID, ViewBag.CA_ID as SelectList, "-- Select --")
You have to use a SelectList (List of SelectListItem) that you can implement for example in a method in your model:
public List<SelectListItem> GetCategories()
{
var db = new MainDatabaseEntities();
List<SelectListItem> list = new List<SelectListItem>();
// Add empty item if needed
SelectListItem commonItem = new SelectListItem();
commonItem.Text = "--- Select ---";
commonItem.Value = "-1";
commonItem.Selected = true;
list.Add(commonItem);
// Add items from Database
foreach (ForumCategory fc in db.ForumCategory)
{
SelectListItem i = new SelectListItem();
i.Text = fc.CATEGORY;
i.Value = fc.CA_ID.ToString();
list.Add(i);
}
return list;
}
And then you can have you dropdown like that:
#Html.DropDownList("DropName", Model.GetCategories())
There may be other errors in some parts of your code, I just answered to the one you quoted
In your editortemplate, you have:
ViewBag.CA_ID as SelectList
But you don't show where you fill the ViewBag. Instead you might want to do something like this:
#Html.DropDownListFor(m => m.CA_ID,
new SelectList(Model.ForumCategory,
"CA_ID", "CATEGORY", Model.CA_ID))
As also explained in MVC3 DropDownListFor - a simple example?.
I am trying to put a list of medical product brand names in a dropdown list on my edit.cshtml file using Html.DropDownListFor(). I am trying to use the Html helper properly but my efforts have been unsuccessful. Model.BrandSelectListItem is an IEnumerable that is supposed to go into the DropDownList.
Also, I don't understand why I need to reference the model as 'model' in the lambda expression, but as 'Model' in the second argument of the following code segment:
#Html.DropDownListFor(model => model.BrandName, Model.BrandSelectListItem)
when executing the code, I receive the following run-time error:
The ViewData item that has the key 'BrandName' is of type
'System.String' but must be of type 'IEnumerable'.
Here are some classes that may be relevant to this error:
MedicalProduct
public class MedicalProduct
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
// is a foreign key
public Nullable<int> BrandID { get; set; }
}
MedicalProductViewModel
public class MedicalProductViewModel
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[DataType(DataType.Currency)]
public double Price { get; set; }
public Nullable<int> BrandID { get; set; }
[DisplayFormat(NullDisplayText="[Generic]")]
public string BrandName { get; set; }
public IEnumerable<SelectListItem> BrandSelectListItem { get; set; }
}
MedicalProductController
public class MedicalProductController : Controller
{
private MvcMedicalStoreDb _db = new MvcMedicalStoreDb();
//
// GET: /MedicalSupply/Edit/5
public ActionResult Edit(int id = 0)
{
MedicalProduct medicalProduct = _db.Products.Find(id);
if (medicalProduct == null)
{
return HttpNotFound();
}
var viewModel = GetMedicalProductViewModel(medicalProduct);
return View(viewModel);
}
public MedicalProductViewModel GetMedicalProductViewModel(MedicalProduct product)
{
var mapper = new MedicalProductMapper(_db);
return mapper.GetMedicalProductViewModel(product);
}
}
MedicalProductMapper
public class MedicalProductMapper
{
private MvcMedicalStoreDb _db;
public MedicalProductMapper(MvcMedicalStoreDb db)
{
_db = db;
}
public MedicalProductViewModel GetMedicalProductViewModel(MedicalProduct source)
{
MedicalProductViewModel viewModel = new MedicalProductViewModel();
var dbBrands = _db.Brands.ToArray();
viewModel.ID = source.ID;
viewModel.Name = source.Name;
viewModel.Price = source.Price;
viewModel.BrandID = source.BrandID;
if (viewModel.BrandID != null)
viewModel.BrandName = dbBrands.SingleOrDefault(b => b.ID == source.BrandID).Name;
var queryBrands = from b in dbBrands
select b;
// BrandSelectListItem is 'null' before this assignment statement executes.
// and Stays null after the statement executes, why?
viewModel.BrandSelectListItem = queryBrands as IEnumerable<SelectListItem>;
return viewModel;
}
}
Edit.cshtml
#model MvcMedicalStore.Models.MedicalProductViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>MedicalProduct</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Price)
#Html.ValidationMessageFor(model => model.Price)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.BrandName)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.BrandName, Model.BrandSelectListItem)
#Html.ValidationMessageFor(model => model.BrandName)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Also, I don't understand why I need to reference the model as 'model'
in the lambda expression, but as 'Model' in the second argument of the
following code segment:
You don't need to reference it as model in the lambda expression. The first part of the lambda (before the => symbol) you are just specifying your parameters and you can name them whatever you want
anything => anything.BrandName
would work the same as using model in place of anything
The lambda expression in this case you can think of it as a method that looks like this
TProperty GetPropertyYouWantToCreateADropdownFor(MedicalPropertyViewModel model)
{
return model.BrandName
}
As for the dropdown, here is a good post explaining how to create a dropdown
How to write a simple Html.DropDownListFor()?
Edit
I plugged in your all your code except your mapper, and just made a little fake implementation of your ViewModel. Your code worked fine.
Here's what I used for my fake controller
var viewModel = new MedicalProductViewModel
{
BrandID = 12,
BrandName = "Some Brand",
ID = 6,
Name = "Some Name",
Price = 12.27,
BrandSelectListItem = new List<SelectListItem>()
{
new SelectListItem() {Text = "Item 1", Value = "1"},
new SelectListItem() {Text = "Item 2", Value = "2"}
}
};
return View(viewModel);
So seeing that this worked, the only thing I can guess is that your problem lies in your Mapper, can you give an example of what viewModel.BrandSelectListItem equals after you get data from the database? Does throwing in fake data work for you?
Edit 2:
queryBrands has to be compatible with SelectListItem if your going to cast it into an IEnumerable<SelectListItem>
You can modify your existing
var queryBrands = from b in dbBrands
select b;
to something like
var queryBrands = dbBrands.Select(b => new SelectListItem()
{
Text = b.PropertyWithWhatYouWantToDisplay,
Value = b.PropertyYouWantAsTheValue,
Selected = //true if you want this item selected, false otherwise
});