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
}));
Related
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" })
Contoller:
public async Task<ActionResult> GetAssiginee()
{
var AssigineeList = await this.handsService.GetTeamTask();
var content = from p in AssigineeList.Data
orderby p.claimid
select new { p.claimid, p.Assiginee};
var x = content.ToList().Select(c => new List<SelectListItem>
{
new SelectListItem { Text = c.claimid, Value = c.Assiginee},
}).ToList();
ViewBag.FirstName = x;
return View();
}
Model :
public class ClaimDetails
{
public int Assigineeid { get; set; }
public List<ClaimDetails> AssigineeList { get; set; }
public int ID { get; set; }
public string claimid { get; set; }
public string contactID { get; set; }
public string Creator { get; set; }
public string Description { get; set; }
public string status { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string ForensicDueDate { get; set; }
public string ForensicDueTime { get; set; }
public string PatientFirstName { get; set; }
public string PatientLastName { get; set; }
public string Client { get; set; }
public string ProviderName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PreScreen { get; set; }
public string Priority { get; set; }
public string Edit { get; set; }
public string Comment { get; set; }
public string Assiginee
{
get
{
return string.Format("{0} {1}", this.FirstName ?? string.Empty, this.LastName ?? string.Empty).Trim();
}
set
{
}
}
public string Patient
{
get
{
return string.Format("{0} {1}", this.PatientFirstName ?? string.Empty, this.PatientLastName ?? string.Empty).Trim();
}
}
}
}
View DropDown List:
I try for those DropDownList ,but showing Error Message
#Html.DropDownListFor(m => m.FirstName,
new SelectList(ViewBag.FirstName as IEnumerable<SelectListItem> Enumerable.Empty<SelectListItem>(), "claimid", "FirstName"),
"Select Assiginee",
new { #style = "width: 180px;height:30px;", id = "ddlAssiginee", #class = "form-control" })
#Html.DropDownList("dropdownCountry", new SelectList(string.Empty, "claimid", "FirstName"), "Select Assiginee", new { #class = "form-control", #style = "width:250px;" })
#Html.DropDownListFor(model => model.ID, ViewBag.FirstName as IEnumerable<SelectListItem>)
#Html.DropDownList("ddldepartmentlist", ViewBag.FirstName as IEnumerable<SelectListItem>)
JavsScript Function:
<script language="javascript" type="text/javascript">
$(function () {
$.ajax({
type: "GET",
url: "/TeamTaskScreen/GetAssiginee",
datatype: "Json",
success: function (data) {
$.each(data, function (index, value) {
$('#ddldepartmentlist').append('<option value="' + value.claimid + '">' + value.FirstName + '</option>');
debugger;
});
}
});
});
</script>
values are coming in Contoller but I Got Error Message in DropDownList
There is no Viewdata item of type IEnumerable<SelectListItem> that has the key
Please help any one.
ViewBag works when you set it in a GET action and try to access it in the view returned by that action method. But in your code, you are making an ajax call to get the data for the dropdown. Your ajax call's success method is expecting an array of items each with claimId and FirstName, but currently you server method is trying to return a view result!
Your view is expecting the a ViewBag item with name FirstName which has the collection of SelectListItems to render the SELECT element options. That means you need to set this ViewBag item in the GET Action method which returns this view, not in some other action method called by an ajax call.
So update your GET action to set this data.
public ActionResult Create()
{
// your existing code to load content collection here
var x = content.Select(c => new List<SelectListItem>
{
Text = c.claimid,
Value = c.Assiginee},
}).ToList();
ViewBag.FirstName = x;
return View();
}
Another option is to simply use the Ajax method. For this, you may return the data in JSON format from your GetAssiginee method.
public async Task<ActionResult> GetAssiginee()
{
var AssigineeList = await this.handsService.GetTeamTask();
var content = from p in AssigineeList.Data
orderby p.claimid
select new { p.claimid, p.Assiginee};
var x = content.Select(c => new claimid= c.claimid,
FirstName= c.Assiginee}).ToList();
return Json(x,JsonRequestBehavior.AllowGet);
}
The above code will return a json array like below
[
{ "claimid":"1","FirstName":"Some Name"},
{ "claimid":"2","FirstName":"Some Other Name"}
]
and your current js code will be able to loop through the array and append options to the select element.
Now since you are populating the data via ajax, no need to use VieBag. Simple replace
#Html.DropDownList("ddldepartmentlist", ViewBag.FirstName as IEnumerable<SelectListItem>)
with
<SELECT name="ddldepartmentlist"></SELECT>
In my Model I have IEnumerable, and due to this I cannot use for loop in view. If I use foreach the Html generated doesn't have indexing, which is what I need. How do I solve this problem.
I'm trying to use same view model to create and edit and I'm having problem in the edit part.
public class CreateModule
{
//Empty form to handle form serialization
public CreateModule()
{
}
public long Id { get; set; }
[Required]
public string ModuleId { get; set; }
[DataType(DataType.DateTime)]
public DateTime DateEntered { get; set; }
public string KindName { get; set; }
public string TypeName { get; set; }
public string SelectedModuleTypeName { get; set; }
public IEnumerable<SelectListItem> TypeNames { get; set; }
public IEnumerable<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
Here is my view where I have used both for and foreach, but I have commented for as I cannot use indexing in it currently
#*
#for (int i = 0; i < Model.Properties.Count(); i++)
{
<label class="label">#Model.Properties[i].Value</label>
<div class="input-block-level">#Html.TextBoxFor(model => Model.Properties[i].Value, new { #value = Model.Properties[i].Value })</div>
}
*#
#foreach (var properties in Model.Properties)
{
<div class="label">#properties.Name</div>
<div class="input-block-level">#Html.TextBoxFor(model => properties.Value, new { #value = properties.Value })</div>
<br/>
}
Currently Html.Textbox for generates following two names which doesn't have indexing in it
properties.value
because of this the values that are submitted during the post are Null. If I use for loop then I think my properties.value will change to properties[0].value and properties[1].value??? I'm not sure, but that is what I'm trying to achieve.
If I change my model from
public IEnumerable<Property> Properties { get; set; }
to
public List<Property> Properties { get; set; }
then my following method in repository would not work as it reutrns IQueryable for value properties, and casting from IQueryable to List would not be possible.
public CreateModule GetModuleDetails(long id)
{
var module = (_dbSis.Modules.Where(t => t.Id == id).Select(m => new CreateModule
{
Id = id,
ModuleId = m.ModuleId,
TypeName = m.ModuleType.TypeName,
KindName = m.ModuleType.ModuleKind.KindName,
Properties = m.PropertyConfiguration.PropertyInstances.Select(
x => new Property { Name = x.Property.Name, Value = x.Value })
}));
return (module.FirstOrDefault());
}
Create a partial view like below, name it Property.cshtml, and put it under Views/Shared/EditorTemplates.
#model MyApp.Models.Property
<div class="label">#Model.Name</div>
<div class="input-block-level">#Html.TextBoxFor(model => Model.Value)</div>
<br/>
Then, replace the foreach loop in your View with this:
#EditorFor(model => model.Properties)
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...
I read that EditorTemplates are loaded automatically, but from asp.net mvc 2 and now 3 with razor, I still cant get this to work.
My model looks like this:
public class RoleViewModel
{
public int RoleId { get; set; }
public bool InRole { get; set; }
public string RoleName { get; set; }
}
public class UserViewModel
{
public User User { get; set; }
public IEnumerable<RoleViewModel> Roles { get; set; }
}
My view looks like this:
~/Views/Roles/Edit.cshtml
#model Project.Web.ViewModel.UserViewModel
#using (Html.BeginForm()) {
#Html.EditorFor(model => model.Roles)
<!-- Other stuff here -->
}
~/Views/Roles/EditorTemplates/RoleViewModel.cshtml
#model Project.Web.ViewModel.RoleViewModel
#foreach (var i in Model)
{
<div>
#i.RoleName
#Html.HiddenFor(model => i.RoleId)
#Html.CheckBoxFor(model => i.InRole)
</div>
}
If i move the content from the EditorTemplate to the actual page, then it works, it shows the checkbox, etc. But with this current setup, all that shows up is the count of the number of roles.
What am I doing wrong?
~/Views/Roles/EditorTemplates/RoleViewModel.cshtml
#model MvcApplication16.Controllers.RoleViewModel
<div>
#Model.RoleName
#Html.HiddenFor(m => m.RoleId)
#Html.CheckBoxFor(m => m.InRole)
</div>
~/Views/Roles/Edit.cshtml
#model MvcApplication16.Controllers.UserViewModel
#using (Html.BeginForm()) {
#Html.EditorFor(m => m.Roles)
<!-- Other stuff here -->
}
Models
public class UserViewModel {
public User User { get; set; }
public IEnumerable<RoleViewModel> Roles { get; set; }
}
public class RoleViewModel {
public int RoleId { get; set; }
public bool InRole { get; set; }
public string RoleName { get; set; }
}
public class User {
public string Name { get; set; }
}
Controller
public ActionResult Edit() {
return View(
new UserViewModel() {
User = new User() { Name = "Test" },
Roles = new List<RoleViewModel>() {
new RoleViewModel() {
RoleId = 1,
InRole = true,
RoleName = "Test Role" }}
});
}
The above code works just fine. Compare it with yours and see if you see anything amiss :)