Retrieve selected checkboxes in an array into the controller - asp.net-mvc-4

How can i retrieve the selected checkbox in the controller.
This is the main view where the user can choose a request access.
#using (Html.BeginForm("addBatch_CARF", "CARF", FormMethod.Post, new { #name = "register" }))
{
#Html.ValidationSummary(true)
<div id="formAlert" class="alert alert-danger">
<a class="close">×</a>
<strong>Warning!</strong> Make sure all fields are filled and try again.
</div>
var catName = "";
var displayCan = "";
var candidates = "";
for (int i = 0; i < Model.Count; i++)
{
if (catName != Model[i].request_category)
{
<li class="list-group-item list-group-item-success">
#Html.DisplayFor(modelItem => Model[i].request_category)
<span class="pull-right" style="margin-right:60px;">Special Instructions</span>
</li>
catName = Model[i].request_category;
displayCan = catName;
}
if (displayCan == Model[i].request_category)
{
candidates = Model[i].request_name;
<div class="checkbox_request">
#Html.CheckBoxFor(model => model[i].isSelected, new { #class = "is_selected" })
#Html.DisplayFor(model => model[i].request_name)
#if(Model[i].request_name == "Folder Access")
{
<span class="label label-danger">Pls specify all the drive path. Note: For accessing of drives outside PETC please proceed to Online CARF</span>
}
<span class="pull-right">
#Html.EditorFor(model => model[i].special_instruction)
</span>
#Html.HiddenFor(model => model[i].request_type_id)
#Html.HiddenFor(model => model[i].system_roles_id)
</div>
}
}
<li class="list-group-item list-group-item-success">
Access to:
</li>
<div id="employeeAdd">
#{Html.RenderAction("AddRequestor"); }
</div>
<p class="request_btn">
<button type="submit" class="btn btn-primary" id="addbtn">Save</button>
</p>
}
I have only rendered this view AddRequestor in selecting or adding an employee.
<table class="table table-hover">
#for (int i = 0; i < Model.Count; i++){
<tr>
<th>
#Html.CheckBox("checkbox", new { #class = "is_selected" })
#Html.DisplayFor(model => model[i].FullName)
#Html.HiddenFor(model => model[i].Emp_Badge_No)
</th>
</tr>
}
</table>
The main goal of this is all the chosen employees must have also all the chosen request access.
[HttpPost]
public ActionResult addBatch_CARF(List<Request_Type> list, List<Employees_All_vw> emp, string[] checkboxes)
{
foreach (var x in emp)
{
int num = 1;
bool z = Convert.ToBoolean(num);
if (x.checkbox == z)
{
//add data into CARF table
CARF carf = new CARF();
carf.requestor = x.Emp_Badge_No;
carf.carf_type = "BATCH CARF";
carf.created_by = #User.Identity.Name.Remove(0, 9).ToLower();
carf.created_date = System.DateTime.Now;
carf.active_flag = true;
db.CARves.Add(carf);
db.SaveChanges();
int id = carf.carf_id;
//add data into Request Access Table
foreach (var i in list)
{
int val = 1;
bool y = Convert.ToBoolean(val);
if (i.isSelected == y)
{
Request_Access ra = new Request_Access();
ra.request_access_id = 1;
ra.carf_id = id;
ra.request_type_id = i.request_type_id;
ra.special_instruction = i.special_instruction;
ra.ra_assignee = i.system_roles_id;
ra.dept_approval = null;
ra.dept_approval_date = null;
ra.dept_remarks = null;
ra.final_approval = null;
ra.final_approval_date = null;
ra.final_remarks = null;
ra.acknowledge_by = null;
ra.acknowledge_date = null;
ra.journal = null;
ra.closed_by = null;
ra.closed_date = null;
ra.verified_by = null;
ra.verified_date = null;
db.Request_Access.Add(ra);
}
}
db.SaveChanges();
}
TempData["MessageAlert"] = "Successfully created!";
return RedirectToAction("Batch_CARF");
}
}
I've got an error on this line if (x.checkbox == z)
Operator '==' cannot be applied to operands of type 'string[]' and 'bool'

Your parameter string[] checkboxes contains values that are typeof string (either "True" or "False") so you would need to use the Convert.ToBoolean() method before comparing if (x.checkbox == z). However this will not work since #Html.CheckBox("checkbox", ..) generates 2 inputs type="checkbox" with value="True" and a type="hidden" with value="False" so if its checked, both true and false post back and if its unchecked, then only false is posted. There is no way you can possibly match up which values belong to which employee.
Instead create a view model to represent the selection of employees
public class EmployeeVM
{
public string BadgeNumber { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
And then in your AddRequestor() method (assumes you have an Employees table)
public ActionResult AddRequestor()
{
List<EmployeeVM> model = db.Employees.Where(e => e.active_flag).Select(e => new EmployeeVM
{
BadgeNumber = e.Emp_Badge_No,
Name = e.FullName
}.ToList();
return PartialView(model);
}
and in the view
#model List<EmployeeVM>
#for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(m => m[i].BadgeNumber)
<label>
#Html.CheckboxFor(m => m[i].IsSelected)
<span>#Html.DisplayFor(m => m[i].Name)</span>
</label>
}
And finally, in the POST method
[HttpPost]
public ActionResult addBatch_CARF(List<Request_Type> list, List<EmployeesVM> employees)
{
// To get the selected employees
IEnumerable<string> selectedEmployees = employees.Where(e => e.IsSelected);
foreach(EmployeesVM employee in selectedEmployees)
{
....
carf.requestor = employee.BadgeNumber;
....

Related

Update Product Table with subtable. Razor code and update code of controller is working fine but [HTTPPOST] code is not working, giving errors

#foreach (var sprd in ViewBag.subProduct)
{
<div class="form-row control-group row-fluid">
<div class="controls span2">
<select id="text" style="visibility: hidden;"></select>
</div>
<div class="controls span2">
#sprd.subproduct_pricetitle
#Html.Hidden("title1", (string)#sprd.subproduct_pricetitle)
</div>
#Html.Hidden("subid", (int)#sprd.subproduct_id)
<div class="controls span2">
<div class="input-prepend input-append row-fluid">
<span class="add-on prepend ">£ </span>
#Html.TextBox("combined-input1", (decimal)#sprd.subproduct_price, new { #class = "row-fluid" })
</div>
</div>
</div>
}
This is a code for displaying the data on view page.
public ActionResult Update(int id)
{
IEnumerable<producttype_master> Product_Typee;
int producttypeid = Convert.ToInt32(context.product_master.Find(id).product_type.ToString());
Product_Typee = context.producttype_master.ToList();
ViewBag.productType = new SelectList(Product_Typee, "producttype_id", "producttype_name", producttypeid);
IEnumerable<product_master> products;
products = context.product_master.ToList();
//List<subproduct_master> sprdList = context.subproduct_master.Where(m => m.product_id == id).ToList();
IEnumerable<subproduct_master> sprdList = context.subproduct_master.Where(m => m.product_id == id).ToList();
ViewBag.subProduct = sprdList;
return View(context.product_master.Find(id));
}
This update code is not working well, giving error.
[HttpPost]
public ActionResult Update(product_master prdmaster, subproduct_master subprdmaster, FormCollection formCollection)
{
product_master prd = context.product_master.Where(m => m.product_id == prdmaster.product_id).FirstOrDefault();
if (prd != null)
{
prd.product_type = int.Parse(formCollection["PrdType"]);
prd.product_updateby = 1;
prd.product_updateon = DateTime.Now;
prd.product_isactive = "1";
subproduct_master sprdList = context.subproduct_master.Where(m => m.product_id == prd.product_id).FirstOrDefault();
if (sprdList != null)
{
//string latestId = context.product_master.Max(p => p.product_id).ToString();
for (int i = 1; i <= 7; i++)
{
subproduct_master sprdList2 = context.subproduct_master.Where(m => m.subproduct_id == sprdList.subproduct_id).FirstOrDefault();
sprdList2.subproduct_price = decimal.Parse(formCollection["combined-input" + i]);
sprdList2.subproduct_pricevalidity = Convert.ToDateTime(formCollection["datepicker1"]);
sprdList2.subproduct_updatedon = DateTime.Now;
sprdList2.subproduct_updatedby = 1;
sprdList2.subproduct_isactive = "1";
context.Entry(sprdList2).CurrentValues.SetValues(sprdList);
//context.SaveChanges();
sprdList2.subproduct_id++;
}
}
context.Entry(prd).CurrentValues.SetValues(prdmaster);
context.SaveChanges();
}
return View(prdmaster);
}

Some Items of ViewModel get lost between View and controller

the problem is, that my ViewModel has e.g. 12 items. In the Chrome-Browser i can see (Network--> klick on the postback request --> Headers--> Form Data), that all 12 items have modified values, that i want to save in the controller. But in the controller there are just 9 items that have content arriving. Where are the other three? The Capacity of the Model is 16 but the other items from 9 to 15 are set to null.
How can i find out what happens between the view and controller during the postback?
Update
Ok, now i found out that the ModelState doesnt contains all Items, but the Information will be transfered to the controller in the Request --> Form container. Let see, how the missing items will also be transfered to the ModelState...
ViewModel
public class ViewModel
{
public List<tool.Models.Issue> OpenIssue { get; set; }
public List<tool.Models.Issue> AllIssuesExceptOriginal { get; set; }
public List<tool.Models.Issue> ClosedIssue { get; set; }
public tool.Models.Site Site { get; set; }
public int ID { get; set; }
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit( ViewModels.ViewModel ViewModel)
{
//Do something with the content of the ViewModel
}
View (a lot more complex)
#for (int i = 0; i < Model.OpenIssue.Count(); i++)
{
#Html.HiddenFor(modelItem => modelItem.OpenIssue[i].Id);
//a lot more HiddenFor fields
Model.AllIssuesExceptOriginal.Capacity = Model.AllIssuesExceptOriginal.Count;
var History = Model.OpenIssue[i].Histories.Where(p => p.IssueId == Model.OpenIssue[i].Id).OrderByDescending(a => a.LastUpdate).First();
<tr class="Content_table">
<td class="Content_Column">
<div class="Content_all">
<div class="History">#Html.DisplayFor(modelItem => History.Description)</div>
#if( Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Count() != null)
{
for (int a = 0; a < Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Except(Model.AllIssuesExceptOriginal.Where(l=>l.LastUpdate == DateTime.MinValue)).Count(); a++)
{
var OtherIssues = Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Except(Model.AllIssuesExceptOriginal.Where(l=>l.LastUpdate == DateTime.MinValue)).OrderBy(p => p.LastUpdate).ToList();
if(OtherIssues[a].Description != "noUpdate")
{
<div class="updated" style="position:relative" id="#i:#a:Description">
<b>#Html.DisplayFor(modelitem=> OtherIssues[a].User.FirstName) #Html.DisplayFor(modelitem=> OtherIssues[a].User.LastName)</b> <span style="color:grey;">-#Html.ValueFor(modelitem=> OtherIssues[a].LastUpdate, "{0:dd.MM.yy HH:mm}") </span> <br />
#Html.DisplayFor(modelItem => OtherIssues[a].Description, new { #class = "meeting" })
<span style="float:right; "><img src="~/Images/ic_cancel_black_18dp.png" id="Description:#i:#a:#Model.AllIssuesExceptOriginal.FindIndex(p=>p.Id == OtherIssues[a].Id)" onclick="markActiveLinkDelete(this);">
#Html.HiddenFor(modelItem => modelItem.AllIssuesExceptOriginal[Model.AllIssuesExceptOriginal.FindIndex(p=>p.Id == OtherIssues[a].Id)].Description)
</span>
</div>
}
}
}
<div class="updated" >#Html.TextAreaFor(modelItem => modelItem.AllIssuesExceptOriginal[Model.AllIssuesExceptOriginal.FindLastIndex(p=>p.InternalNotes.Replace("Updated:","") == Model.OpenIssue[i].Id.ToString())].Description, new { #class = "meeting" })</div>
#Html.HiddenFor(modelItem=>modelItem.AllIssuesExceptOriginal[Model.AllIssuesExceptOriginal.FindLastIndex(p=>p.InternalNotes.Replace("Updated:","") == Model.OpenIssue[i].Id.ToString())].InternalNotes)
</div>
</td>
}
</table>
</div>
<p>
<input type="submit" value="Save" name = "Save"/>
<input type="submit" value="Cancel" name = "Cancel"/>
</p>
</fieldset>
}
Thanks for your help in advance.
To solve this, i added a Hidden field with the indexer for each item of the Model.
View Updated
#if( Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Count() != null)
{
for (int a = 0; a < Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Except(Model.AllIssuesExceptOriginal.Where(l=>l.LastUpdate == DateTime.MinValue)).Count(); a++)
{
var OtherIssues = Model.AllIssuesExceptOriginal.Where(p => p.InternalNotes.Replace("Updated:", "") == Model.OpenIssue[i].Id.ToString()).Except(Model.AllIssuesExceptOriginal.Where(l=>l.LastUpdate == DateTime.MinValue)).OrderBy(p => p.LastUpdate).ToList();
if(OtherIssues[a].Description != "noUpdate")
{
//content
}
//This is new
#Html.HiddenFor(modelItem => modelItem.AllIssuesExceptOriginal[Model.AllIssuesExceptOriginal.FindIndex(p=>p.Id == OtherIssues[a].Id)].Id)
}
}

How display the last n of records in MVC

i am taking last 4 four comments and want to display in the tooltip,
I am doing the below code but its showing the contents like "System.Collection.Generic.List"
var list = db.PO_Prd_Comments.Where(t => t.PO_TrgCal_ID == item.ID && t.Reply == false).OrderByDescending(t => t.PO_TrgCal_ID).Take(4).ToList();
List<string> comments = new List<string>();
if (list.Count != 0)
{
foreach (var ts in list)
{
comments.Add(ts.PrdComment);
if (list.Count == 1)
{
notify = list.SingleOrDefault().notify;
}
else
{
notify = true;
}
}
}
<td>
<a href="#" onclick="popup4(#CountID)" title="#comments"
<img src="~/Images/comment.GIF"/></a>
</td>
How i display these four comments in the tooltip.
comments is a list of string. You need to convert that to a single string and use that as the title property value.
<a href="#" onclick="popup4(#CountID)" title="#String.Join(Environment.NewLine,comments)">
<img src="~/Images/comment.GIF"/>
</a>

There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key '****'. [duplicate]

This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 4 years ago.
Im trying to do a dropdownlist of Student Enrollments at Student index page.
Student Controller:
public ActionResult Index(string studentEnrollment, string sortOrder, string currentFilter, string searchString, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
ViewBag.CurrentFilter = searchString;
var students = studentService.GetAll();
//var students = from s in studentService.GetAll()
// select s;
var studentViewModel = Mapper.Map<IEnumerable<Student>, IEnumerable<StudentViewModel>>(students);
if (!String.IsNullOrEmpty(searchString))
{
students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper())
|| s.FirstMidName.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{
case "name_desc":
students = students.OrderByDescending(s => s.LastName);
break;
case "Date":
students = students.OrderBy(s => s.EnrollmentDate);
break;
case "date_desc":
students = students.OrderByDescending(s => s.EnrollmentDate);
break;
default:
students = students.OrderBy(s => s.LastName);
break;
}
List<Course> courses = new List<Course>();
SelectList studentEnrollment = new SelectList(courses, "CourseID", "Title");
ViewBag.Courses = studentEnrollment;
//if (!string.IsNullOrEmpty(studentEnrollment))
// students = students.Where(m => m.Course.Title == studentEnrollment);
int pageSize = 3;
int pageNumber = (page ?? 1);
return View(students.ToPagedList(pageNumber, pageSize));
}
View:
#using (Html.BeginForm("Index", "Student", FormMethod.Get))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<p>
Find by name: #Html.TextBox("SearchString", ViewBag.CurrentFilter as string)
Enrollment: #Html.DropDownList("Course", (IEnumerable<SelectListItem>)ViewBag.Courses, "Select Course")
<input type="submit" value="Filter" />
</p>
}
error at line:
Enrollment: #Html.DropDownList("Course", (IEnumerable)ViewBag.Courses, "Select Course")
What Im doing wrong?
I have seen a lot of questions where people have had issues with the drop down list and it was because of the view bag. Everything I have seen says you should try to avoid using ViewBag for drop downs. What I would suggest instead is to put your list in your viewmodel.
Public List<SelectListItem> CourseList { get; set; }
I am not seeing in your code where you are populating your course list. On your controller instead of setting the viewbag set this parameter. Something like
foreach(var temp in CourseList){ //Course list being pulled from the database or wherever that data exists
model.CourseList.Add(new SelectListItem{ Text = temp.Name, Value = temp.Value });
}
then on your view your drop down list would be changed to
#Html.DropDownList("Course", Model.CourseList, "Select Course")

fill #html.dropdownlist from other #html.dropdownlist by same table using ajax

I'm working on some search/filter functionality by using dropdownlists
the question is how can i populate the second dropdownlist by choosing item in first ddl
if all data saved in ont table.
i have table of CarType that has manufacturer, model and year.
when i choose a manufacturer in first ddl the second will filled by models of this manufacturer.
Code i have in Controller:
public ActionResult Search(string manufacturer, string carModel, string searchString, string gear)
{
using (CarTypesLogic logic = new CarTypesLogic())
{
IEnumerable<CarType> allCarTypes = logic.GetAllCarTypes();
var manufacturerList = new List<string>();
var modelList = new List<string>();
var gearList = new List<string>();
var foundManufacturer = from maker in allCarTypes
orderby maker.Manufacturer
select maker.Manufacturer;
var foundModels = from model in allCarTypes
orderby model.Model
select model.Model;
var foundGears = from transmission in allCarTypes
select transmission.Gear;
manufacturerList.AddRange(foundManufacturer.Distinct());
modelList.AddRange(foundModels.Distinct());
gearList.AddRange(foundGears.Distinct());
ViewBag.Manufacturer = new SelectList(manufacturerList);
ViewBag.Gear = new SelectList(gearList);
ViewBag.carModel = new SelectList(modelList);
var foundCars = from car in allCarTypes select car;
if (!String.IsNullOrEmpty(manufacturer))
{
foundCars = foundCars.Where(car => car.Manufacturer == manufacturer);
}
if (!String.IsNullOrEmpty(gear))
{
foundCars = foundCars.Where(car => car.Gear == gear);
}
if (!String.IsNullOrEmpty(searchString))
{
foundCars = foundCars.Where(car => car.Manufacturer.ToLower().Contains(searchString.ToLower()));
}
if (!String.IsNullOrEmpty(carModel))
{
foundCars = foundCars.Where(car => car.Model == carModel);
}
return View(foundCars);
}
}
My cshtml code:
#using (Html.BeginForm())
{
<p>
Manufacturer: #Html.DropDownList("manufacturer", String.Empty)
Model: #Html.DropDownList("carModel",String.Empty)
Gear: #Html.DropDownList("gear", String.Empty)
Free Type: #Html.TextBox("SearchString")
<br />
<input type="submit" value="Search"/>
</p>
}
you need to use Cascaded DropDownList.
here are few examples:
http://mvc4beginner.com/Sample-Code/Cascading-DropDownList/APS-.NET-MVC-Cascading-DropdownLists-Using-LINQ.html
http://code.msdn.microsoft.com/Cascading-DropDownList-in-833683f9/sourcecode?fileId=48387&pathId=451527572
http://www.itorian.com/2013/02/cascading-dropdownlist-in-aspnet-mvc.html