Intelli-Seeker
asked on
ASP.NET MVC 5 with Entity Framework 6 - model type dictionary error.
ASP.NET MVC 5 with Entity Framework 6 - model type dictionary error.
Exception Details: System.InvalidOperationExc eption: The model item passed into the dictionary is of type 'System.Data.Entity.Dynami cProxies.C ustomer_C8 33F96E78FC 481F05AA3B 3A27DE9594 AE7D02E3CC 5F913A6C93 10908BA150 C1', but this dictionary requires a model item of type 'CRM.Models.CustomerModel' .
Customer Edit View (snip of code):
CustomerModel:
I should note that in this project, I used Entity Framework 6 scaffolding and connected to a SQL database. That created CRMModel.edmx and an auto-generated template CRMModel.Context class. I am using a specific model for this view. I don't know if that plays into this issue or not.
Exception Details: System.InvalidOperationExc
Customer Edit View (snip of code):
@model CRM.Models.CustomerModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customer</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.status_id, "Prospect Status", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(s => s.status_id, Model.status_id, "Please Select Prospect Status")
@Html.ValidationMessageFor(model => model.status_id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfidenceRating, "Confidence Rating", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(c => c.ConfidenceRating, Model.ConfidenceRating,"Please Select Confidence Rating")
@Html.ValidationMessage("Confidence Rating is required.")
</div>
</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>
}
CustomerModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace CRM.Models
{
public class CustomerModel
{
[Display (Name = "System of Record ID")]
public string SystemOfRecordId { get; set; }
[Display(Name = "Customer Name")]
public string Name { get; set; }
[Display (Name="Prospect Status")]
public SelectList status_id { get; set; }
[Display (Name="Confidence Rating")]
public SelectList ConfidenceRating { get; set; }
public Boolean IsBusinessCustomer { get; set; }
public int Id { get; set; }
}
}
I should note that in this project, I used Entity Framework 6 scaffolding and connected to a SQL database. That created CRMModel.edmx and an auto-generated template CRMModel.Context class. I am using a specific model for this view. I don't know if that plays into this issue or not.
ASKER
Sorry, of course you would need that. My mistake. Thanks for looking at my question.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using CRM.Models;
namespace CRM.Controllers
{
public class CustomersController : Controller
{
private CRMEntities db = new CRMEntities();
// GET: Customers
public ActionResult Index(string id)
{
string searchString = id;
var customers = from c in db.Customers
select c;
if (!String.IsNullOrEmpty(searchString))
{
customers = customers.Where(c => c.Name.Contains(searchString));
}
return View(customers); //the view is the Index view of the CustomersController
}
// GET: Customers/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
//{
// var Details = new List<CustomerViewModel>();
// {
// Details = Customer.Select(a => new CustomerViewModel()
// {
// }
// }
//}
return View(customer);
}
// GET: Customers/Create
public ActionResult Create(CustomerModel model)
{
if (model.ConfidenceRating==null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id==null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share", Value="2"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(model);
}
// POST: Customers/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,SystemOfRecordId,Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
//this if statement checks to make sure everything is valid in the form and if so, it saves to the database and redirects to the Details page
//using the Id of the newly created customer.
if (ModelState.IsValid)
{
db.Customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Details", new { Id = customer.Id });
}
//if there is something invalid in the form, then it redirects to the Customer view.
return View(customer);
}
// GET: Customers/Edit/5
public ActionResult Edit(CustomerModel model, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id == null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share", Value="2"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(customer);
}
// POST: Customers/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,SystemOfRecordId,/*Relationship,*/Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
if (ModelState.IsValid)
{
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customer);
}
// GET: Customers/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
return View(customer);
}
// POST: Customers/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Customer customer = db.Customers.Find(id);
db.Customers.Remove(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Hi again,
Could you please point out exactly where you get this error? Where you were before and what were you trying to do? Could you also paste the whole error?
Giannis
Could you please point out exactly where you get this error? Where you were before and what were you trying to do? Could you also paste the whole error?
Giannis
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Will this change cause any issues with posting changes to the database? I am trying to avoid making changes to the Customer class that was created by the entity framework template. That is why I created a CustomerModel class. I guess that is where my confusion is. The model class that I am using is "CustomerModel" but the model in Entity Framework is Customer and the database table is Customer.
ASKER
Thanks. I was using the templates created by scaffolding. I made the edits to the controller and view below. As soon as I click on the Edit link in the Customers view I received the dictionary error. I will just paste everything below rather than giving you snips. That may make it easier for you to follow. I apologize - I am new to MVC. This is a work in progress.
customers controller:
Customers - Edit view:
CustomerModel.cs:
customers controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using CRM.Models;
namespace CRM.Controllers
{
public class CustomersController : Controller
{
private CRMEntities db = new CRMEntities();
// GET: Customers
public ActionResult Index(string id)
{
string searchString = id;
var customers = from c in db.Customers
select c;
if (!String.IsNullOrEmpty(searchString))
{
customers = customers.Where(c => c.Name.Contains(searchString));
}
return View(customers); //the view is the Index view of the CustomersController
}
// GET: Customers/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
//{
// var Details = new List<CustomerViewModel>();
// {
// Details = Customer.Select(a => new CustomerViewModel()
// {
// }
// }
//}
return View(customer);
}
// GET: Customers/Create
public ActionResult Create(CustomerModel model)
{
if (model.ConfidenceRating==null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id==null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share", Value="2"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(model);
}
// POST: Customers/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,SystemOfRecordId,/*Relationship,*/Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
//this if statement checks to make sure everything is valid in the form and if so, it saves to the database and redirects to the Details page
//using the Id of the newly created customer.
if (ModelState.IsValid)
{
db.Customers.Add(customer);
db.SaveChanges();
return RedirectToAction("Details", new { Id = customer.Id });
}
//if there is something invalid in the form, then it redirects to the Customer view.
return View(customer);
}
// GET: Customers/Edit/5
public ActionResult Edit(int? Id)
{
var model = new CustomerModel();
if (Id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(Id);
model = new CustomerModel();
Id = customer.Id;
if (customer == null)
{
return HttpNotFound();
}
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id == null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share", Value="2"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(customer);
}
// POST: Customers/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,SystemOfRecordId,/*Relationship,*/Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
if (ModelState.IsValid)
{
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customer);
}
// GET: Customers/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(id);
if (customer == null)
{
return HttpNotFound();
}
return View(customer);
}
// POST: Customers/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Customer customer = db.Customers.Find(id);
db.Customers.Remove(customer);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
Customers - Edit view:
@model CRM.Models.CustomerModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customer</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)
<div class="form-group">
@Html.LabelFor(model => model.SystemOfRecordId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SystemOfRecordId, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SystemOfRecordId, "", new { @class = "text-danger" })
</div>
</div>
@*<div class="form-group">
@Html.LabelFor(model => model.Relationship, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Relationship, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Relationship, "", new { @class = "text-danger" })
</div>
</div>*@
<div class="form-group">
@Html.LabelFor(model => model.Tin, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Tin, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Tin, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
@*<div class="form-group">
@Html.LabelFor(model => model.status_id, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.status_id, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.status_id, "", new { @class = "text-danger" })
</div>*@
<div class="form-group">
@Html.LabelFor(model => model.status_id, "Prospect Status", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(s => s.status_id, Model.status_id, "Please Select Prospect Status")
@Html.ValidationMessageFor(model => model.status_id, "", new { @class = "text-danger" })
</div>
</div>
@*<div class="form-group">
@Html.LabelFor(model => model.ConfidenceRating, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.ConfidenceRating, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.ConfidenceRating, "", new { @class = "text-danger" })
</div>*@
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfidenceRating, "Confidence Rating", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(c => c.ConfidenceRating, Model.ConfidenceRating,"Please Select Confidence Rating")
@Html.ValidationMessage("Confidence Rating is required.")
</div>
@*<div class="form-group">
@Html.LabelFor(model => model.BankOfficer, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.BankOfficer, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.BankOfficer, "", new { @class = "text-danger" })
</div>*@
</div>
<div class="form-group">
@Html.LabelFor(model => model.TrustOfficer, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.TrustOfficer, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.TrustOfficer, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.IsBusinessCustomer, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.IsBusinessCustomer)
@Html.ValidationMessageFor(model => model.IsBusinessCustomer, "", new { @class = "text-danger" })
</div>
</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>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
CustomerModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace CRM.Models
{
public class CustomerModel
{
[Display (Name = "System of Record ID")]
public string SystemOfRecordId { get; set; }
public string Tin { get; set; }
[Display(Name = "Customer Name")]
public string Name { get; set; }
//public Int32 status_id { get; set; }
[Display (Name="Prospect Status")]
public SelectList status_id { get; set; }
//public IEnumerable<SelectListItem> ProspectStatus { get; set; }
//public Int32 ConfidenceRating { get; set; }
[Display (Name="Confidence Rating")]
public SelectList ConfidenceRating { get; set; }
//public IEnumerable<SelectListItem> ConfidenceRating { get; set; }
public string BankOfficer { get; set; }
public string TrustOfficer { get; set; }
public Boolean IsBusinessCustomer { get; set; }
public int Id { get; set; }
//public virtual DbSet<Customer> Customers { get; set; }
}
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
The property names are what are throwing this error?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
You are awesome! Yes, I am new to MVC and was using boilerplate code as well a s some tutorials that I found online. You made much more sense out of my messy code. I will work on it and close the question if everything is working properly.
Let me know if you need anything else.
Giannis
Giannis
ASKER
That worked splendidly! Now I just need to do some minor cleanup on the HTML code and apply this same concept to other views that I have. I have a Meetings controller and views where I need to do the same type of querying. Thanks for your help!
ASKER
Thanks a million! You gave me a better understanding of MVC in a practical sense related to my specific project. I will use what you explained to enhance everything else in this project.
Glad to help.... :D
ASKER
Could you possibly share the latest View and Controller code for the Edit?
ASKER
Edit view:
CustomersController (Edit section):
@model CRM.Models.CustomerModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customer</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)
<div class="form-group">
@Html.LabelFor(model => model.SystemOfRecordId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.SystemOfRecordId, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.SystemOfRecordId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Tin, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Tin, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Tin, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.status_id, "Prospect Status", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(s => s.status_id, Model.status_id, "Please Select Prospect Status")
@Html.ValidationMessageFor(model => model.status_id, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ConfidenceRating, "Confidence Rating", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.DropDownListFor(c => c.ConfidenceRating, Model.ConfidenceRating, "Please Select Confidence Rating")
@Html.ValidationMessage("Confidence Rating is required.")
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.TrustOfficer, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.TrustOfficer, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.TrustOfficer, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.IsBusinessCustomer, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
@Html.EditorFor(model => model.IsBusinessCustomer)
@Html.ValidationMessageFor(model => model.IsBusinessCustomer, "", new { @class = "text-danger" })
</div>
</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>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
CustomersController (Edit section):
// GET: Customers/Edit/5
public ActionResult Edit(int? Id)
{
var model = new CustomerModel();
if (Id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(Id);
model = new CustomerModel();
if (customer == null)
{
return HttpNotFound();
}
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id == null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="Share", Value="2"},
new SelectListItem(){Text="Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(model);
}
// POST: Customers/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,SystemOfRecordId,/*Relationship,*/Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
if (ModelState.IsValid)
{
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", new { Id = customer.Id });
}
return View(customer);
}
In your action you create a new CustomerModel, but never populate it.
This will have its properties not initialized.
Try populating them like so:
Giannis
model = new CustomerModel();
This will have its properties not initialized.
Try populating them like so:
Customer customer = db.Customers.Find(Id);
model = new CustomerModel{
Name = customer .Name,
Id = customer.Id,
// <--- other properties here.
};
Giannis
ASKER
Can you use a selectlist property when populating the model? The CustomerModel class has a SelectList defined for status_id and I want that to populate that in the Edit view. when I enter status_id = customer.status_id, intellisense says that it cannon implicitly convert type 'int?' to System.Web.Mvc.SelectList' .
ASKER
Same issue with Boolean. Here is my code for the Edit section on the CustomersController.
// GET: Customers/Edit/5
public ActionResult Edit(int? Id)
{
var model = new CustomerModel();
if (Id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(Id);
model = new CustomerModel
{
SystemOfRecordId = customer.SystemOfRecordId,
Tin = customer.Tin,
Name = customer.Name,
ConfidenceRating = customer.ConfidenceRating,
status_id = customer.status_id,
TrustOfficer = customer.TrustOfficer,
IsBusinessCustomer = customer.IsBusinessCustomer
};
if (customer == null)
{
return HttpNotFound();
}
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id == null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="Share", Value="2"},
new SelectListItem(){Text="Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(model);
}
// POST: Customers/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,SystemOfRecordId,/*Relationship,*/Tin,Name,status_id,ConfidenceRating,BankOfficer,TrustOfficer,IsBusinessCustomer")] Customer customer)
{
if (ModelState.IsValid)
{
db.Entry(customer).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", new { Id = customer.Id });
}
return View(customer);
}
ASKER
Here is the CustomerModel class if needed. There is some extra code in there that is commented out when I was doing some testing. I am still learning the ropes as you can tell.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
namespace CRM.Models
{
public class CustomerModel
{
[Display (Name = "System of Record ID")]
public string SystemOfRecordId { get; set; }
[Display (Name = "TIN")]
public string Tin { get; set; }
[Display(Name = "Customer Name")]
public string Name { get; set; }
//public Int32 status_id { get; set; }
[Display (Name="Prospect Status")]
public SelectList status_id { get; set; }
//public IEnumerable<SelectListItem> ProspectStatus { get; set; }
//public Int32 ConfidenceRating { get; set; }
[Display (Name="Confidence Rating")]
public SelectList ConfidenceRating { get; set; }
//public IEnumerable<SelectListItem> ConfidenceRating { get; set; }
public string BankOfficer { get; set; }
public string TrustOfficer { get; set; }
public Boolean IsBusinessCustomer { get; set; }
public int Id { get; set; }
//public virtual DbSet<Customer> Customers { get; set; }
}
}
You can do what you used to do with the SelectList. Leave them null (ignore them ) during initialization and then populate them as you already do in this sample:
So if you do nothing for ConfidenceRating in the initialization (completely remove this row:
It will know it is null so it will initialize the list.
This will show you the dropdown in your browser but you are still missing the selected value.
In this case you need to define which item is selected.
SelectListItem has a property named 'Selected'. This is boolean and defines if the item is selected. So in the code above you could modify it as:
I do not have the source for your Customer entity, so i am just assuming that there is a property named 'ConfidenceRatingId'.
Let me know how it goes,
Giannis
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
So if you do nothing for ConfidenceRating in the initialization (completely remove this row:
ConfidenceRating = customer.ConfidenceRating,
It will know it is null so it will initialize the list.
This will show you the dropdown in your browser but you are still missing the selected value.
In this case you need to define which item is selected.
SelectListItem has a property named 'Selected'. This is boolean and defines if the item is selected. So in the code above you could modify it as:
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0", Selected = (customer.ConfidenceRatingId == 0)},
new SelectListItem(){Text="1 - Very Stable", Value="1", Selected = (customer.ConfidenceRatingId == 1)},
new SelectListItem(){Text="2 - Stable", Value="2", Selected = (customer.ConfidenceRatingId == 2)},
new SelectListItem(){Text="3 - At Risk", Value="3", Selected = (customer.ConfidenceRatingId == 3)},
}, "Value", "Text");
}
I do not have the source for your Customer entity, so i am just assuming that there is a property named 'ConfidenceRatingId'.
Let me know how it goes,
Giannis
ASKER
The edit view shows the Name in the edit screen, but does not show the item that was selected in the dropdown menus in the create view. It was saved to the database (I checked SQL). Here is a screenshot of the edmx.
Here is my updated CustomersController
Here is my updated CustomersController
// GET: Customers/Edit/5
public ActionResult Edit(int? Id)
{
var model = new CustomerModel();
if (Id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Customer customer = db.Customers.Find(Id);
model = new CustomerModel
{
SystemOfRecordId = customer.SystemOfRecordId,
Tin = customer.Tin,
Name = customer.Name,
TrustOfficer = customer.TrustOfficer,
//IsBusinessCustomer = customer.IsBusinessCustomer,
};
{
if (model.ConfidenceRating == null)
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0", Selected = (customer.ConfidenceRating == 0)},
new SelectListItem(){Text="1 - Very Stable", Value="1", Selected = (customer.ConfidenceRating == 1)},
new SelectListItem(){Text="2 - Stable", Value="2", Selected = (customer.ConfidenceRating == 2)},
new SelectListItem(){Text="3 - At Risk", Value="3", Selected = (customer.ConfidenceRating == 3)},
}, "Value", "Text");
{
if (model.status_id == null)
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0", Selected = (customer.status_id == 0)},
new SelectListItem(){Text="Existing Customer", Value="1", Selected = (customer.status_id == 1)},
new SelectListItem(){Text="River Valley Referral – Share", Value="2", Selected = (customer.status_id == 2)},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3", Selected = (customer.status_id == 3)},
}, "Value", "Text");
}
};
if (customer == null)
{
return HttpNotFound();
}
if (model.ConfidenceRating == null)
{
model.ConfidenceRating = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="", Value="0"},
new SelectListItem(){Text="1 - Very Stable", Value="1"},
new SelectListItem(){Text="2 - Stable", Value="2"},
new SelectListItem(){Text="3 - At Risk", Value="3"},
}, "Value", "Text");
}
if (model.status_id == null)
{
model.status_id = new SelectList(new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share", Value="2"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
}, "Value", "Text");
}
return View(model);
}
Could you possibly upload the project in Experts Exchange so i could have a look? I do not know if thisis a sample project or it contains sensitive info. It is kind of hard to check it like this though, cause some debugging would be helpful.
ASKER
Is it possible to send it directly to you rather than through Experts Exchange?
You can find me at jyparask gmail
ASKER
I sent you a link to a shared Dropbox folder.
Will check and let you know
ASKER
Any thoughts after reviewing the solution?
Hi,
I was really puzzled about this until i reallised that you are passing a SelectList into status_id. Your model should have separate properties for the id and for the SelectList.
For instance your Customer Model should have the following properties:
then your controller would populate them accordingly:
and your view would show as:
The DropDownListFor helper expects the property where it will supply the value as a first parameter, and an IEnumerable of SelectionListItem as a second parameter. As you had it, it would not bind the values correctly.
Let me know how it goes.
I was really puzzled about this until i reallised that you are passing a SelectList into status_id. Your model should have separate properties for the id and for the SelectList.
For instance your Customer Model should have the following properties:
[Display (Name="Prospect Status")]
public int? status_id { get; set; }
public IEnumerable<SelectListItem> ProspectStatus { get; set; }
then your controller would populate them accordingly:
model = new CustomerModel
{
SystemOfRecordId = customer.SystemOfRecordId,
Tin = customer.Tin,
Name = customer.Name,
TrustOfficer = customer.TrustOfficer,
//IsBusinessCustomer = customer.IsBusinessCustomer,
status_id = customer.status_id
};
...
model.ProspectStatus = new List<SelectListItem>(){
new SelectListItem(){Text="Prospective Customer", Value="0"},
new SelectListItem(){Text="Existing Customer", Value="1"},
new SelectListItem(){Text="River Valley Referral – Share"},
new SelectListItem(){Text="River Valley Referral – Do Not Share", Value="3"},
};
}
and your view would show as:
@Html.DropDownListFor(s => s.status_id, Model.ProspectStatus, "Please Select Prospect Status")
The DropDownListFor helper expects the property where it will supply the value as a first parameter, and an IEnumerable of SelectionListItem as a second parameter. As you had it, it would not bind the values correctly.
Let me know how it goes.
Could you please provide the code in your controller?
Giannis