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
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
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>
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; }
}
}
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
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")