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.InvalidOperationException: The model item passed into the dictionary is of type 'System.Data.Entity.DynamicProxies.Customer_C833F96E78FC481F05AA3B3A27DE9594AE7D02E3CC5F913A6C9310908BA150C1', but this dictionary requires a model item of type 'CRM.Models.CustomerModel'.

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>
}

Open in new window


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

Open in new window


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.
Intelli-SeekerAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ioannis ParaskevopoulosCommented:
Hi,

Could you please provide the code in your controller?

Giannis
0
Intelli-SeekerAuthor Commented:
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);
        }
    }
}

Open in new window

0
Ioannis ParaskevopoulosCommented:
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
0
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference ithrough the Colors of STEM program.

Ioannis ParaskevopoulosCommented:
Ok, i think i see your issue here.

Your View expects something of CustomerModel, as defined in your Models folder. In your Edit action though you are passing a Customer object, which is the Entity as defined in your Entities. You should create a CustomerModel out of the Customer entity and pass this in the view.

Check the following snippet:

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

            ///
            ///Your view is expecting a CustomerModel but you are returning a Customer
            ///
            return View(customer);
        }

Open in new window


Try something like this:

            Customer customer = db.Customers.Find(id);
            model = new CuatomerModel{
                id= customer.id
                ///...other code to bind the properties you get from the Customer object
            };
///...other code

            return View(customer);
        }

Open in new window


To be honest, i am not sure why your Get Edit action expect a CustomerModel as an input. You should only ask for the id and define/create a CustomerModel in the action:

        // GET: Customers/Edit/5
        public ActionResult Edit(int? id)
        {
            var model = new CustomerModel();

Open in new window


You have a similar problem in the POST Edit action, though you should have the CustomerModel in the method definition as you currently do. But if the modelstate has errors and you return the View, again you are including an object of type Customer instead of CustomerModel.

I hope this helps,
Giannis
1
Intelli-SeekerAuthor Commented:
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.
0
Intelli-SeekerAuthor Commented:
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:

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

Open in new window


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

Open in new window


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

Open in new window

0
Ioannis ParaskevopoulosCommented:
You should reflect back the changes to the models.

For instance if you change the name in the edit form you should handle that in the controller and say:

customer.Name = model.Name;

Open in new window


You should do that for every property. You do not need to check if a property has changed, just replace them.

Of corse there are scenarios where you would want to do the check.

Take for instance a case where you would allow a client to post only the changes. For instance if they change the name they would post only the changed name. In that case all other properties would be null or the default value, so you would need to check which properties are sent in order to only update these. But in your case, you send back to the controller the full object, so you should be fine.

Of course you should TEST TEST TEST that everything is indeed ok.

If you are woried if any relationships would be altered in the database, no unless you say so. But still do not take my word for it.

Giannis
1
Intelli-SeekerAuthor Commented:
The property names are what are throwing this error?
0
Ioannis ParaskevopoulosCommented:
No,

I am not sure how much you know about MVC, but since you say you are new i will say a few things instead of considering them granted.

In your view you define the type of the Model this view is expecting to get from the Controller. This is defined by the following line which is usually on the top of the file:

@model CRM.Models.CustomerModel

Open in new window


The view is expecting this type and only this. If it gets any other type from the controller it will throw the error you are receiving stating tha it was expecting this but got something else.

Do put a beakpoint in the line where you are returning the view and hover the parameter passed and see what is its type. You will notice it is not CRM.Models.CustomerModel as it should.

Let's take a look at your GET Edit action (I am removing some irrelevant code):

        //This Action is expecting a specific id and it will try to find it in the db so it will return the view with the details of this customer.
        //We have separate models for the db and the view, because they serve different purposes and usually have different properties 
        //behaviours etc. For instance, in your case the CustomerModel has two SelectionList properties, that have absolutely no use in the db 
        //context, but make perfect sense in your View.

        //So what you need is get the entry from the db, transform it into something the View will understad and return it.

        // GET: Customers/Edit/5
        public ActionResult Edit(int? Id)
        
        {
            //Here you are creating a new model that the View will understand. This is currently empty, so we need to fill in the blanks.
            var model = new CustomerModel();

            //This check could go first, as there is not point in creating an empty object if you are not going to use it.
            if (Id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }

            //With this you are fetching your data from the DB. You should use this in order to fill in whatever blanks you can of the model. I say
            //whatever blanks you can, cause for instance you may not fill in the SelectionLists out of it.
            Customer customer = db.Customers.Find(Id);

            //You are re-initialising the model here. Why? It is already new a few lines above. To be honest, the declaration should go after checking if the customer exists.
            model = new CustomerModel();

            //This is a potential runtime error and it is also wrong in general. First of all, you are using the customer's id before checking if the 
            //customer exists, which you do right after that. So if the customer does not exist you will get a Null Refference exception. It is also 
            //wrong in general, cause `Id` is already equal with customer.Id, unless of course the customer with this id does not exist which is 
            //covered by what i said above. Remove this line completely.
            Id = customer.Id;
                
            //Now you check if the customer exists. Good...
                if (customer == null)
                {
                    return HttpNotFound();
                }

//removed some code here in order to make it shorter. Do not remove this from your code....


                //Try a breakpoint here. When you hit the breakpoint hover the ustomer and see, what is its type? It should be something like 
                //CRM.Entities.Customer. But, hey.... the view is expecting something of type CRM.Models.CustomerModel. What did you miss???
                //Well..... you currently have an empty CustomerModel, that you created twice but did nothing else with it. 

                //So here is the time where you start filling in the blanks. For instance.....     
                //model.Id = customer.Id; 
                //model.Name = customer.Name;

                //Or even better, here should be the place where you should declare and initialize your model like so:
                //var model = new CustomerModel
                //{
                //    Id = customer.Id,
                //    Name = customer.Name,
                //    ...more properties here
                //};
 
                //and finally return the model instead of the customer:
                //return View(model);

                return View(customer);
            }

Open in new window



I hope it makes some more sense now,
Giannis
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Intelli-SeekerAuthor Commented:
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.
0
Ioannis ParaskevopoulosCommented:
Let me know if you need anything else.

Giannis
0
Intelli-SeekerAuthor Commented:
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!
0
Intelli-SeekerAuthor Commented:
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.
0
Ioannis ParaskevopoulosCommented:
Glad to help.... :D
1
Intelli-SeekerAuthor Commented:
One thing that I still need to figure out with this edit view is that it goes to the correct Id but does not pull the information that is in the database for that Id (25084) in the Edit view. I'm sure this is something that I have to define in the controller.

Details view (create view directs to details view after clicking submit)
Edit view
0
Ioannis ParaskevopoulosCommented:
Could you possibly share the latest View and Controller code for the Edit?
0
Intelli-SeekerAuthor Commented:
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.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")
}

Open in new window


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

Open in new window

0
Ioannis ParaskevopoulosCommented:
In your action you create a new CustomerModel, but never populate it.

model = new CustomerModel();

Open in new window


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.

};

Open in new window


Giannis
1
Intelli-SeekerAuthor Commented:
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'.
0
Intelli-SeekerAuthor Commented:
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);
        }

Open in new window

0
Intelli-SeekerAuthor Commented:
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; }
    }
}

Open in new window

0
Ioannis ParaskevopoulosCommented:
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:

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

Open in new window


So if you do nothing for ConfidenceRating in the initialization (completely remove this row:

ConfidenceRating = customer.ConfidenceRating,

Open in new window


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

Open in new window


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
1
Intelli-SeekerAuthor Commented:
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.

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

Open in new window

0
Ioannis ParaskevopoulosCommented:
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.
0
Intelli-SeekerAuthor Commented:
Is it possible to send it directly to you rather than through Experts Exchange?
0
Ioannis ParaskevopoulosCommented:
You can find me at jyparask gmail
1
Intelli-SeekerAuthor Commented:
I sent you a link to a shared Dropbox folder.
0
Ioannis ParaskevopoulosCommented:
Will check and let you know
0
Intelli-SeekerAuthor Commented:
Any thoughts after reviewing the solution?
0
Ioannis ParaskevopoulosCommented:
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:

        [Display (Name="Prospect Status")]
        public int? status_id { get; set; }
        public IEnumerable<SelectListItem> ProspectStatus { get; set; }

Open in new window


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

Open in new window


and your view would show as:

                @Html.DropDownListFor(s => s.status_id, Model.ProspectStatus, "Please Select Prospect Status")

Open in new window


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.
1
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.