Getting error of "The model item passed into the dictionary is of type...." - asp.net-mvc

I'm making a website using asp.net mvc 4 & EF6 where admins can add new client information. So far everything is working fine but whenever I try to save the data by pressing Add button I get this error,
The model item passed into the dictionary is of type 'MyMvc.Models.UserInfo', but this dictionary requires a model item of type 'MyMvc.Models.BrManagement'
Here are my codes,
Controller
[HttpPost]
public ActionResult ClientManager(BrManagement ClTable)
{
if (Session["AdminNAME"] != null)
{
if (ModelState.IsValid)
{
var AddClient = ClTable.AddUserInfo;
abdb.UserInfoes.Add(AddClient);
abdb.SaveChanges();
return RedirectToAction("ClientManager", new { ClPanelId = "AllCl" });
}
return View(ClTable.AddUserInfo);
}
else
{
return RedirectToAction("AdminLogin");
}
}
Model
public class BrManagement
{
public Branch Branches { get; set; }
public IEnumerable<Branch> BrCollection { get; set; }
public UserInfo AddUserInfo { get; set; }
public IEnumerable<UserInfo> UserCollection { get; set; }
}
View
#using (Html.BeginForm("ClientManager", "Home", FormMethod.Post))
{
#Html.ValidationSummary(true)
<div class="editor-label">
<strong>Client USER ID</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.UserId)
#Html.ValidationMessageFor(a => a.AddUserInfo.UserId)
</div>
<div class="editor-label">
<strong>Client Password</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.Password)
#Html.ValidationMessageFor(a => a.AddUserInfo.Password)
</div>
<div class="editor-label">
<strong>Full Name</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.Name, new { size = 30 })
#Html.ValidationMessageFor(a => a.AddUserInfo.Name)
</div>
<div class="editor-label">
<strong>Address</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.AddressLine1, new { size = 30 })
#Html.ValidationMessageFor(a => a.AddUserInfo.AddressLine1)
</div>
#Html.HiddenFor(a => a.AddUserInfo.CreatedDate, new { #Value = System.DateTime.Now })
#Html.HiddenFor(a => a.AddUserInfo.IsActive, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsApproved, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsinfoMatched, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsReportView, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsVarified, new { #Value = "N" })
<br />
<p><input type="submit" class="btn btn-info" value="Add" /></p>
}
I've used the same code for Branches & BrCollection model, both of them are working fine. UserCollection model is also working fine. Why is this happening for AddUserInfo model? I've searched a lot but couldn't find any solution similar to mine. Need this help really bad. Your help will be appreciated! Tnx.
UPDATE
View(FULL)
#model ABCoLtd.Models.BrManagement
#{
ViewBag.Title = "ClientManager";
string active = ViewBag.ClActive.ToString();
Layout = "~/Views/Shared/_ALayout.cshtml";
}
<link href="~/Content/DataTables-1.10.4/css/jquery.dataTables.min.css" rel="stylesheet" />
<body>
<script src="~/Scripts/DataTables-1.10.4/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
var tabpane = '#active';
$("#" + tabpane).addClass("active");
$('#BrTable').DataTable({
"aoColumns": [
{ "bSortable": true },
{ "bSortable": true },
{ "bSortable": true },
{ "bSortable": true }
]
});
});
</script>
<br /><br /><br /><br />
<div class="container well" style="min-width: 100%; padding-right: 5px;">
<h3>Client Manager</h3><hr style="border-top: 2px solid #096596;" />
<ul class="nav nav-tabs">
<li>All Clients </li>
<li>Add Clients</li>
</ul>
<div class="tab-content">
<div class="tab-pane" id="AllCl" style="padding-top: 10px; padding-left: 10px;">
<h4>Manage Clients</h4><hr style="border-top: 2px solid #096596;" />
<div class="table-responsive">
<table id="BrTable" class="table table-striped">
<thead>
<tr><th>BOID</th><th>Name</th><th>Email</th><th>Phone</th></tr>
</thead>
<tbody>
#foreach(var item in Model.UserCollection)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.UserId)</td>
<td>#Html.DisplayFor(modelItem => item.Name)</td>
<td>#Html.DisplayFor(modelItem => item.Email)</td>
<td>#Html.DisplayFor(modelItem => item.Phone1)</td></tr>
}
</tbody>
</table>
</div>
</div>
<div class="tab-pane" id="AddCl" style="padding-top: 10px; padding-left: 10px;">
<h4>Add Client</h4><hr style="border-top: 2px solid #096596;" />
#using (Html.BeginForm("ClientManager", "Home", FormMethod.Post))
{
#Html.ValidationSummary(true)
<div class="editor-label">
<strong>Client BO Account No.</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.BOAccountNo, new { size = 30 })
#Html.ValidationMessageFor(a => a.AddUserInfo.BOAccountNo)
</div>
<div class="editor-label">
<strong>Client USER ID</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.UserId)
#Html.ValidationMessageFor(a => a.AddUserInfo.UserId)
</div>
<div class="editor-label">
<strong>Client Password</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.Password)
#Html.ValidationMessageFor(a => a.AddUserInfo.Password)
</div>
<div class="editor-label">
<strong>Full Name</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.Name, new { size = 30 })
#Html.ValidationMessageFor(a => a.AddUserInfo.Name)
</div>
<div class="editor-label">
<strong>Address</strong>
</div>
<div class="editor-field">
#Html.TextBoxFor(a => a.AddUserInfo.AddressLine1, new { size = 30 })
#Html.ValidationMessageFor(a => a.AddUserInfo.AddressLine1)
</div>
#Html.HiddenFor(a => a.AddUserInfo.CreatedDate, new { #Value = System.DateTime.Now })
#Html.HiddenFor(a => a.AddUserInfo.IsActive, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsApproved, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsinfoMatched, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsReportView, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.IsVarified, new { #Value = "N" })
#Html.HiddenFor(a => a.AddUserInfo.UserType, new { #Value = "C" })
<br />
<p><input type="submit" class="btn btn-info" value="Add" /></p>
}
</div>
</div>
</div>
</body>

Your view expect BrManagement
#model MyMvc.Models.BrManagement
But you returned ClTable.AddUserInfo which is type of UserInfo, that is why you got that error.
To fix this, change return View(ClTable.AddUserInfo); to return View(ClTable); in your controller.

Related

ASP.NET MVC - add to a viewmodel list and submit

I have an ASP.NET MVC program with an order/odc request form. I have a customer, order and order item model. What I want to do is allow the user to place an order for a list of items to be approved. I have the viewmodel being passed to the form/view with a few fields including a list of order item objects. I am able to dynamically add rows to the table which shows the list of order items but on submit there is nothing in the viewmodel list. What am I doing wrong? How do I pass the items entered into the table to the view so that I can submit to the database?
Controller
public ActionResult NewOdc()
{
var viewModel = new NewOdcViewModel()
{
OdcItems = new List<tblOdcItem>()
};
viewModel.OdcItems.Add(new tblOdcItem());
return View(viewModel);
}
I call this code from jQuery to add a new item to the list:
public ActionResult GetView(string rowCount)
{
tblOdcItem item = new tblOdcItem();
return PartialView("_OdcItemEditor", item);
}
And on submit I call this code:
[HttpPost]
public ActionResult NewOdcSubmit(NewOdcViewModel viewModel)
{
_context.tblOdcs.Add(new tblOdc());
...
I'm using a foreach to go through the list and create a partial for each item.
View:
#using (Html.BeginForm("NewOdcSubmit", "Odc", FormMethod.Post))
{
if (Model != null)
{
#Html.HiddenFor(m => m.OdcItems);
}
<div class="panel panel-info">
<div class="panel-heading">
<h2 class="panel-title">Enter New ODC</h2>
</div>
<div class="panel-body">
#Html.AntiForgeryToken()
<div class="form-group">
#Html.LabelFor(model => model.User.UserName, new { #class = "col-md-2 col-sm-1 control-label" })
<div class="col-md-2 col-sm-3">
#Html.TextBoxFor(model => model.User.UserName, new { #Value = ((PM_Portal2020.Models.tblUser)Session["User"]).UserName, #readonly = true })
</div>
#Html.LabelFor(model => model.User.Phone, new { #class = "col-md-2 col-sm-1 control-label" })
<div class="col-md-2 col-sm-3">
#Html.TextBoxFor(model => model.User.Phone, new { #Value = ((PM_Portal2020.Models.tblUser)Session["User"]).Phone })
</div>
</div>
<div class="form-group col-md-10 col-sm-12">
<label>Expenses</label>
<table id="submissionTable" class="table table-bordered">
<thead>
<tr>
<th>Qty</th>
<th>Description</th>
<th>Estimated Cost</th>
</tr>
</thead>
<tbody>
#foreach (PM_Portal2020.Models.tblOdcItem item in Model.OdcItems)
{
#Html.Partial("_OdcItemEditor", item)
}
</tbody>
</table>
<p>
<button id="add" type="button" class="btn btn-primary">Add</button>
</p>
</div>
<div class="form-group col-lg-10 col-sm-12">
#Html.LabelFor(model => model.Details, new { #class = "col-md-2 col-sm-1 control-label" })
<div class="">
#Html.TextAreaFor(model => model.Details, new { #class = "form-control" })
</div>
</div>
</div>
<div class="panel-footer">
<div class="">
<button type="submit" class="btn btn-success">Save</button>
#Html.ActionLink("Back", "Index")
</div>
</div>
</div>
}
PartialView in Shared folder:
#model PM_Portal2020.Models.tblOdcItem
<tr #Html.Id("tablerow" + Model.ID)>
<td>
<div class="editor-field">
#Html.TextBoxFor(model => model.Quantity, new { #class = "text-box single-line", name = "Quantity[" + Model.ID + "]", type = "text", value = "", required = "required" })
</div>
</td>
<td>
<div class="editor-field">
#Html.TextBoxFor(model => model.Description, new { #class = "text-box single-line", name = "Description[" + Model.ID + "]", type = "text", value = "", required = "required", id = "itemDesc" })
</div>
</td>
<td>
<div class="editor-field">
#Html.TextBoxFor(model => model.EstimatedCost, new { #class = "text-box single-line", name = "EstimatedCost[" + Model.ID + "]", type = "text", value = "", required = "required" })
</div>
</td>
<td>
<button type="button" class="btn btn-primary" onclick="removeTr(this);">
<span class="glyphicon glyphicon-trash"></span>
</button>
</td>
</tr>
View Model
public class NewOdcViewModel
{
public NewOdcViewModel()
{
}
public IList<tblOdcItem> OdcItems { get; set; }
public string Details { get; set; }
public int OdcId { get; set; }
public tblUser User { get; set; }
}
It submits to the controller but the odcitems list is always count = 0. Any help would be great. Thanks
Here is the javascript example, just use this function on add/delete operation to re-arrange name.
function RearangeName(){
var i = 0;
$("#submissionTable>tbody>tr").each(function () {
$(this).find("input").each(function () {
if ($(this).prop("name").indexOf('Quantity') > 0) {
$(this).attr('name', "OdcItems[" + i + "].Quantity");
}
if ($(this).prop("name").indexOf('Description') > 0) {
$(this).attr('name', "OdcItems[" + i + "].Description");
}
if ($(this).prop("name").indexOf('EstimatedCost') > 0) {
$(this).attr('name', "OdcItems[" + i + "].EstimatedCost");
}
});
i++;
});
}
the name should be matched with model property, so in partial view, you have set name as OdcItems[0].Quantity instead of Quantity[" + Model.ID + "].
#Html.TextBoxFor(model => model.Quantity, new { #class = "text-box single-line", name = "OdcItems[0].Quantity", type = "text", value = "", required = "required" })
eg.
OdcItems[0].Quantity
OdcItems[1].Quantity
OdcItems[2].Quantity
....
OdcItems[n].Quantity

Modify property in a list with razor

Say I want to modify a Movie in a view.
We can do it by the code.
#model MvcMovie.Models.Movie
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Movie</legend>
#Html.HiddenFor(model => model.ID)
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ReleaseDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ReleaseDate)
#Html.ValidationMessageFor(model => model.ReleaseDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Genre)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Genre)
#Html.ValidationMessageFor(model => model.Genre)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Price)
#Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
However it is for one movie. But I have many movies say 5. The movie model is a list. How can I loop through it?
Your controller/view model":
public class MovieViewModel
{
public int ID { get; set; }
public string Title { get; set; }
}
public class HomeController : Controller
{
[HttpPost]
public ActionResult IndexValid3(IList<MovieViewModel> movieViewModel)
{
//set breakpoint here and update db here
return View(movieViewModel);
}
public ActionResult IndexValid3()
{
IList<MovieViewModel> list = new List<MovieViewModel>();
var movieViewModel = new MovieViewModel { ID = 1, Title = "title1"};
var movieViewModel2 = new MovieViewModel { ID = 1, Title = "title2"};
list.Add(movieViewModel);
list.Add(movieViewModel2);
return View(list);
}
View:
#model IList<Testy20161006.Controllers.MovieViewModel>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>IndexValid3</title>
</head>
<body>
<div>
#using (Html.BeginForm())
{
<table>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>#Html.TextBoxFor(m => Model[i].ID)</td>
<td>#Html.TextBoxFor(m => Model[i].Title)</td>
</tr>
}
</table>
<input type="submit" value="submit" />
}
</div>
</body>

mvc No data in ActionResult method after submit

I have an Index page on which there is a section to write a project name and select from a dropdownlist a project type.
Below that I have a submit button that directs to the ActionResult method Create in the Projects controller.
Code:
[UPDATE]
index.cshtml:
#using reqcoll.ViewModels
#model myViewModel
#{
ViewBag.Title = "ReqColl - project";
}
#* First half *#
#using (Html.BeginForm("CreateProject", "Projects"))
{
#Html.AntiForgeryToken()
<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
#RenderTopHalf(Model.modelProject)
</div>
}
#* Second half *#
#using (Html.BeginForm("CreateRequirement", "Projects"))
{
#Html.AntiForgeryToken()
<div class="form-group" id="pnSecondHalf">
#* Requirements list *#
<div class=" col-md-6 col-lg-6 col-sm-12">
#RenderBottomLeftHalf(Model.modelRequirement)
</div>
#* New/Edit requirements panel *#
<div class="col-md-6 col-lg-6 col-sm-12">
#RenderBottomRightHalf(Model.modelRequirement)
</div>
</div>
}
#* ================================================================================= ============= *#
#* Helpers *#
#helper RenderTopHalf(reqcoll.Models.Project project)
{
<div class=" well">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
#Html.LabelFor(model => project.projectName, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.TextBoxFor(model => project.projectName, htmlAttributes: new { #class = "ProjectNameInput" })
#Html.ValidationMessageFor(model => project.projectName)
</div>
</div>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row row-spacing">
#Html.LabelFor(model => project.projectType, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.DropDownListFor(model => project.projectType, new SelectList(
new List<Object>{
new { value = 0 , text = "...Select..." },
new { value = 1 , text = "Windows application" },
new { value = 2 , text = "Web application" },
new { value = 3 , text = "Device application"}
},
"value",
"text",
project.projectType), htmlAttributes: new { #class = "DropDownList" })
#Html.ValidationMessageFor(model => project.projectType)
</div>
<input type="hidden" value="" id="hdProjectID" />
</div>
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Create" />
</div>
<div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Edit" />
|
<input type="submit" class="btn btn-default" value="Delete" />
</div>
</div>
</div>
}
#helper RenderBottomLeftHalf(reqcoll.Models.Requirement requirement)
{
<div class=" well">
<table class="table">
<tr>
<th>
#if (Model.modelProject.Requirements != null)
{
var m = Model.modelProject;
if (m.Requirements.Count > 0)
{
#Html.DisplayNameFor(model => model.modelProject.Requirements[0].shortDesc)
}
}
else
{
<label class="label label-primary col-sm-12 col-md-6 col-lg-6">No requirements available</label>
}
</th>
<th></th>
</tr>
#if (Model.modelProject.Requirements != null)
{
var m = Model.modelProject;
if (m.Requirements.Count > 0)
{
foreach (var item in Model.modelProject.Requirements)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.shortDesc)
</td>
<td>
#* buttons here*#
#*#Html.ActionLink("E", "Edit", new { id = item.requirementID }) |
#Html.ActionLink("D", "Delete", new { id = item.requirementID })*#
</td>
</tr>
}
}
}
</table>
</div>
}
#helper RenderBottomRightHalf(reqcoll.Models.Requirement requirement)
{
<div class=" well">
#Html.ValidationSummary(true)
<div class="row">
#Html.LabelFor(model => requirement.shortDesc, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12">
#Html.TextBoxFor(model => requirement.shortDesc, htmlAttributes: new { #class = "RequirementShortDesc" })
#Html.ValidationMessageFor(model => requirement.shortDesc)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => requirement.longDesc, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12 RequirementLongDesc">
#Html.EditorFor(model => requirement.longDesc)
#Html.ValidationMessageFor(model => requirement.longDesc)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => requirement.priorityCode, htmlAttributes: new { #class = "control-label col-md-4 col-lg-4 col-sm-12" })
<div class="col-md-8 col-lg-8 col-sm-12">
#foreach (var value in Enum.GetValues(requirement.priorityCode.GetType()))
{
<div class="control-label col-sm-5 col-md-5 col-lg-5">
#Html.RadioButtonFor(m => requirement.priorityCode, value)
#Html.Label(value.ToString())
</div>
}
#Html.ValidationMessageFor(model => requirement.priorityCode)
</div>
</div>
<input type="hidden" value="" id="hdRequirementID" />
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnReqCreate" class=" col-sm-12 col-md-6 col-lg-6">
#* submit button here *#
#*#Html.ActionLink("Add", "Add", "Requirement", new { #class = "btn btn-default btnSize" })*#
</div>
<div id="pnReqEdit" class=" col-sm-12 col-md-6 col-lg-6">
#* submit buttons here *#
#*#Html.ActionLink("Edit", "Edit", "Requirement", new { #class = "btn btn-default btnSize" })
#Html.ActionLink("Delete", "Delete", "Requirement", new { #class = "btn btn-default btnSize" })*#
</div>
</div>
</div>
}
#section Scripts {
<script>
$(function () {
var pID = $('#hdProjectID').val();
if (pID != null) {
if (pID.length > 0) {
$('#pnEdit').show();
$('#pnCreate').hide();
$('#pnSecondHalf').show();
} else {
$('#pnEdit').hide();
$('#pnCreate').show();
$('#pnSecondHalf').hide();
}
} else {
$('#pnEdit').hide();
$('#pnCreate').show();
$('#pnSecondHalf').hide();
}
var rID = $('#hdRequirementID').val();
if (rID != null) {
if (rID.length > 0) {
$('#pnReqEdit').show();
$('#pnReqCreate').hide();
} else {
$('#pnReqEdit').hide();
$('#pnReqCreate').show();
}
} else {
$('#pnReqEdit').hide();
$('#pnReqCreate').show();
}
});
</script>
#Scripts.Render("~/bundles/jqueryval")
}
ViewModel:
using reqcoll.Models;
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project modelProject;
public Requirement modelRequirement;
}
}
Controller:
using System.Web.Mvc;
using reqcoll.Models;
using reqcoll.ViewModels;
namespace reqcoll.Controllers
{
public class ProjectsController : Controller
{
private myContext db = new myContext();
// GET: Projects
public ActionResult Index()
{
// allow more than one model to be used in the view
var vm = new myViewModel()
{
modelProject = new Project() { projectName = "test", projectType = 1 },
modelRequirement = new Requirement() { requirementID = -1 },
};
return View(vm);
}
[HttpPost]
[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateProject(myViewModel vm)
{
if (vm != null)
{
var ab = Request.Form;
// key 1: __RequestVerificationToken
// key 2: project.projectName
// key 3: project.projectType
if (ModelState.IsValid)
{
Project project = vm.modelProject;
// db.Project.Add(project.Item1);
// db.SaveChanges();
// return RedirectToAction("Index");
}
}
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
[ORIGINAL]
#using (Html.BeginForm("Create", "Projects"))
{
#Html.AntiForgeryToken()
<div class="top-spacing col-md-12 col-lg-12 col-sm-12">
<div class=" well">
#Html.ValidationSummary(true)
<div class="row">
#Html.LabelFor(model => model.Item1.projectName, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.TextBoxFor(model => model.Item1.projectName, htmlAttributes: new { #class = "ProjectNameInput" })
#Html.ValidationMessageFor(model => model.Item1.projectName)
</div>
</div>
#Html.ValidationSummary(true)
<div class="row row-spacing">
#Html.LabelFor(model => model.Item1.projectType, htmlAttributes: new { #class = "control-label col-md-2 col-lg-2 col-sm-12" })
<div class="col-md-10 col-lg-10 col-sm-12">
#Html.DropDownListFor(model => model.Item1.projectType, new SelectList(
new List<Object>{
new { value = 0 , text = "...Select..." },
new { value = 1 , text = "Windows application" },
new { value = 2 , text = "Web application" },
new { value = 3 , text = "Device application"}
},
"value",
"text",
0), htmlAttributes: new { #class = "DropDownList" })
#Html.ValidationMessageFor(model => model.Item1.projectType)
</div>
<input type="hidden" value="" id="hdProjectID" />
</div>
<div class="row top-spacing col-md-offset-5 col-sm-offset-5">
<div id="pnCreate" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Create" />
</div>
<div id="pnEdit" class=" col-sm-4 col-md-4 col-lg-4">
<input type="submit" class="btn btn-default" value="Edit" />
|
<input type="submit" class="btn btn-default" value="Delete" />
</div>
</div>
</div>
</div>
}
ProjectsController:
private myContext db = new myContext();
// GET: Projects
public ActionResult Index()
{
// allow more than one model to be used in the view
return View(new Tuple<Project, Requirement, Priority>(new Project(), new Requirement(), new Priority()));
}
[HttpPost]
[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "projectName,projectType")] Project project)
{
if (ModelState.IsValid)
{
db.Project.Add(project);
db.SaveChanges();
return RedirectToAction("Index");
}
return RedirectToAction("Index");
}
So when the submit button is clicked, the ActionResult Create is called, but the ModelState is not valid and does not have the information enterd by the user.
What am I doing wrong?
Your model is looking like complex object as you are using model.Item1.projectName and model.Item1.projectType, but in action method you are trying to get values directly which is wrong.
[Updated code]
With the new code posted, this quick correction to your model will allow it to bind correctly from your view:
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project project;
public Requirement requirement;
}
}
[Original]
Despite the fact of using a Tuple<> type instead of defining a class that would encapsulate the data to pass to the view. You can still achieve what you want by creating a helper in your view.
#helper RenderMyProject(Project project) {
...
#Html.TextBoxFor(x=> project.projectType)
...
}
Then, you will call this helper
#RenderMyProject(model.Item1)
Whats the difference?
The name of the input will change. Instead of posting [Item1.projectType] Inside the response object to your controller, it will look like [project.projectType] which will be mapped to your project parameter automatically.
Found the problem.
I added {get; set;} in the myViewModel to both the models and then it worked.
so:
using reqcoll.Models;
namespace reqcoll.ViewModels
{
public class myViewModel
{
public Project Project { get; set; }
public Requirement Requirement { get; set; }
}
}

Ajax form with model errors

I created an Ajax form in mvc 4 like that
#using (Ajax.BeginForm("Create", ajaxOptions: new AjaxOptions { UpdateTargetId = "updatedDiv", OnFailure = "OnFailure" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div id="Errors" class="block">
</div>
#*<div class="block width-50">
<div class="input-group" style="direction: ltr">
<input type="text" class="form-control">
<span class="input-group-addon">Incoming No</span>
</div>
</div>*#
<div class="block" id="item-guarantee">
#Html.RadioButtonFor(m => m.CorrespondenceSideId, 1, new { #checked = "checked" })<label class="label-style">#Global.CorrespondenceSide_Internal</label>
#Html.RadioButtonFor(m => m.CorrespondenceSideId, 2)<label class="label-style">#Global.CorrespondenceSide_External</label>
#Html.ValidationMessageFor(m => m.CorrespondenceSideId)
</div>
<div class="block">
<div class="input-group">
#Html.Label(Global.Correspondence_CorrespondenceNo)
#Html.EditorFor(m => m.CorrespondenceNo)
#Html.ValidationMessageFor(m => m.CorrespondenceNo)
</div>
</div>
<div class="block">
<div class="input-group">
#Html.Label(Global.Correspondence_IncomingNo)
#Html.EditorFor(m => m.IncomingNo)
#Html.ValidationMessageFor(m => m.IncomingNo)
</div>
</div>
}
and this is the controller
public ActionResult Create(Correspondence model)
{
ViewBag.BoxType = (Enum_BoxType)model.BoxTypeId;
ViewBag.CorrespondenceTypesList = this.Factory.Get<CorrespondenceTypesService>()
.GetAsListItems(this.CurrentLanguage);
ViewBag.AssignmentSidesList = this.Factory.Get<AssignmentSidesService>()
.GetAsListItems(this.CurrentLanguage);
ViewBag.IncomingSidesList = this.Factory.Get<IncomingSidesService>()
.GetAsListItems(this.CurrentLanguage);
ViewBag.Lookup_BoxTypes = this.Factory.Get<BoxTypesServices>().GetAsListItems(this.CurrentLanguage, (int)ViewBag.BoxType);
if (!ModelState.IsValid) return PartialView("_CreatePartial", model);
this.Factory.Get<CorrespondencesService>().AuthorizedAdd(model);
var AllCorrespondences = this.Factory.Get<CorrespondencesService>().GetAll(correspondence => correspondence.Date, (Enum_BoxType)model.BoxTypeId).ToList();
return new View("Index", AllCorrespondences.ToPagedList(1, 5));
}
Now when I return PartialView("_CreatePartial", model); and model returns with model errors, that errors doesn't appear in 'validationsummary()' in the partial

Passing Model in ViewModel to controller get null (Edit Form)

This edit form was already success, then i want to add add comment to this form, to do this i'm following this article
http://www.arrangeactassert.com/when-to-use-html-renderpartial-and-html-renderaction-in-asp-net-mvc-razor-views/
i create the viewmodel named CaseInternalEditViewModel
public class CaseInternalEditViewModel
{
public CaseInternalEditViewModel()
{
caseComment = new List<CaseComment>();
}
public String caseIDComment { get; set; }
public CaseInternal caseInternal { get; set; }
public List<CaseComment> caseComment { get; set; }
}
and change model in View :
#model myCHMTest.Models.CaseInternalEditViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div class="container">
<fieldset>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<legend>CaseInternal</legend>
<div class="container">
#Html.HiddenFor(model => model.caseIDComment)
#Html.HiddenFor(model => model.caseInternal.ID)
#Html.HiddenFor(model => model.caseInternal.CaseID)
#Html.HiddenFor(model => model.caseInternal.StatusID)
#* #Html.HiddenFor(model => model.caseInternal.CreatedNIK)*#
#Html.HiddenFor(model => model.caseInternal.CreatedBy)
#Html.HiddenFor(model => model.caseInternal.CreatedDt)
#Html.HiddenFor(model => model.caseInternal.SLA)
#Html.HiddenFor(model => model.caseInternal.SLAFlag)
#Html.HiddenFor(model => model.caseInternal.DatCreated)
#Html.HiddenFor(model => model.caseInternal.DayResolved)
#Html.HiddenFor(model => model.caseInternal.CategoryID)
<div class="sixteen columns">
<div class="fbbluebox">
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.CaseID)
#Html.DisplayFor(model => model.caseInternal.CaseID)
#Html.ValidationMessageFor(model => model.caseInternal.CaseID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.caseInternal.Title)
#Html.ValidationMessageFor(model => model.caseInternal.Title)
</div>
</div>
<hr />
</div>
<div class="one-third column">
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.BranchID)
</div>
<div class="editor-field">
#Html.DropDownList("BranchID")
#Html.ValidationMessageFor(model => model.caseInternal.BranchID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.ProjectID, "InternalProject")
</div>
<div class="editor-field">
#Html.DropDownList("ProjectID", null, new { #onchange = "javascript:cascadingdropdown();" })
#Html.ValidationMessageFor(model => model.caseInternal.ProjectID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.SubProjectID, "InternalSubProject")
</div>
<div class="editor-field">
#Html.DropDownList("SubProjectID", String.Empty)
#*#Html.DropDownListFor(model => model.SubProjectID, new SelectList(Enumerable.Empty<SelectListItem>()))*#
#Html.ValidationMessageFor(model => model.caseInternal.SubProjectID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.PengaduanID, "InternalPPengaduan")
</div>
<div class="editor-field">
#Html.DropDownList("PengaduanID", String.Empty)
#Html.ValidationMessageFor(model => model.caseInternal.PengaduanID)
</div>
</div>
<div class="one-third column">
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.CreatedNIK)
</div>
<div class="editor-field">
#* #Html.TextBoxFor(model => model.caseInternal.CreatedNIK, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.CreatedNIK)*#
<input type="text" name="InitialNIK" value="#Model.caseInternal.CreatedNIK" disabled="disabled"/>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.CreatedBy)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.CreatedBy, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.CreatedBy)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.CreatedDt)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.CreatedDt, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.CreatedDt)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.AssignGroupID)
</div>
<div class="editor-field">
#Html.DropDownList("AssignGroupID", null, new { #onchange = "javascript:memberdropdown();" })
#Html.ValidationMessageFor(model => model.caseInternal.AssignGroupID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.AssignMemberID)
</div>
<div class="editor-field">
#Html.DropDownList("AssignMemberID", String.Empty)
#Html.ValidationMessageFor(model => model.caseInternal.AssignMemberID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.StatusID)
</div>
<div class="editor-field">
#Html.DropDownList("StatusID",null, new { #disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.StatusID)
</div>
</div>
<div class="one-third column">
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.SLA)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.SLA, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.SLA)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.SLAFlag)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.SLAFlag, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.SLAFlag)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.DayResolved)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.DayResolved, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.DayResolved)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.DatCreated)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.caseInternal.DatCreated, new { disabled = "disabled" })
#Html.ValidationMessageFor(model => model.caseInternal.DatCreated)
</div>
</div>
<div class="sixteen columns">
<div class="fbgreybox" >
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.Description)
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.caseInternal.Description, new { style = "width: 100%; height: 100px;" })
#Html.ValidationMessageFor(model => model.caseInternal.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.caseInternal.LinkCase)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.caseInternal.LinkCase)
#Html.ValidationMessageFor(model => model.caseInternal.LinkCase)
</div>
</div>
<p>
<input type="submit" value="Save" class="uibutton large confirm"/>
#Html.ActionLink("Back to List", "Index", "CaseInternal", new { #class = "uibutton" })
</p>
</div>
</div>
}
</fieldset>
</div>
#using (Ajax.BeginForm("Comment", "CaseInternal", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "myGrid", OnSuccess = "done" }))
{
#*<input type="text" id="caseEka" name="caseEka" />*#
#Html.HiddenFor(model => model.caseIDComment)
<input type="text" id="Comment" name="Comment"/>
}
<div id="myGrid">
#Html.Partial("_showComment", Model.caseComment)
</div>
<script type="text/javascript">
function done() {
document.getElementById('Comment').value = '';
}
function cascadingdropdown() {
var idDept = $("#ProjectID").val();
var subProject = $('#SubProjectID').val();
var urlemp = '#Url.Action("GetSubProjectFromProjectID")';
var select = $('#SubProjectID');
$.ajax({
type: "POST",
url: urlemp,
data: { id: idDept },
error: function (jqXHR, textStatus, errorThrown) {
alert("error" + jqXHR.responseText);
},
success: function (returndata) {
if (returndata.ok) {
select.empty();
$.each(returndata.data, function (index, itemData) {
if (subProject == itemData.ID) {
select.append($('<option selected="selected"></option>').val(itemData.ID).html(itemData.SubProjectName));
} else {
select.append($('<option></option>').val(itemData.ID).html(itemData.SubProjectName));
}
});
select.show('slow');
// $("#ProjectID").attr("disabled", "disabled");
}
else {
window.alert(' error : ' + returndata.message);
}
}
}
);
}
function getNameNik() {
window.alert("AAAASSDSD");
var idDept = $("#CreatedNIK").val();
var urlemp = '#Url.Action("GetNameNik")';
$.ajax({
type: "POST",
url: urlemp,
data: { id: idDept },
error: function (jqXHR, textStatus, errorThrown) {
alert("error" + jqXHR.responseText);
},
success: function (returndata) {
if (returndata.ok) {
$('#nikLabel').text("");
$.each(returndata.data, function (index, itemData) {
$('#nikLabel').text(itemData.FirstName + " " + itemData.LastName);
});
}
else {
window.alert(' error : ' + returndata.message);
}
}
}
);
}
function memberdropdown() {
var idDept = $("#AssignGroupID").val();
var subProject = $('#AssignMemberID').val();
var urlemp = '#Url.Action("GetMemberFromGroupID")';
var select = $('#AssignMemberID');
$.ajax({
type: "POST",
url: urlemp,
data: { id: idDept },
error: function (jqXHR, textStatus, errorThrown) {
alert("error" + jqXHR.responseText);
},
success: function (returndata) {
select.empty();
if (returndata.ok) {
$.each(returndata.data, function (index, itemData) {
if (subProject == itemData.ID) {
select.append($('<option selected="selected"></option>').val(itemData.ID).html(itemData.UserName));
} else {
select.append($('<option></option>').val(itemData.ID).html(itemData.UserName));
}
});
select.show('slow');
// $("#ProjectID").attr("disabled", "disabled");
}
else {
window.alert(' error : ' + returndata.message);
}
}
}
);
}
function start() {
cascadingdropdown();
memberdropdown();
}
window.onload = start;
// window.onload = memberdropdown;
</script>
and here my controller:
public ActionResult Edit(string id)
{
CaseInternal caseinternal = db.CaseInternals.Find(id);
caseinternal.NullSafeTrimStrings();
ViewBag.PengaduanID = new SelectList(db.InternalPPengaduans, "ID", "PPengaduanName", caseinternal.PengaduanID);
ViewBag.ProjectID = new SelectList(db.InternalProjects, "ID", "ProjectName", caseinternal.ProjectID);
ViewBag.SubProjectID = new SelectList(db.InternalSubProjects, "ID", "SubProjectName", caseinternal.SubProjectID);
ViewBag.CategoryID = new SelectList(db.MasterCategories, "ID", "CategoryName", caseinternal.CategoryID);
ViewBag.AssignGroupID = new SelectList(db.MasterGroups, "ID", "GroupName", caseinternal.AssignGroupID);
ViewBag.AssignMemberID = new SelectList(db.MasterAssignUsers, "ID", "UserName", caseinternal.AssignMemberID);
ViewBag.BranchID = new SelectList(branchObject.A2BR, "BRCODE", "BRNAME", caseinternal.BranchID);
ViewBag.StatusID = new SelectList(db.MasterStatus, "ID", "StatusName", caseinternal.StatusID);
CaseInternalEditViewModel caseInternalEdit = new CaseInternalEditViewModel();
caseInternalEdit.caseInternal = caseinternal;
caseInternalEdit.caseIDComment = caseinternal.CaseID;
var commentCase = db.CaseComments.Where(p => p.CaseID == caseinternal.CaseID).OrderByDescending(p => p.CreatedDt);
foreach (CaseComment cas in commentCase)
{
caseInternalEdit.caseComment.Add(cas);
}
return View(caseInternalEdit);
}
[HttpPost]
public ActionResult Edit(CaseInternalEditViewModel caseinternalEdit)
{
//CaseInternalEditViewModel caseinternalEdit
CaseInternal caseinternal = caseinternalEdit.caseInternal;
if (ModelState.IsValid)
{
db.Entry(caseinternal).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.PengaduanID = new SelectList(db.InternalPPengaduans, "ID", "PPengaduanName", caseinternal.PengaduanID);
ViewBag.ProjectID = new SelectList(db.InternalProjects, "ID", "ProjectName", caseinternal.ProjectID);
ViewBag.SubProjectID = new SelectList(db.InternalSubProjects, "ID", "SubProjectName", caseinternal.SubProjectID);
ViewBag.CategoryID = new SelectList(db.MasterCategories, "ID", "CategoryName", caseinternal.CategoryID);
ViewBag.AssignGroupID = new SelectList(db.MasterGroups, "ID", "GroupName", caseinternal.AssignGroupID);
ViewBag.AssignMemberID = new SelectList(db.MasterAssignUsers, "ID", "UserName", caseinternal.AssignMemberID);
ViewBag.BranchID = new SelectList(branchObject.A2BR, "BRCODE", "BRNAME", caseinternal.BranchID);
ViewBag.StatusID = new SelectList(db.MasterStatus, "ID", "StatusName", caseinternal.StatusID);
return View(caseinternalEdit);
}
the modelstate is always invalid, because some field is null, field2 in dropdownlist is null when passing to controller.
is the viewbag the problem? should i change the name of viewbag?
#Html.EditorFor(model => model.caseInternal.Title)
is rendered to
<input class="text-box single-line" id="caseInternal_Title" name="caseInternal.Title" type="text" value="ViewModel" />
but dropdownlist
<select id="BranchID" name="BranchID"><option selected="selected" value="001">KANTOR PUSAT NON OPERASIONAL </option>
the different is the name, the branch should be caseinternal.branchID maybe it will work, but how to do that?
You have:
#Html.DropDownList("BranchID")
You want:
#Html.DropDownListFor(model => model.caseInternal.BranchID)
OR if you really don't want to use a DropDownListFor() for whatever reason....
#Html.DropDownList("caseInternal_BranchID")

Resources