Html Helper for <ICollection> - c#

I have a view model that has a of items that are equipment for a session and I want to create a new session but I am not sure how to use a HTML helper to achieve this, here is the view model:
public class SessionInsertViewModel
{
public string Title { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Duration { get; set; }
public string Difficulty { get; set; }
public string Equipment { get; set; }
public virtual ICollection<Product> Products { get; set; }
public int ClassId { get; set; }
}
and here is the Form on my view:
#using (Html.BeginForm(MVC.Session.Insert(), FormMethod.Post, new { #class = "form label-inline", name = "iform", enctype = "multipart/form-data", id = "Insert" }))
{
#Html.HiddenFor(model => model.ClassId)
<div class="formSep">
<label class="req">Session Name</label>
<div style="color:red;display:none" id="reqTitle">This Field is required to create a Session</div>
#Html.EditorFor(model => model.Title, new { #class = "medium", id="Title"})
</div>
<div class="formSep">
<span style="color:red">#Html.ValidationMessageFor(model => model.Description)</span>
<label class="req">Description</label>
<div style="color:red;display:none" id="reqDesc">This Field is required to create a Session</div>
#Html.TextAreaFor(model => model.Description,new{style="width: 420px; height: 6em;"})
</div>
<div class="formSep">
<table>
<tr>
<th style="text-align:left"><span>Date</span></th>
<th style="text-align:left"><div>Time</div></th>
</tr>
<tr>
<th style="padding-right: 20px;"><input id="StartDate" type="text" style="width:120px" /></th>
<th><input id="Hour" value="12:00" type="text" style="width:67px" /></th>
</tr>
</table>
</div>
<div class="formSep">
<label class="req">Duration (In Minutes)</label>
#Html.EditorFor(model => model.Duration, new { #class = "medium", id = "Duration" })
</div>
<div class="formSep">
<label class="req">Difficulty</label>
#Html.DropDownListFor(model => model.Difficulty, new SelectList(new List<Object> { new { value = "Easy", text = "Easy" }, new { value = "Medium", text = "Medium" }, new { value = "Difficult", text = "Difficult" } }, "value", "text", #Model.Difficulty), new { id="Difficulty" })
</div>
</div>
}
So I need to be able to select a list of Equipment in the form and send it with the ViewModel to the controller but I am not sure how to do this.

Save the possible options for the dropdowns in the Model, not in the View.
Then you can pass them the other way (so from Controller > Model > View).
Sample:
Model:
public class SessionInsertViewModel
{
// existing code
public List<Difficulty> Difficulties { get; set; }
}
View:
#Html.DropDownListFor( model => model.Difficulty
, new SelectList( Model.Difficulties
, "Text"
, "Value"
)
)

Related

Why is the DepartmentID value not being properly bound to the view model's property?

Not sure why but the for some reason the view model is not binding the DepartmentId when I hit the submit button, I get an error:
Value cannot be null.
Parameter name: value
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Not sure which value is being null as the code does not break, rather after hitting the submit button that is the message that is being displayed.
I'm assuming it's the departmentId that's not being properly bound to the DepartmentID property in CoursePreReqViewModel.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: value
View:
#using (Html.BeginForm("Catalog", "Courses", FormMethod.Post, new { #class = "pure-form pure-form-aligned" }))
{
#Html.AntiForgeryToken()
<div class="row">
<div class="col">
<input id="myInput" class="form-control" type="text" placeholder="Search..">
</div>
<div class="col">
#Html.LabelFor(model => model.DepartmentId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownListFor(model => model.DepartmentId, Model.DepartmentList, "Department", new { #class = "form-control required", id = "department-list" })
#Html.ValidationMessageFor(model => model.DepartmentId)
</div>
<div class="col">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
}
Controller:
[HttpPost]
public ActionResult Catalog(CoursePreReqViewModel viewModel)
{
DepartmentRepo dRepo;
CoursesRepo cRepo;
MajorPreRequisitesRepo reqRepo;
using (context)
{
dRepo = new DepartmentRepo(context);
cRepo = new CoursesRepo(context);
viewModel.PopulateDepermentSelectList(dRepo.GetAllDepartments());
reqRepo = new MajorPreRequisitesRepo(context);
viewModel.Courses = cRepo.GetAllCoursesAndPreReqsByDepartment(viewModel.DepartmentId);
}
return View(viewModel);
}
View model:
public class CoursePreReqViewModel
{
[Required]
[Display(Name = "")]
public int DepartmentId { get; set; }
public IList<Course> Courses { get; set; }
public IList<MajorPreRequisite> CoursesAndPreReqs { get; set; }
[Display(Name = "Department: ")]
public IList<Department> Departments { get; set; }
public CoursePreReqViewModel() { }
public SelectList DepartmentList
{
get
{
return new SelectList(Departments, "Id", "Name");
}
}
public void PopulateDepartmentSelectList(IList<Department> populatedDepartments)
{
Departments = populatedDepartments;
}
}
Sarthak here is another answer: this is the asp.net mvc fiddler https://dotnetfiddle.net/ARdtvr
!!!Display Name needs to be a value!!!
I can help you keep the code you have, and answer your question.
controller/classes:
public class Course
{
public int CourseId { get; set; }
}
public class MajorPreRequisite
{
public int MajorPreRequisiteId { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CoursePreReqViewModel
{
//Make sure to comment this out -or- put this field in view
//try this first with your code, before you change code eg using a dictionary
//[Required]
//[Display(Name = "")]
public int DepartmentId { get; set; }
public IList<Course> Courses { get; set; }
public IList<MajorPreRequisite> CoursesAndPreReqs { get; set; }
[Display(Name = "Department: ")]
public IList<Department> Departments { get; set; }
public CoursePreReqViewModel() { }
public Dictionary<string, string> DepartmentList { get; set; }
public void GetAllCoursesAndPreReqsByDepartment(IList<Course> populateCourses)
{
Courses = populateCourses;
}
}
public class HomeController : Controller
{
[HttpPost]
public ActionResult Catalog(CoursePreReqViewModel viewModel)
{
//Put a breakpoint herre to see departmentid of user choice
return View();
}
public ActionResult Index11()
{
CoursePreReqViewModel viewModel = new CoursePreReqViewModel();
Dictionary<string, string> depts = new Dictionary<string, string>();
depts.Add("1", "deptOne");
depts.Add("2", "deptTwo");
viewModel.DepartmentList = depts;
IList<Course> courses = new List<Course>();
courses.Add(new Course { CourseId = 1 });
courses.Add(new Course { CourseId = 2 });
viewModel.GetAllCoursesAndPreReqsByDepartment(courses);
return View(viewModel);
}
view:
#model WebApplication4what2.Controllers.CoursePreReqViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index11</title>
</head>
<body>
#using (Html.BeginForm("Catalog", "Home", FormMethod.Post, new { #class = "pure-form pure-form-aligned" }))
{
<div class="row">
<div class="col">
<input id="myInput" class="form-control" type="text" placeholder="Search..">
</div>
<div class="col">
#Html.LabelFor(model => model.DepartmentId, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.DropDownListFor(model => model.DepartmentId, new SelectList(Model.DepartmentList, "Key", "Value"), Model.DepartmentId)
#Html.ValidationMessageFor(model => model.DepartmentId)
</div>
<div class="col">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
}
</body>
</html>

How to bind an object in a view to the controller?

This may be a dumb question but I'm kind of new with the razor. I'm trying to create a dynamic form. I have a list of object of fields and show them dynamically in my page. But, when I want to save the selected value of my field for a dropdown(example), I don't know how to save the object of my foreach to my model in the controller (I can save my value with no harm).
Index.cshtml:
<div class="row">
#foreach (var buildingBlock in buildingBlocks)
{
<div class="col-sm">
<div class="card">
<div class="card-body">
<h5 class="card-title">#buildingBlock.BuildingBlockTitle</h5>
#foreach (Test.Test.Models.BuildingBlockField buildingBlockField in buildingBlockFields)
{
<div class="form-group">
<label for="companyName">Company Name</label>
//I tried that but it's not working (Obviously :))
#Html.EditorFor(model => buildingBlockField)
#Html.DropDownListFor(model => model.buildingBlockFields[0].Values, buildingBlockField.OptionDetails, "Select Contract", new { #class = "selectpicker", multiple = "multiple" })
</div>
}
</div>
</div>
</div>
}
</div>
BuildingBlockField:
public class BuildingBlockField
{
public int BuildingBlockFieldID{ get; set; }
public int BuildingBlockID { get; set; }
public List<SelectListItem>? OptionDetails { get; set; }
public string FieldTitle { get; set; }
public FieldType Type { get; set; }
public bool IsMultiple { get; set; }
public int[] Values { get; set; }
public string Value { get; set; }
}
model controller:
public class ContractInformationsModel
{
public List<BuildingBlockField> buildingBlockFields { get; set; }
}
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.BuildingBlocks = Models.BuildingBlock.getBuildingBlocks();
ViewBag.BuildingBlockFields = Models.BuildingBlockField.getBuildingBlockFields();
return View();
}
[HttpPost]
public ActionResult generateWordContract(ContractInformationsModel contractInformations)
{
return View("Index");
}
}
I expect to find in my controller object contractInformations to find a list of buildingBlockFields with all the information and not only the value.
Thank you
Edit :
This seems to work but i have to do it for every property and hide then. Is there any other solution ?
#for (var i = 0; i < buildingBlockFields.Count(); i++){
<div class="form-group">
#Html.HiddenFor(model => model.buildingBlockFields[i].BuildingBlockFieldID, new { Value = buildingBlockFields[i].BuildingBlockFieldID })
#Html.HiddenFor(model => model.buildingBlockFields[i].FieldTitle, new { Value = buildingBlockFields[i].FieldTitle })
#Html.HiddenFor(model => model.buildingBlockFields[i].Type, new { Value = buildingBlockFields[i].Type })
#Html.DropDownListFor(model => model.buildingBlockFields[0].Values, buildingBlockFields[i].OptionDetails, "Select Contract", new { #class = "selectpicker", multiple = "multiple" })
</div>
}
Since you are passing ContractInformationsModel model to your view, which has a list of type BuildingBlockField, your html should contain the building block field ID and a "counter" that can identify indexes in that list.
#{
// declare counter
int i = 0
}
#foreach (BuildingBlockField buildingBlockField in buildingBlockFields)
{
<div class="form-group">
<label for="companyName">#buildingBlockField.FieldTitle</label>
#Html.HiddenFor(model=>model.buildingBlockFields[i].BuildingBlockFieldID)
#Html.TextBoxFor(model => model.buildingBlockFields[i].FieldTitle, new { #class = "form-control", Value = #buildingBlockField.FieldTitle })
#Html.DropDownListFor(model => model.buildingBlockFields[i].Values, buildingBlockField.OptionDetails, "Select Contract", new { #class = "selectpicker", multiple = "multiple" })
</div>
#i++
}

I want to apply for-each loop on two models at same time Asp.Net MVC

I want to apply for each loop on two models at the same time.
My Controller Action Is:
public ActionResult MarkAttendance(int id)
{
var students = _context.Students.Where(c => c.ClassId == id).ToList();
var status = _context.Statuses.ToList();
var viewModel = new AttendanceViewModel
{
Student = students,
Status = status
};
return View(viewModel);
}
My Student Model is
public class Student
{
public int Id { get; set; }
[Required]
[StringLength(30)]
[RegularExpression(#"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
public string Name { get; set; }
[Required]
[StringLength(30)]
[RegularExpression(#"^[A-Za-z\s]{1,}[\.]{0,1}[A-Za-z\s]{0,}$", ErrorMessage = "Invalid name. Use letters only")]
[Display(Name = "Father Name")]
public String FatherName { get; set; }
[Required]
[Range(0, 10000)]
public int Fee { get; set; }
[Required]
[RegularExpression(#"^((\+92)|(0092))-{0,1}\d{3}-{0,1}\d{7}$|^\d{11}$|^\d{4}-\d{7}$", ErrorMessage = "Please enter only mobile number, Landline not acceptable")]
[Display(Name = "Student Contact No.")]
public string StudentContact { get; set; }
[Required]
[RegularExpression(#"^[0-9]+$", ErrorMessage = "Please enter correct phone number")]
[Display(Name = "Guardian Contact No.")]
public string GuardianContact { get; set; }
[Required]
[RegularExpression(#"^[0-9]+$", ErrorMessage = "Enter only numbers")]
[Display(Name = "Roll Number")]
[IfRollNoExists]
public int RollNo { get; set; }
[Required]
[Display(Name = "Record Date")]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime DateTime { get; set; }
[Display(Name = "Student Picture")]
public String ImageURL { get; set; }
public Class Class { get; set; }
[Required]
[Display(Name = "Class Title")]
public int ClassId { get; set; }
[ForeignKey("Account")]
public int AccountId { get; set; }
public virtual Account Account { get; set; }
}
My Status Class is
public class Status
{
public int Id { get; set; }
public string StudentStatus { get; set; }
}
My ViewModel Is:
public class AttendanceViewModel
{
public IEnumerable<Student> Student { get; set; }
public IEnumerable<Status> Status { get; set; }
}
My Razor View is:
#model Pioneer.ViewModel.AttendanceViewModel
#foreach (var student in Model.Student)
{
<tr>
<td>#student.Name</td>
<td>#student.RollNo</td>
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
</tr>
}
Now when I am getting error for using
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Present", new { id = "1" })
Below I attached an image of error. Error Screen Shot
And please tell me can I iterate over my rows without using for-each if I use HTML helper here?
What you are trying to achieve is not possible. As per your view code, the Status model should be part of Student model class class.
So your view Model will look like this :
public class AttendanceViewModel
{
public IEnumerable<Student> Student { get; set; }
}
And Student model class will include status :
public class Student
{
public IEnumerable<Status> Status { get; set; }
}
Now you can access status in your view like this :
#model Pioneer.ViewModel.AttendanceViewModel
#foreach (var student in Model.Student)
{
<tr>
<td>#student.Name</td>
<td>#student.RollNo</td>
#foreach(var status in student)
{
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(status.StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(statusStudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(status.StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(status.StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
}
</tr>
}
EDIT :
Or if you're particular about using the same ViewModel as mentioned in the question, you can replace foreach with for. Check below sample code :
#model Pioneer.ViewModel.AttendanceViewModel
#for(var studentIndex = 0; studentIndex < Model.Student.Count(); studentIndex++)
{
<tr>
<td>#Model.Student[studentIndex].Name</td>
<td>#Model.Student[studentIndex].RollNo</td>
#for(var statusIndex = 0; statusIndex < Model.Status.Count; statusIndex++)
{
<td>
<div data-toggle="buttons">
<label class="btn btn-success active">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Present", new { id = "1" })
</label>
<label class="btn btn-danger">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Absent", new { id = "2" })
</label>
<label class="btn btn-primary">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "On Leave", new { id = "3" })
</label>
<label class="btn btn-warning">
#Html.RadioButtonFor(m => m.Status[statusIndex].StudentStatus, "Short Leave", new { id = "4" })
</label>
</div>
</td>
}
</tr>
}
m.Status its IEnumerable<Status>, it's have not StudentStatus property.
#Html.RadioButtonFor(m => m.Status.StudentStatus, "Absent", new { id = "2" })

Passing data of dynamic table displayed from dropdownlist selected item to controller in Asp.Net MVC

I have a dropdwonlist and depending of the selected item a dynamic table will be dispalyed containing 2 textboxes and 1 checkbox in each row.
After filling the textbox and checking the checkbox I want to pass cheked rows(more than a row) to controller .
I need your help please.
Thank you :)
Script:
<script>
$(function () {
$("#ProduitID").change(function () {
$.get("/Demandes/GetGabarit", { produit: $("#ProduitID").val() }, function (data) {
$("#Gabarit").empty();
$.each(data, function (index, row) {
$("#Gabarit").append($("<tr>").append("<td>"+"<input type=checkbox name='"+row.Designation+"'/>"+"</td>"
+"<td>" + row.Designation + "</td>"
+ "<td>" + "<input type=text style=width:50px; />" + "</td>"
));
});
})
});
});
View:
<div class="form-group">
#Html.LabelFor(model => model.Produit, "Produit", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(p => p.CodeBarre, ViewBag.Produit as SelectList, "Sélectionner un produit", new { id = "ProduitID", #class = "form-control" })
#Html.ValidationMessageFor(model => model.Produit, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CodeBarre, "Gabarit", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<table class="table table-striped">
<thead>
<tr>
<th width="25%">Check</th>
<th width="25%">#Html.DisplayNameFor(model => model.Designation)</th>
<th width="25%">#Html.DisplayNameFor(model => model.Quantite)</th>
</tr>
</thead>
<tbody id="Gabarit">
<tr>
<td class="Designation"></td>
<td class="Quantite" name="Qt"></td>
<td class="Check"></td>
</tr>
</tbody>
</table>
Controller:
public ActionResult Create( DemandeViewModel demande)
{
if (ModelState.IsValid)
{
string strQt = Request.Form["Qt"].ToString();
var dbdemande = new Demande()
{
Emetteur = demande.Emetteur,
id = demande.id,
Date=DateTime.Now,
Quantite = Convert.ToInt32(strQt),
CodeBarre = //i don't know what to put
};
demanderepository.Insert(dbdemande);
return RedirectToAction("Index");
}
ViewBag.DesignationAtelier = new SelectList(db.Atelier.Where(c => c.idPole == idPole), "id", "DesignationAtelier",demande.id);
var Produit = db.Gabarit.Select(x => x.Produit).Distinct();
ViewBag.Produit = new SelectList(Produit);
return View(demande);
}
ViewModel:
public class DemandeViewModel
{
public int CodeBarre { get; set; }
public string Emetteur { get; set; }
public int id { get; set; }
public Nullable<int> Produit { get; set; }
public string Designation { get; set; }
public string Photo { get; set; }
public int Quantite { get; set; }
public string DesignationAtelier { get; set; }
public List<Gabarit> Gabarits { get; set; }
public Nullable<System.DateTime> Date { get; set; }
}
PS: Gabarits are displayed from produits selected item.
My Code in controller doesn't work.
Thank you
Did you have [HttpPost] prefix on your method?

c# ASP.NET MVC cannot pass model's collection field to controller [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 7 years ago.
I have a class from EF.
public partial class Customer
{
public Customer()
{
this.Customer_CustomerSpecialConcern = new HashSet<Customer_CustomerSpecialConcern>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public virtual ICollection<Customer_CustomerSpecialConcern> Customer_CustomerSpecialConcern { get; set; }
}
When I pass the model from controller to view everything works fine (can access Customer_CustomerSpecialConcern values).
The problem is when I post back model to a controller to save the changes the property Customer_CustomerSpecialConcern is null.
Here is how I use it in view.
#foreach (var ccsc in Model.Customer_CustomerSpecialConcern)
{
<div class="form-group fields-container col-md-3">
<label class="field-label control-label col-md-10" for="">#ccsc.CustomerSpecialConcern.Title</label>
<div class="col-md-1 field-input">
#Html.EditorFor(model => ccsc.Value)
#Html.HiddenFor(model => ccsc.Value)
</div>
</div>
}
Please, I need help to get the values of this collection property to controller. Thank you.
Update - Customer_CustomerSpecialConcern class details
public partial class Customer_CustomerSpecialConcern
{
public int Id { get; set; }
public int Customer_Id { get; set; }
public int CustomerSpecialConcern_Id { get; set; }
public bool Value { get; set; }
public virtual Customer Customer { get; set; }
public virtual CustomerSpecialConcern CustomerSpecialConcern { get; set; }
}
Please try this,
#for (int i = 0; i < Model.Customer_CustomerSpecialConcern.Count(); i++)
{
<div class="form-group fields-container col-md-3">
<label class="field-label control-label col-md-10" for="">#Model.CustomerSpecialConcern[i].Title</label>
<div class="col-md-1 field-input">
#Html.EditorFor(model => model.Customer_CustomerSpecialConcern[i].Value)
#Html.HiddenFor(model => model.Customer_CustomerSpecialConcern[i].Value)
</div>
</div>
}
Check this article.
I tried your example, and this is how it looks
public ActionResult Index()
{
var customer = new Customer
{
Name = "Name",
Surname = "Surname",
Email = "email#email.com",
Mobile = "mobile...",
Customer_CustomerSpecialConcern = new List<Customer_CustomerSpecialConcern>
{
new Customer_CustomerSpecialConcern
{
Value = true
},
new Customer_CustomerSpecialConcern
{
Value = true
}
}
};
return View(customer);
}
View:
#model WebApplication1.Models.Customer
#{
ViewBag.Title = "Customer";
var customer_CustomerSpecialConcern = Model.Customer_CustomerSpecialConcern.ToList();
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
for (int i = 0; i < Model.Customer_CustomerSpecialConcern.Count(); i++)
{
<div class="form-group fields-container col-md-3">
<label class="field-label control-label col-md-10" for=""></label>
<div class="col-md-1 field-input">
#Html.CheckBoxFor(model => customer_CustomerSpecialConcern[i].Value)
</div>
</div>
}
<input type="submit" value="Save"/>
}

Categories

Resources