MVC dynamic data passing to controller - c#

I am creating a MVC application. I am having a view with a form to fill, but it seems that controller does not get data that was entered (it is null when debugging).
My controller:
public ActionResult AddGroupsQty(AddGroupsQtyViewModel value)
{
var model = new AddGroupsQtyViewModel();
model.subject_id = value.subject_id;
model.qty = value.qty;
ClassDeclarationsDBEntities1 entities1=new ClassDeclarationsDBEntities1();
var subj = entities1.Subjects
.Where(b => b.class_id == model.subject_id)
.FirstOrDefault();
model.subject_name = subj.name;
if (ModelState.IsValid)
{
int maxId = 0;
int total = 0;
total = entities1.Groups.Count();
if (total == 0)
{
maxId = 0;
}
else
{
maxId = entities1.Groups.Max(u => u.group_id);
}
for (int i = 0; i < value.qty; i++)
{
var teacher = entities1.Users
.Where(b => b.email.Replace(" ", String.Empty) == model.teacher_emails[i].Replace(" ", String.Empty))
.FirstOrDefault();
var group=new Models.Group(value.subject_id, maxId+1, model.group_names[i], teacher.user_id);
entities1.Groups.Add(group);
entities1.SaveChangesAsync();
}
return RedirectToAction("OperationSuccess", "Account");
}
return View(model);
}
My View model:
public class AddGroupsQtyViewModel
{
public int qty { get; set; }
public int subject_id { get; set; }
public string subject_name { get; set; }
[Required]
[Display(Name = "Name of group")]
public List<string> group_names { get; set; }
[Required]
[Display(Name = "Email of teacher")]
public List<string> teacher_emails { get; set; }
}
and the View:
#using System.IdentityModel.Configuration
#using System.Web.UI.WebControls
#model ClassDeclarationsThsesis.Models.AddGroupsQtyViewModel
#{
ViewBag.Title = "AddGroupsQty";
}
<h2>Add Groups to #Model.subject_name</h2>
#if (Model != null)
{
using (Html.BeginForm("AddGroupsQty", "Account", new { qty = Model.qty, Model.subject_id }, FormMethod.Post, new { #class = "form-horizontal", role = "form", }))
{
#Html.AntiForgeryToken()
<h4>Insert data</h4>
<hr />
<table>
<tr>
<th>
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.group_names, new { #class = "col-md-2 control-label" })
</div>
</th>
<th>
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.teacher_emails, new { #class = "col-md-2 control-label" })
</div>
</th>
</tr>
#for (int i = 0; i < Model.qty; i++)
{
<tr>
<th>
<div class="form-group">
<div class="col-md-10">
#Html.TextBoxFor(m => m.group_names[i], new { #class = "form-control" })
</div>
</div>
</th>
<th>
<div class="form-group">
<div class="col-md-10">
#Html.TextBoxFor(m => m.teacher_emails[i], new { #class = "form-control" })
</div>
</div>
</th>
</tr>
}
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit" />
</div>
</div>
}
}
The problem is that when running the application, filling the form and submitting by pressing the button, it throws a null exception in controller that both lists:
List teacher_emails
and:
List group_names
are null. I do not see any error in my form. How can I solve it?

model.teacher_emails and model.group_names are always null, because model is new.
var model = new AddGroupsQtyViewModel();
Try using value.teacher_emails and value.group_names instead.
Also tidy that code up. A blank line after the variable declaration, and you would have spotted it yourself.

Related

Creating an ASP.net MVC Web Application with details given below:

To take the image from user and save image of users table in the database.
To add a view to show images of users from the folder Images in the Listing View of user along with other information of user.
Now the reason for this question is that when I tried to save it in database it saves the images successfully but not in the Images folder I tried everything but none of the method works.
My Code:
Employee Controller:
using My_Work.DAL;
using My_Work.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PagedList;
using PagedList.Mvc;
using System.IO;
namespace My_Work.Controllers
{
public class EmployeeController : Controller
{
// GET: Employee
public ActionResult Index(string SearchBy, string SearchTerm,
int? page, string sortBy)
{
//In case of Invalid user redirect to login
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
ViewBag.CitySort = String.IsNullOrEmpty(sortBy) ? "City desc" : "City";
ViewBag.GenderSort = sortBy == "Gender" ? "Gender desc" : "Gender";
EmployeeEntity entity = new EmployeeEntity();
List<Employee> list = entity.GetList(SearchBy,
SearchTerm, sortBy);
HttpCookie cookie = Request.Cookies["Detalis"];
if (cookie != null)
{
string color = cookie["Lastlogin"];
}
return View(list.ToPagedList(page ?? 1, 5));
}
public ActionResult Create()
{
//In case of Invalid user redirect to login
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
ViewBag.DepartmentsList = getDepartmentList();
//ViewBag.LanguagesList = GetLanguagesList();
return View();
}
[HttpPost]
public ActionResult Create(Employee employee)
{
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
if (ModelState.IsValid)
{
var allowedExtensions = new[] {".Jpg", ".png", ".jpg", "jpeg"};
var ext = Path.GetExtension(employee.file.FileName);
//getting the extension(ex-.jpg)
if (allowedExtensions.Contains(ext)) //check what type of extension
{
//~/Images is relative path for images in root directory
var path = Path.Combine(Server.MapPath("~/Images"),Path.GetFileName(employee.file.FileName));
employee.ImageURL = employee.file.FileName;
//saving photo of employee in the image folder
// file.SaveAs Saves the contents of an uploaded file to a specified path on the Web server.
employee.file.SaveAs(path);
}
else
{
ViewBag.message = "Please choose only Image file";
ViewBag.DepartmentsList = getDepartmentList();
return View(employee);
}
EmployeeEntity entity = new EmployeeEntity();
int count = entity.insert(employee);
if (count > 0)
{
ViewBag.successMessage = "Data insterted Successfully !";
}
ModelState.Clear();
}
ViewBag.DepartmentsList = getDepartmentList();
return View(employee);
}
[HttpPost]
public ActionResult Delete(long id)
{
//In case of Invalid user redirect to login
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
EmployeeEntity entity = new EmployeeEntity();
int RowCount = entity.DeleteEmployee(id);
return RedirectToAction("Index");
}
public ActionResult Edit(int id)
{
//In case of Invalid user redirect to login
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
Employee emp = new EmployeeEntity().GetSingleEmployee(id);
ViewBag.DepartmentsList = getDepartmentList();
return View(emp);
}
[HttpPost]
public ActionResult Edit(Employee employee)
{
//In case of Invalid user redirect to login
if (Session["login"] == null)
{
return RedirectToAction("Login", "User");
}
int RowCount = new
EmployeeEntity().UpdateEmployee(employee);
return RedirectToAction("Index");
}
private List<SelectListItem> getDepartmentList()
{
List<SelectListItem> departmentList = new
Department().getDepartmentList();
return departmentList;
}
}
}
Employee Model:
using My_Work.CustomValidation;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace My_Work.Models
{
public class Employee
{
public int EmployeeID { get; set; }
[Required]
public string FirstName { get; set; }
public string LastName { get; set; }
[Required]
public string Gender { get; set; }
[Required]
[Range(20, 60, ErrorMessage = "Age must be between 20 and 60")]
[Display(Name = "Age")]
public int Age { get; set; }
[Required]
[Display(Name = "Education Level")]
public int EducationLevel { get; set; }
[Range(25000, 500000, ErrorMessage = "Please enter correct value")]
[Required]
/* We can control the display of data in a View (UI) using
display attributes */
[Display(Name = "Salary")]
public int Salary { get; set; }
[Required]
[EmailAddress]
public string EmailAddress { get; set; }
[Required(ErrorMessage = "Please enter hire date")]
[Display(Name = "Hire Date")]
[CustomHireDate(ErrorMessage = "Hire Date must be less than or equal to Today's Date")]
[DataType(DataType.Date)]
public DateTime? HireDate { get; set; }
public string City { get; set; }
public Department department { get; set; }
public string ImageURL { get; set; }
[Required]
[Display(Name = "Upload Photo")]
public HttpPostedFileBase file { get; set; }
}
}
EmployeeEntity Class:
using My_Work.Models;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Configuration;
namespace My_Work.DAL
{
public class EmployeeEntity
{
string ConnectionString = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
SqlConnection sqlConnection = null;
SqlCommand cmd = null;
public int insert(Employee employee)
{
int effectedRows = 0;
try
{
sqlConnection = new SqlConnection(ConnectionString);
string query = #"insert into Employee(EmployeeID,FirstName,LastName,Gender,Age,EducationLevel,Salary,EmailAddress,HireDate,
City,DepartmentID,ImageURL)
values('" + employee.EmployeeID + "','" + employee.FirstName + "','"
+ employee.LastName + "','" + employee.Gender + "','" + employee.Age +
"','" + employee.EducationLevel + "','" + employee.Salary + "','" +
employee.EmailAddress + "','" + employee.HireDate + "','" +
employee.City + "','" + employee.department.DepartmentID +
"','" + employee.ImageURL + "')";
sqlConnection.Open();
cmd = new SqlCommand(query, sqlConnection);
effectedRows = cmd.ExecuteNonQuery();
sqlConnection.Close();
return effectedRows;
}
catch (Exception exp)
{
return effectedRows;
}
}
public List<Employee> GetList(string searchBy, string search, string sortBy)
{
//Here we have passed searchBy and Search as parameters and we are
// going to apply where filter in SQL Query using these parameters
List<Employee> employeesList = new List<Employee>();
sqlConnection = new SqlConnection(ConnectionString);
string query = String.Empty;
if (String.IsNullOrEmpty(sortBy))
{
sortBy = "City";
}
if (!String.IsNullOrEmpty(searchBy))
{
query = #"select * from Employee inner join Department on Employee.DepartmentID = Department.DepartmentID where "
+ searchBy + " like '%" + search + "%'order by "+sortBy+"";
}
else
{
query = #"select * from Employee inner join Department on Employee.DepartmentID =
Department.DepartmentID order by " + sortBy + "";
}
cmd = new SqlCommand(query, sqlConnection);
sqlConnection.Open();
SqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
employeesList.Add(new Employee
{
EmployeeID = Convert.ToInt32(dataReader["EmployeeId"].ToString()),
FirstName = dataReader["FirstName"].ToString(),
LastName = dataReader["LastName"].ToString(),
Gender = dataReader["Gender"].ToString(),
City = dataReader["City"].ToString(),
EmailAddress = dataReader["EmailAddress"].ToString(),
Age = Convert.ToInt32(dataReader["Age"].ToString()),
Salary = Convert.ToInt32(dataReader["Salary"].ToString()),
EducationLevel = Convert.ToInt32(dataReader["EducationLevel"].ToString()),
HireDate = DateTime.Parse(dataReader["HireDate"].ToString()),
ImageURL = dataReader["ImageURL"].ToString(),
department = new Department
{
DepartmentID = Convert.ToInt32(dataReader["departmentId"].ToString()),
Name = dataReader["Name"].ToString()
}
});
}
sqlConnection.Close();
return employeesList;
}
public List<Employee> GetList()
{
List<Employee> EmployeeList = new List<Employee>();
sqlConnection = new SqlConnection(ConnectionString);
string query = #"select * from Employee emp inner join Department dept on emp.DepartmentID=dept.DepartmentID";
sqlConnection.Open();
cmd = new SqlCommand(query, sqlConnection);
SqlDataReader dataReader = cmd.ExecuteReader();
while (dataReader.Read())
{
EmployeeList.Add(new Employee
{
FirstName = dataReader["FirstName"].ToString(),
LastName = dataReader["LastName"].ToString(),
Gender = dataReader["Gender"].ToString(),
EmailAddress =
dataReader["EmailAddress"].ToString(),
City = dataReader["City"].ToString(),
Salary
= Convert.ToInt32(dataReader["Salary"].ToString()),
Age =
Convert.ToInt32(dataReader["Age"].ToString()),
EducationLevel =
Convert.ToInt32(dataReader["EducationLevel"].ToString()),
department = new Department
{
DepartmentID =
Convert.ToInt32(dataReader["DepartmentID"].ToString()),
Name = dataReader["Name"].ToString()
},
HireDate =
DateTime.Parse(dataReader["HireDate"].ToString())
});
}
sqlConnection.Close();
return EmployeeList;
}
}
}
Create View:
#model My_Work.Models.Employee
{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<title>Employee Information</title>
</head>
<body>
#using (Html.BeginForm("Create", "Employee", FormMethod.Post, new
{ enctype = "multipart/form-data" }))
{
<div class="form-horizontal">
<h4 class="h1 text-center">Create Employee</h4>
<hr />
<div>
#if (ViewBag.successMessage != null)
{
<h3>#ViewBag.successMessage</h3>
}
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes:
new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes:
new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Gender, htmlAttributes: new
{ #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Gender, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Gender, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EmailAddress,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EmailAddress, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model =>
model.EmailAddress, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.City, htmlAttributes: new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.City, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.City, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Salary, htmlAttributes: new
{ #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Salary, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Salary, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Age, htmlAttributes: new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Age, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Age, "", new
{ #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.EducationLevel,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.EducationLevel, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model =>
model.EducationLevel, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.HireDate, htmlAttributes:
new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.HireDate, new {
htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.HireDate,
"", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.department.DepartmentID,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model =>
model.department.DepartmentID,
(List<SelectListItem>)ViewBag.DepartmentsList)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.file, htmlAttributes: new {
#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.file, new { type = "file",
#class = "form-control" })
#Html.ValidationMessageFor(model => model.file, "",
new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btndefault" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to Main Page", "Index")
</div>
</body>
</html>
Index View:
#using PagedList.Mvc;
#using PagedList;
#model IPagedList<My_Work.Models.Employee>
#{
Layout = null;
HttpCookie cookie = Request.Cookies["Detalis"];
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div style="float:left">
#Html.ActionLink("Create New", "Create")
</div>
<div style="float:right">
#{
String img64 = (string)Session["userImage"];
String img64Url = string.Format("data:image/" +
(string)Session["userImageType"] + ";base64,{0}", img64);
//imagetype can be e.g. gif, jpeg, png etc.
}
<img alt="" src="#img64Url" width="40" height="40"
class="rounded-circle" />
<br />
#Html.ActionLink("Click to Logout", "Logout", "User")
</div>
<br />
<p>
#using (#Html.BeginForm("Customize", "Employee", FormMethod.Post))
{
<b>User Preferences:</b>
#Html.TextBox("RecordCount")
<input type="submit" value="Set Preferences" />
}
</p>
<p>
#using (#Html.BeginForm("Index", "Employee", FormMethod.Get))
{
<b>Search By:</b>
#Html.RadioButton("SearchBy", "City", true)
<text>City</text>
#Html.RadioButton("SearchBy", "Gender")
<text>Gender</text><br />
#Html.TextBox("search") <input type="submit"
value="search" />
}
</p>
<p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model =>
model.First().FirstName)
</th>
<th>
#Html.DisplayNameFor(model =>
model.First().EmailAddress)
</th>
<th>
#Html.ActionLink("Gender", "Index", new
{
sortBy = ViewBag.GenderSort,
SearchBy = Request["SearchBy"],
SearchTerm = Request["SearchTerm"]
})
</th>
<th>
#Html.ActionLink("City", "Index", new
{
sortBy = ViewBag.CitySort,
SearchBy = Request["SearchBy"],
SearchTerm = Request["SearchTerm"]
})
</th>
<th>
#Html.DisplayNameFor(model =>
model.First().HireDate)
</th>
<th>
Photo
</th>
</tr>
#if (Model.Count() == 0)
{
<tr>
<td colspan="6">
No records match search criteria
</td>
</tr>
}
else
{
foreach (var item in Model)
{
using (Html.BeginForm("Delete", "Employee", new
{
id = item.EmployeeID
}))
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.FirstName)
</td>
<td>
#Html.DisplayFor(modelItem => item.EmailAddress)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.City)
</td>
<td>
#Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
#if (!string.IsNullOrEmpty(item.ImageURL))
{
#*#Url.Content convert the relative path into application absolute
path*#
<img src="#Url.Content("~/Images/" + item.ImageURL)"
height="50px" width="50px" />
}
else
{
<span>No Image Found!</span>
}
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id =
item.EmployeeID }) |
#Html.ActionLink("Details", "Details", new { id =
item.EmployeeID }) |
<input type="submit" value="Delete" onclick="return confirm('do you really want to delete this record?');" />
</td>
</tr>
}
}
}
</table>
#Html.PagedListPager(Model, page => Url.Action("Index", new {
page, SearchBy = Request.QueryString["SearchBy"], SearchTerm =
Request.QueryString["SearchTerm"], sortBy =
Request.QueryString["sortBy"] }), new PagedListRenderOptions() {
Display = PagedListDisplayMode.IfNeeded,
DisplayPageCountAndCurrentLocation = true })
<br />
<div style="float:left">
<dl>
<dt>
#Html.ActionLink("User Last Login:", cookie["Lastlogin"])
</dt>
<dd>
#if (cookie != null)
{
#cookie["Lastlogin"];
}
</dd>
</dl>
</div>
<br />
</body>
</html>
Images Folder:

Passing object with List from view to Controller. List is not mapping/

I have two objects that I pass to View, and than back to controller.
public class Category1Dictionary
{
public int Id { get; set; }
public IList<Category2Dictionary> SubCategories {get; set;}
public string UserName { get; set; }
}
public class Category2Dictionary
{
public int Id { get; set; }
public string Category2Item { get; set; }
}
My view looks like this:
#model Budget.Models.Category1Dictionary
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.Id)
#Html.HiddenFor(m => m.UserName)
#Html.HiddenFor(m => m.SubCategories)
#Html.LabelFor(m => m.Category1Item, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(m => m.Category1Item, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(m => m.Category1Item, "", new { #class = "text-danger" })
</div>
#for (int i = 0; i < Model.SubCategories.Count; i++)
{
<div class="col-md-10" style="padding-left:40px">
#Html.EditorFor(m => m.SubCategories[i].Category2Item, new { htmlAttributes = new { #class = "form-control" } })
#Html.HiddenFor(m => m.SubCategories[i].Id, new { htmlAttributes = new { #class = "form-control" } })
</div>
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
And action in the controller:
[HttpPost]
public ActionResult Edit(Category1Dictionary category1Dictionary)
{
return View(category1Dictionary);
}
With this layout in action I get object Category1Dictionary with all items but SubCategories is NULL. I saw some similar posts but I have spent 6 hours in total on this and still can make it work...
Get Method:
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Category1Dictionary category1Dictionary = db.Category1Dictionaries.Include(p=>p.SubCategories).First(c=>c.Id == id);
if (category1Dictionary == null)
{
return HttpNotFound();
}
return View(category1Dictionary);
}
EDIT:
input field generated by EditorFor
Post message from fiddler:

Create multiple objects in one view in ASP.NET

I would like to create multiple objects from one view (e.g. 5 Items in one View). My View looks like:
#model IEnumerable<WerehouseProject.Models.ItemRentList>
#{
ViewBag.Title = "Create";
}
<h2>Dodaj</h2>
#{Html.RenderPartial("_PartialError");}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#for (int i = 0; i < Model.Count; i++)
{
<div class="form-group">
#Html.LabelFor(model => model[i].ItemID, "Przedmiot", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("ItemID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model[i].ItemID, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model[i].Ilosc, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model[i].Ilosc, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model[i].Ilosc, "", new { #class = "text-danger" })
</div>
</div>
#Html.HiddenFor(model => model[i].ItemRentID)
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Dodaj" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
<button type="button" name="ID" value="#ViewBag.ItemRentID" onclick="location.href='#Url.Action("Details", "ItemRents", new { ID = #ViewBag.ItemRentID })'">Wróć</button>
</div>
Create GET method:
public ActionResult Create(int ID, int quantity)
{
var model = new List<ItemRentList>();
for(int i = 0; i < quantity; i++)
{
model.Add(new ItemRentList { ItemRentID = ID } );
}
ViewBag.ItemRentID = ID;
ViewBag.ItemID = new SelectList(db.Items, "ItemID", "Nazwa");
return View(model);
}
And my POST Create method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "IRListID,Ilosc,ItemRentID,ItemID")] IEnumerable<ItemRentList> itemRentList)
{
...
}
My itemRentList.ItemID is always 0, can someone tell me how should I code View or Controller to get list of ItemRentList in POST Method?
This is my Model of ItemRentList
public class ItemRentList
{
[Key]
public int IRListID { get; set; }
[Display(Name = "Ilość")]
public double Ilosc { get; set; }
[Display(Name = "Nazwa przedmiotu")]
public int ItemID { get; set; }
public virtual Item Item { get; set; }
public int ItemRentID { get; set; }
public virtual ItemShopping ItemRent { get; set; }
}
If I edit View and Controller to create only one and always one ItemRentList (not one object in list, just simple ItemRentList) then the value of ItemID is correctly bind to object, the problem is when I want to create a list of ItemRentList, then ItemID is always 0, no mater what I choose from DropDownList.

Values lost when sent to controller

I want to send my EmailFormModel, which contains the Ressurs-list, to the controller where i want to do stuff with it. However I'm never able to access the values in my EmailFormModel in my controller. I tried to overcome this problem by using Sessions, but still it doesnt work.
The list Ressurs contains several Ressursbehov, but there is never more than one EmailFormModel.
My controller
namespace WebApplication6.Controllers
{
public class AppController : Controller
{
const string SESSION_SAVED_MODEL = "savedModel";
[HttpGet]
public ActionResult Index()
{
Session[SESSION_SAVED_MODEL] = new EmailFormModel();
return View(Session[SESSION_SAVED_MODEL]);
}
public ActionResult Sent()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Index(EmailFormModel model)
{
//other irrelevant code
if (Request.Params["Ekstra_Ressurs"] != null)
{
model.Ressurs.Add(new RessursBehov());
Session[SESSION_SAVED_MODEL] = model;
}
}
return View(model);
}
}
My model
namespace WebApplication6.Models
{
public class EmailFormModel
{
[Required, Display(Name = "Prosjektnummer")]
public string Prosjektnummer { get; set; }
[Required, Display(Name = "Prosjektnavn")]
public string Prosjektnavn { get; set; }
[Required, Display(Name = "Prosjekttype")]
public string Prosjekttype { get; set; }
[Required, Display(Name = "Prosjektleder")]
public string Prosjektleder { get; set; }
public List<RessursBehov> Ressurs = new List<RessursBehov>()
{
new RessursBehov() };
}
public class RessursBehov
{
[Required, Display(Name = "Ressurstype")]
public string Ressurstype { get; set; }
[Required, Display(Name = "Navn på ressurs")]
public string Navn_På_Ressurs { get; set; }
[Required, Display(Name = "Ukenummer")]
public int? Ukenummer { get; set; }
[Required, Display(Name = "Antall timer")]
public int? Antall_Timer { get; set; }
[Required, Display(Name = "Antall uker")]
public int? Antall_Uker { get; set; }
}
}
}
My View
#model WebApplication6.Models.EmailFormModel
#{
ViewBag.Title = "Registrer nytt prosjekt";
List<SelectListItem> prosjektTypeListe = new List<SelectListItem>()
{
new SelectListItem { Text = "Prosjekt", Value = "Prosjekt" },
new SelectListItem { Text = "Forvaltning", Value = "Forvaltning" }
};
List<SelectListItem> ressurstypeliste = new List<SelectListItem>()
{
new SelectListItem { Text = "utvikler", Value = "utvikler" },
new SelectListItem { Text = "frontendutvikler", Value = "frontendutvikler" },
new SelectListItem { Text = "epi-utvikler", Value = "epi-utvikler" },
new SelectListItem { Text = "webnodesutvikler", Value = "webnodesutvikler" },
new SelectListItem { Text = "designer", Value = "designer" },
new SelectListItem { Text = "rådgiver", Value = "rådgiver" },
new SelectListItem { Text = "prosjektleder", Value = "prosjektleder" }
};
}
<div class="title">
<div class="text-center">
<h2>#ViewBag.Title</h2>
</div>
</div>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="rows">
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnavn, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnavn, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnavn)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjekttype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe, "-- Velg Prosjekttype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektleder, new { #class = "col-md-1 text-center" }) <!--tar inn m som parameter og returnerer m.prosjektleder-->
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektleder, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektleder)
</div>
</div>
#for (var i = 0; i < Model.Ressurs.Count; i++)
{
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ressurstype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => Model.Ressurs[i].Ressurstype, ressurstypeliste, "-- Velg ressurstype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
#Html.LabelFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "col-md-2 text-right" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Navn_På_Ressurs)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ukenummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Ukenummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Ukenummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Timer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Uker)
</div>
</div>
}
<br />
<div class="row">
<div class="col-md-5"></div>
<div class="col-md-2">
<input type="submit" class="btn btn-default" value="Legg til ressurser" name="Ekstra_Ressurs" />
</div>
<div class="col-md-2">
<input type="submit" class="btn btn-primary" value="Send inn mail" name="Sendknapp" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
In order to reach model in HttpPost Index action
1) You should pass EmailFormModel type model to View in the GET Index action method.
EmailFormModel model = new EmailFormModel();
Session[SESSION_SAVED_MODEL]=model;
return View(model);
2) You should use Model at the lambda expressions
#Html.TextBoxFor(m => Model.Prosjektleder, new { #class = "html_label" })
change all ms with Model.
All you have to do is add #Name in html attribute then you wont need to use session also .
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe , "-- Velg Prosjekttype --", new { #class = "dropdown" , #Name = "Prosjekttype" })

Cannot pass viewmodel with list to controller-action (MVC 5)

I am having problem passing a viewmodel that contains a list of "files" from my view to my controller(action). The viewmodel seems to be passed to the actionresult with all the propetries, except the list (List Files). The list just stays null, even if the model contains files when i submit the form.
What do i do wrong? I will paste my c# code from my controller, model, viewmodel and my RazorHTML.
File-model:
public class File
{
[Key]
public int ID { get; set; }
[Display(Name = "Filnamn")]
public string Filename { get; set; }
//[Display(Name = "Beskrivning")]
//public string Description { get; set; }
[Display(Name = "Filtyp")]
public string ContentType { get; set; }
public byte[] Data { get; set; }
public int Size { get; set; }
//public string CreatorId { get; set; }
public string CreatorID { get; set; }
[Required]
[Display(Name = "Skapare")]
[ForeignKey("CreatorID")]
public virtual ApplicationUser Creator { get; set; }
//public int DocumentId { get; set; }
public int DocumentID { get; set; }
[Required]
[Display(Name = "Dokument")]
[ForeignKey("DocumentID")]
public virtual Document Document { get; set; }
}
Viewmodel:
public class CreateDocumentViewModel
{
public CreateDocumentViewModel()
{
CheckboxUsers = new List<CheckBoxListUser>();
CheckboxGroups = new List<CheckBoxListGroup>();
CheckboxTags = new List<CheckBoxListTags>();
Files = new List<File>();
}
[Display(Name = "Beskrivning")]
public string Description { get; set; }
[Display(Name = "Titel")]
public string Name { get; set; }
[DataType(DataType.MultilineText)]
[Display(Name = "Markdown")]
public string Markdown { get; set; }
HttpPostedFileBase FileToAdd { get; set; }
[Display(Name="Användare")]
public List<CheckBoxListUser> CheckboxUsers { get; set; }
[Display(Name = "Grupper")]
public List<CheckBoxListGroup> CheckboxGroups { get; set; }
[Display(Name = "Taggar")]
public List<CheckBoxListTags> CheckboxTags { get; set; }
[Display(Name = "Filer")]
public ICollection<File> Files { get; set; }
public string FilesJson { get; set; }
}
View:
#model MarkdownManagerNew.Viewmodels.CreateDocumentViewModel
#{
ViewBag.Title = "CreateDocument";
}
<h2>Nytt dokument</h2>
#Html.BeginForm("CreateFile", "User", new { model = Model, test = Model.Name, files = Model.Files }, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control", placeholder = "Titel" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control", placeholder = "Beskrivning" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group col-md-6 markdownEditorForm">
<div class="col-md-12">
#Html.EditorFor(model => model.Markdown, new { htmlAttributes = new { #class = "form-control markdownEditor" } })
#Html.ValidationMessageFor(model => model.Markdown, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-sm-6 markdownResult"></div>
</div>
</div>
<div class="row">
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.CheckboxGroups)
</dt>
#for (int i = 0; i < Model.CheckboxGroups.Count; i++)
{
<dd>
#Html.CheckBoxFor(x => x.CheckboxGroups[i].IsChecked)
#Html.HiddenFor(x => x.CheckboxGroups[i].ID)
#Html.HiddenFor(x => x.CheckboxGroups[i].Display)
#Html.DisplayFor(x => x.CheckboxGroups[i].Display)
</dd>
}
<dt>
#Html.DisplayNameFor(model => model.CheckboxUsers)
</dt>
#for (int i = 0; i < Model.CheckboxUsers.Count; i++)
{
<dd>
#Html.CheckBoxFor(x => x.CheckboxUsers[i].IsChecked)
#Html.HiddenFor(x => x.CheckboxUsers[i].ID)
#Html.HiddenFor(x => x.CheckboxUsers[i].Display)
#Html.DisplayFor(x => x.CheckboxUsers[i].Display)
</dd>
}
<dt>
#Html.DisplayNameFor(model => model.CheckboxTags)
</dt>
#for (int i = 0; i < Model.CheckboxTags.Count; i++)
{
<dd>
#Html.CheckBoxFor(x => x.CheckboxTags[i].IsChecked)
#Html.HiddenFor(x => x.CheckboxTags[i].ID)
#Html.HiddenFor(x => x.CheckboxTags[i].Display)
#Html.DisplayFor(x => x.CheckboxTags[i].Display)
</dd>
}
</dl>
</div>
<div class="form-group">
#Html.Label("File", new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" id="File" name="upload" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Ladda upp fil" class="btn btn-default" />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
#if (Model.Files.Count > 0)
{
<h3>#Html.DisplayNameFor(model => model.Files)</h3>
<table class="table table-striped table-bordered">
<tr>
<th>Filename</th>
<th>Filetype</th>
<th>Size(bytes)</th>
</tr>
#foreach (var file in Model.Files)
{
<tr>
<td>#file.Filename</td>
<td>#file.ContentType</td>
<td>#file.Size</td>
</tr>
}
</table>
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-1 col-md-10">
<input type="submit" value="Skapa" class="btn btn-default" />
</div>
</div>
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Controller
[HttpPost]
public ActionResult CreateFile(CreateDocumentViewModel viewModel)
{
var file = repo.CreateFile(upload, GetCurrentUser());
viewModel.Files.Add(file);
TempData["viewModel"] = viewModel;
//return RedirectToAction("CreateDocument", file);
return RedirectToAction("CreateDocument", new { files = viewModel.Files });
}
-EDIT-
I have also tried adding editorfields for every property in every file like this:
#for (int i = 0; i < Model.Files.Count; i++)
{
<div>
#Html.LabelFor(x => x.Files[i].DocumentID)
#Html.EditorFor(x => x.Files[i].DocumentID)
#Html.ValidationMessageFor(x => x.Files[i].DocumentID)
#Html.LabelFor(x => x.Files[i].CreatorID)
#Html.EditorFor(x => x.Files[i].CreatorID)
#Html.ValidationMessageFor(x => x.Files[i].CreatorID)
#Html.LabelFor(x => x.Files[i].ID)
#Html.EditorFor(x => x.Files[i].ID)
#Html.ValidationMessageFor(x => x.Files[i].ID)
#Html.LabelFor(x => x.Files[i].ContentType)
#Html.EditorFor(x => x.Files[i].ContentType)
#Html.ValidationMessageFor(x => x.Files[i].ContentType)
#Html.LabelFor(x => x.Files[i].CreatorID)
#Html.EditorFor(x => x.Files[i].CreatorID)
#Html.ValidationMessageFor(x => x.Files[i].CreatorID)
#Html.LabelFor(x => x.Files[i].Data)
#Html.EditorFor(x => x.Files[i].Data)
#Html.ValidationMessageFor(x => x.Files[i].Data)
#Html.LabelFor(x => x.Files[i].Filename)
#Html.EditorFor(x => x.Files[i].Filename)
#Html.ValidationMessageFor(x => x.Files[i].Filename)
#Html.LabelFor(x => x.Files[i].Size)
#Html.EditorFor(x => x.Files[i].Size)
#Html.ValidationMessageFor(x => x.Files[i].Size)
</div>
}
Your files are of type ICollection thus each file information needs to be present within the form to be able to be posted to the controller in the populated viewmodel. Currently you have no fields for this collection and such the ICollection is empty when posted to the controller. You can create an custom EditorFor to display the File data as well as post this data to the controller.
Please refer to this tutorial on how to do this:
http://blog.learningtree.com/en/editing-collections-in-asp-net-mvc/
In your code you are doing something similar for the checkboxes:
#for (int i = 0; i < Model.CheckboxUsers.Count; i++)
{
<dd>
#Html.CheckBoxFor(x => x.CheckboxUsers[i].IsChecked)
#Html.HiddenFor(x => x.CheckboxUsers[i].ID)
#Html.HiddenFor(x => x.CheckboxUsers[i].Display)
#Html.DisplayFor(x => x.CheckboxUsers[i].Display)
</dd>
}
Note the hidden fields, this is what is passing the data to the controller for the list of checkboxes. I would reccomend creating a custom EditorFor for the files. Or more simply repopulate the collection of files again in your controller from the model.
But the Files collection is not in any inputs. They are basically just labels, therefore they will not post to server. Since they do not change by user, you can just load the files from DB again in your action.

Categories