ASP.NET MVC DropDownListFor Model binding - asp.net-mvc

I am trying to bind a dropdown to my model, but I am having issues. My model that is passed into my HttpPost function is NULL, but only if I try to bind to the "product" object's CategoryID field. If I exclude trying to bind to product.CatgeoryID, then the IncidentNumber string is not null. Thanks for any input.
Here is my model.
public class BIFireTypeModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Product
{
public int CategoryID { get; set; }
public Product()
{
CategoryID = 0;
}
}
And here is my controller:
//
// GET: /BasicIdentification/
[HttpGet]
public ViewResult BasicIdentificationIndex()
{
Product newproduct = new Product();
ViewModelData vmd = new ViewModelData();
vmd.product = newproduct;
vmd.product.CategoryID = 2;
ViewBag.Categories = GetItems();
return View(vmd);
}
[HttpPost]
public ActionResult BasicIdentificationIndex(ViewModelData product)
{
ViewBag.Categories = GetItems();
return View(product);
}
public List<BIFireTypeModel> GetItems()
{
List<BIFireTypeModel> categories = new List<BIFireTypeModel>();
categories.Add(new BIFireTypeModel() { ID = 1, Name = "IA" });
categories.Add(new BIFireTypeModel() { ID = 2, Name = "Extended Attack" });
categories.Add(new BIFireTypeModel() { ID = 3, Name = "Large Fire Support" });
return categories;
}
public class ViewModelData
{
public String IncidentNumber { get; set; }
public Product product { get; set; }
}
And finally my cshtml:
#{
using (Html.BeginForm())
{
<h4>Incident Number</h4><input id="txtIncidentNumber" name="IncidentNumber" type="text" />
#Html.DropDownListFor(x => x.product.CategoryID, new SelectList(ViewBag.Categories, "ID", "Name"))
#* WILL CAUSE IncidentNumber in BasicIdentificationIndex(ViewModelData product) TO BE NULL
<h4>Incident Number</h4><input id="afasf" name="product.CategoryID" type="text" />
*#
<input type="submit" value="Submit" />
}
}
EDIT
In my Post function, I can access product.CategoryID with Request[] like so:
[HttpPost]
public ActionResult BasicIdentificationIndex(ViewModelData product)
{
String tmp = Request["product.CategoryID"];
ViewBag.Categories = GetItems();
return View(product);
}
And it returns the right value. But this value will not bind in my model, and if I try to use DropDownListFor at all with product, ALL VALUES in ViewModelData product will be null.

FIXED:
Here is the issue.
public ActionResult BasicIdentificationIndex(ViewModelData product)
public class ViewModelData
{
public Employee product { get; set; }
}
The NAME of my object in my ViewModelData was the same as the PARAMETER in BasicIdentificationIndex(). This caused major issues. All I had to do was change the name.
EDIT:
Something else that is very IMPORTANT is that when I was using EditorForModel(), my dropdowns weren't binding, but when I would manually create them with #Html.EnumDropDownListFor the binding worked. Good to know.

Here is an example approach that populates three DropDownListFor at the same View:
ViewModel:
public class GroupViewModel
{
public IEnumerable<SelectListItem> Schedules { get; set; }
public int ScheduleId { get; set; }
public IEnumerable<SelectListItem> Labs { get; set; }
public int LabId { get; set; }
public IEnumerable<SelectListItem> Terms { get; set; }
public int TermId { get; set; }
}
Controller:
public ActionResult Create()
{
//Populate DropDownList binding values
var model = new GroupViewModel
{
//Preselect the Lab with id 2
//LabId = 2,
Labs = repository.Labs.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Terms = repository.Terms.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Schedules = repository.Schedules.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
})
};
return PartialView("_Create", model);
}
View:
#Html.DropDownListFor(m => m.LabId, new SelectList(Model.Labs, "Value", "Text"),
"Select", new { #class = "selectpicker" })
#Html.DropDownListFor(m => m.ScheduleId, new SelectList(Model.Schedules, "Value", "Text"),
"Select", new { #class = "selectpicker" })
#Html.DropDownListFor(m => m.TermId, new SelectList(Model.Terms, "Value", "Text"),
"Select", new { #class = "selectpicker" })
Hope this helps...

Related

ASP.NET MVC EditorFor and DateTime default value

I want to set default value for an EditorFor HTML helper but just the helper text is displayed in it. Why EditorFor does not let me to set its default value, please?
class Person {
public int Id { get; set; }
public DateTime DateOfBirth { get; set; }
...
}
class PersonVM {
public Person { get; set; }
...
}
public ActionResult Edit(int id)
{
var vm = new PersonVM ();
vm.Person = db.Persons.Where(x => x.Id == id).FirstOrDefault();
...
return View(vm);
}
#model Project.Models.PersonVM
#Html.EditorFor(model => model.Person.DateOfBirth , new { htmlAttributes = new { #class = "form-control" } })
Set the default value by assigning a value to the model property.
Either in the Controller Action:
public ActionResult Edit(int id) {
var vm = new PersonVM ();
vm.Person = db.Persons.Where(x => x.Id == id).FirstOrDefault();
if (vm.Person.DateOfBirth == default(DateTime)) {
vm.Person.DateOfBirth = new DateTime(1900, 01, 01); // default value
}
// ...
return View(vm);
}
Or in the ViewModel (make sure that you only map valid DateOfBirth from the DB to the ViewModel):
public class PersonVM {
public PersonViewModel () {
DateOfBirth = new DateTime(1900, 01, 01); // default value
}
public int Id { get; set; }
public DateTime DateOfBirth { get; set; }
// ...
}

Populate DropDownList in ASP.NET MVC from database table using Entity Framework 6 and ViewModel

I have been scratching my head for a whole night on an issue I can do quickly using ajax/jquery and stored procedures. I want to
1) Populate a drop down list from values obtained from a database table using Entity Framework and view model. I DO NOT WANT TO USE VIEWBAG OR VIEWDATA. Any help appreciated.
2) How can I generate a Create View using the View Model with the all the default fields ? The scaffholding works on a model but not on a view model ?
MY MODELS
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public string Level { get; set; }
public int DepartmentId { get; set; }
}
public class Grade
{
public int ID { get; set; }
public string Level { get; set; }
}
View Model
public class GradeSelectListViewModel
{
public Employee Employee { get; set; }
public IEnumerable<SelectListItem> Grades { get; set; }
public GradeSelectListViewModel(Employee employee, IEnumerable grades)
{
Employee = employee;
Grades = new SelectList(grades, "Grade", "Name", employee.Level);
}
}
MY CONTEXT CLASS
public class EmployeeContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Grade> Grades { get; set; }
}
MY CONTROLLER
public ActionResult Edit (int? id)
{
using (var db = new EmployeeContext())
{
var model = new GradeSelectListViewModel(db.Employees.Find(id), db.Grades);
//model.Employee = db.Employees.Single(x => x.EmployeeID == id);
model.Grades = db.Grades.ToList().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Level
});
return View(model);
}
}
MY RAZOR PAGE CSHTML
#model MVCDemo.ViewModels.GradeSelectListViewModel
....
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
....
#Html.DropDownListFor(x => Model.Employee.Level,
new SelectList(Model.Grades, "ID", "Level"),
"Select Level")
....
<input type="submit" value="Create" class="btn btn-default" />
}
The main issue is that in the view you have new SelectList(Model.Grades, "ID", "Level") but Grades is IEnumerable<SelectListItem> and SelectListItem does not contain properties named ID and Level.
However there are a a few other issues with your code. First a view model should not contain a data model, and instead your view model should be
public class GradeSelectListViewModel
{
public int? ID { get; set; } // make this ID so you do not need an input for it
public string Name { get; set; }
.... // other properties of Employee that your editing
[Required(ErrorMessage = "..")]
public int? Level { get; set; } // make value types nullable to protect against under-posting attacks
public IEnumerable<SelectListItem> Grades { get; set; }
}
and add display and validation attributes as required. Note that I deleted the constructor (you don't seem to be using it, but if you did, then you also need to include a parameter-less constructor, otherwise an exception will be thrown when submitting to the POST method. I also assume that Level should be typeof int since you binding to the int ID property of Grade.
The the code in your GET method should be
Employee employee = db.Employees.Find(id);
var model = new GradeSelectListViewModel()
{
ID = employee.EmployeeID,
Name = employee.Name,
Level = employee.Level, // convert to int?
....
Grades = db.Grades.Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Level
})
};
return View(model);
and in the view
#Html.DropDownListFor(x => Model.Level, Model.Grades, "Select Level")
Note also that in the POST method, your need to reassign the SelectList if you return the view because ModelState is invalid.
You can use the following approach that populates three DropDownListFor at the same View:
ViewModel:
public class GroupViewModel
{
public IEnumerable<SelectListItem> Schedules { get; set; }
public int ScheduleId { get; set; }
public IEnumerable<SelectListItem> Labs { get; set; }
public int LabId { get; set; }
public IEnumerable<SelectListItem> Terms { get; set; }
public int TermId { get; set; }
}
Controller:
public ActionResult Create()
{
//Populate DropDownList binding values
var model = new GroupViewModel
{
//Preselect the Lab with id 2
//LabId = 2,
Labs = repository.Labs.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Terms = repository.Terms.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
}),
Schedules = repository.Schedules.Select(c => new SelectListItem
{
Value = c.Id.ToString(),
Text = c.Name
})
};
return View("Create", model);
}
View:
#Html.DropDownListFor(m => m.LabId, new SelectList(Model.Labs, "Value", "Text"),
"Select", new { #class = "selectpicker" })
#Html.DropDownListFor(m => m.ScheduleId, new SelectList(Model.Schedules, "Value", "Text"),
"Select", new { #class = "selectpicker" })
#Html.DropDownListFor(m => m.TermId, new SelectList(Model.Terms, "Value", "Text"),
"Select", new { #class = "selectpicker" })

How to add extra item in asp .net mvc dropdownlist from controller

I am using ViewModel to create view in my asp .net MVC application. In this view I need to bind a dropdownlist (Successfully binded).
Problem: I want to add extra items with value in dropdownlist like "select","0"
Here is my Viewmodel:
public class PagesViewModel
{
public int Id { get; set; }
[Required]
[Display(Name = "Page Name")]
public string PageName { get; set; }
[Display(Name = "Parent Page")]
public IEnumerable<Page> Page { get; set; }
}
My Controller:
public ActionResult Create()
{
var model = new PagesViewModel
{
Page = db.Pages.Where(s => s.IsActive == true).OrderBy(r => r.PageName)
};
//--- Here I need to add extra items manually
return View(model);
}
My View:
#Html.DropDownListFor(model => model.Id, new SelectList(Model.Page, "Id", "PageName"), "Select Parent Page", htmlAttributes: new { #class = "form-control" })
There is an overload for the DropDownListFor helper that allows you to specify an option label - I assume that is what you are after.
#Html.DropDownListFor(m => m.SomeID, Model.SomeSelectList, "Select one...", new { #class="your-class-here" })
This will render a <option> element with a value="" attribute:
<select id="SomeId" name="SomeId" class="your-class-here">
<option value="">Select one...</option>
<!-- ... the rest of the items from the SelectList -->
</select>
Otherwise, your Pages property needs to be something that derives from ICollection (like a List), which will allow you to add items:
Model:
public class PagesViewModel
{
public int Id { get; set; }
[Required]
[Display(Name = "Page Name")]
public string PageName { get; set; }
[Display(Name = "Parent Page")]
public ICollection<Page> Page { get; set; }
}
Controller:
public ActionResult Create()
{
var model = new PagesViewModel
{
Page = db.Pages.Where(s => s.IsActive == true)
.OrderBy(r => r.PageName)
.ToList()
};
model.Pages.Add(new Page{ /* ... object initializers here */ });
return View(model);
}
try this
var model = new PagesViewModel
{
Page = db.Pages.Where(s => s.IsActive == true).OrderBy(r => r.PageName)
};
model.Page.Add(new Page{ Name='ABC' ... }) // You can define your properties here
public ActionResult Create()
{
var model = new PagesViewModel
{
Page = db.Pages.Where(s => s.IsActive == true).OrderBy(r => r.PageName)
};
List<SelectListItem> listItem = new List<SelectListItem>();
foreach(var item in Model)
{
listItem.Add(new SelectListItem{Text = item.PageName, Value=item.Id});
}
listItem.Add( new SelectListItem{Text = "SomeText", Value="Some Value"});
//--- Here I need to add extra items manually
return View(model);
}
you can also insert your optional text at top by linq extension method Insert(index, ValueToBeInserted). index will be zero if you want insert at top.
Please mark as anser if helped.

How to use a View Model to populate a Drop Down list

I'm currently using a ViewBag to pass data to the DropDown list.
I want to use a model instead but I can't get it to work. Here is what I have :
public ActionResult Index(int? catID)
{
GiftListItems viewModel = new GiftListItems
{
Categories = **how do I use this property for DropDown list ?**
};
// using this for DropDown list now :
var query = _categoryRepository.Table
.Select(x => new { x.Id, x.Name })
.Distinct()
.OrderBy(x => x.Name);
ViewBag.Values = new SelectList(query.AsEnumerable(), "Id", "Name");
return View(viewModel);
}
In View :
#Html.DropDownList("catID", (SelectList)ViewBag.Values, new { onchange = "this.form.submit();" })
Model :
public class GiftListItems
{
public IEnumerable<Category> Categories { get; set; }
}
Is this easy to do? Thanks
public class Model
{
public int SelectedItem{get;set;}
public IList<DropDownObj> ListObj{get;set;
public IList<SelectListItem> SelectListItemListObj{get;set;}
{
get
{
var list = (from item in ListObj
select new SelectListItem()
{
Text = item.Id.ToString(CultureInfo.InvariantCulture),
Value item.Name
}).ToList();
return list;
}
set{}
}
}
public class DropDownObj
{
public int Id{get;set;}
public string Name{get;set;
}
usage:
#Html.DropDownListFor(c=>c.SelectedItem,Model.SelectListItemListObj)
Example:
Models:
public class VmSysCategoryModel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class GiftListItemsDropDown
{
public int SelectedCategoryId { get; set; }
public IEnumerable<VmSysCategoryModel> Categories { get; set; }
public IList<SelectListItem> SelectListItemListObj
{
get
{
var list = (from item in Categories
select new SelectListItem()
{
Text = item.Id.ToString(CultureInfo.InvariantCulture),
Value=item.Name
}).ToList();
return list;
}
set { }
}
}
Controller:
public ActionResult Index(int? catID)
{
var listCategories = _categoryRepository.Table
.Select(x => new {x.Id, x.Name})
.Distinct()
.OrderBy(x => x.Name);
var obj = new GiftListItemsDropDown()
{
Categories = Mapper.Map<IList<listCategories>, IList<VmSysCategoryModel>>(listCategories)
//here you mast to map from domain to viewmodel
};
return View(obj);
}
View:
#model GiftListItemsDropDown
#Html.DropDownListFor(c=>c.SelectedCategoryId ,Model.SelectListItemListObj)
You can use the view model like this -
public ActionResult NewsEdit(int ID, dms_New dsn)
{
var query = _categoryRepository.Table
.Select(x => new { x.Id, x.Name })
.Distinct()
.OrderBy(x => x.Name)).ToList();
GiftListItems viewModel = new GiftListItems
{
Categories = query.Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name
})
};
return View(viewModel);
}
and in your view -
#model GiftListItems
#Html.DropDownList(
"catID",
Model.Categories,
new { onchange = "this.form.submit();" }
)
And your View model now should look like this -
public class GiftListItems
{
public IEnumerable<SelectListItem> Categories { get; set; }
// public IEnumerable<Category> Categories { get; set; } --
}

ASP.NET MVC post a dropdownlist

When I post via the click on "btSave", in the controller I receive the model. In the model, I see the value off all fields (I show here only "FirstName" but there are others). But the doropdownlist value are null all the time.
Do you have an idea why ?
Thanks,
//Dropfown content
public class LkpTypeCompany
{
public virtual int Id { get; set; }
public virtual int Code { get; set; }
public virtual string NL { get; set; }
public virtual string FR { get; set; }
public virtual string Value { get; set; }
}
//Model Definition
public class CustomerModel
{
public List<LkpTypeCompany> LkpTypeCompany { get; set; }
public Customer Customer { get; set; }
}
//Posting form
jQuery('#btGeneralSave').click(function (event) {
var jqxhr = $.post("Controller/Actio,", $("form").serialize(),
function (data) {
});
});
//HTML
#model eSIT.GC.WebUI.Models.CustomerModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.Customer.FirstName, new { maxlength = 50 })
#Html.DropDownListFor( m => m.Customer.LkpTypeCompany, new SelectList(Model.LkpTypeCompany, "Code", "FR", Model.Customer.LkpTypeCompany.Code))
<input type="button" id="btSave" value="Save"/>
}
I see the overload that you were attempting to use but I have had good luch with using SelectListItem
Try
#Html.DropDownListFor( m => m.Customer.LkpTypeCompany,
new SelectList(Model.LkpTypeCompany
.Select(i => new SelectListItem
{
Text = i.Code,
Value = (*somecondition*) ? i.FR : i.NL,
Selected = i.Code == Model.Customer.LkpTypeCompany.Code
}));

Resources