I using MVC 5.1 and EF 6.1 database first model. I don't like the view that was created by the scaffolding as it uses all the database columns. On the create view I just want the user to input the required fields all other data can be added through editing the details view. I have created the a view model to use other than the .edmx generated one. The view works as expected but when the create action button is click the post operation dies with a "[NullReferenceException: Object reference not set to an instance of an object.]
Here is my view model
public class DesktopCreateViewModel
{
[Required]
[Display(Name = "Serial Number")]
[StringLength(30)]
public string SERIAL_NUMBER { get; set; }
public int Model_DesktopId { get; set; }
public int DeviceType_DesktopId { get; set; }
[Required]
[StringLength(50)]
public string MAC1 { get; set; }
[Display(Name = "Arrival Date")]
public DateTime ARRIVAL_DATE { get; set; }
[Timestamp]
[Display(Name = "Record Updated")]
public DateTime RECORD_UPDATED { get; set; }
public int LocationId { get; set; }
public int Location_CodeId { get; set; }
public int MemoryId { get; set; }
public int MonitorId { get; set; }
public int PlantId { get; set; }
public int DepartmentId { get; set; }
public int Operating_SystemId { get; set; }
[ForeignKey("DeparmentId")]
public virtual Department Department { get; set; }
[ForeignKey("DeviceType_DesktopId")]
public virtual DeviceType_Desktop DeviceType_Desktop { get; set; }
[ForeignKey("Location_CodeId")]
public virtual Location_Code Location_Code { get; set; }
[ForeignKey("LocationId")]
public virtual Location Location { get; set; }
[ForeignKey("MemoryId")]
public virtual Memory Memory { get; set; }
[ForeignKey("Model_DesktopId")]
public virtual Model_Desktop Model_Desktop { get; set; }
[ForeignKey("MonitorId")]
public virtual Monitor Monitor { get; set; }
[ForeignKey("Operating_SystemId")]
public virtual Operating_System Operating_System { get; set; }
[ForeignKey("PlantId")]
public virtual Plant Plant { get; set; }
public IEnumerable<DesktopCreateViewModel> Create_Desktop { get; set; }
public virtual ICollection<DesktopCreateViewModel> Desktops { get; set; }
Here is the portion of the controller that fails
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ICollection<DesktopCreateViewModel> desktop)
{
if (ModelState.IsValid)
{
foreach (var item in desktop)
{
db.Entry(desktop).State = EntityState.Added;
}
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.DepartmentId = new SelectList(db.Departments, "Id", "DEPARTMENT1", desktop.DepartmentId);
ViewBag.DeviceType_DesktopId = new SelectList(db.DeviceType_Desktop, "Id", "DEVICE_TYPE", desktop.DeviceType_DesktopId);
ViewBag.Location_CodeId = new SelectList(db.Location_Code, "Id", "LOCATION_CODE1", desktop.Location_CodeId);
ViewBag.LocationId = new SelectList(db.Locations, "Id", "LOCATION1", desktop.LocationId);
ViewBag.MemoryId = new SelectList(db.Memories, "Id", "MEMORY1", desktop.MemoryId);
ViewBag.Model_DesktopId = new SelectList(db.Model_Desktop, "Id", "MODEL", desktop.Model_DesktopId);
ViewBag.MonitorId = new SelectList(db.Monitors, "Id", "MONITOR1", desktop.MonitorId);
ViewBag.Operating_SystemId = new SelectList(db.Operating_System, "Id", "OS", desktop.Operating_SystemId);
ViewBag.PlantId = new SelectList(db.Plants, "Id", "PLANT1", desktop.PlantId);
return View(desktop);
}
This is the View
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Desktop</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.SERIAL_NUMBER, new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.SERIAL_NUMBER)
#Html.ValidationMessageFor(model => model.SERIAL_NUMBER)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Model_DesktopId, "Model", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("Model_DesktopId", String.Empty)
#Html.ValidationMessageFor(model => model.Model_DesktopId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DeviceType_DesktopId, "Device Type", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("DeviceType_DesktopId", String.Empty)
#Html.ValidationMessageFor(model => model.DeviceType_DesktopId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MAC1, new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.MAC1)
#Html.ValidationMessageFor(model => model.MAC1)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ARRIVAL_DATE, new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.ARRIVAL_DATE)
#Html.ValidationMessageFor(model => model.ARRIVAL_DATE)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.RECORD_UPDATED, new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.EditorFor(model => model.RECORD_UPDATED)
#Html.ValidationMessageFor(model => model.RECORD_UPDATED)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LocationId, "Location", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("LocationId", String.Empty)
#Html.ValidationMessageFor(model => model.LocationId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Location_CodeId, "Location Code", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("Location_CodeId", String.Empty)
#Html.ValidationMessageFor(model => model.Location_CodeId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MemoryId, "Memory", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("MemoryId", String.Empty)
#Html.ValidationMessageFor(model => model.MemoryId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MonitorId, "Monitor", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("MonitorId", String.Empty)
#Html.ValidationMessageFor(model => model.MonitorId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PlantId, "Plant", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("PlantId", String.Empty)
#Html.ValidationMessageFor(model => model.PlantId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DepartmentId, "Department", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("DepartmentId", String.Empty)
#Html.ValidationMessageFor(model => model.DepartmentId)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Operating_SystemId, "Operating System", new { #class = "control-label col-md-4" })
<div class="col-md-8">
#Html.DropDownList("Operating_SystemId", String.Empty)
#Html.ValidationMessageFor(model => model.Operating_SystemId)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-8 col-md-4">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The action is expecting a collection of viewmodels (ICollection<DesktopCreateViewModel>), but the view only contains one. Try changing to:
public ActionResult Create(DesktopCreateViewModel desktop)
Related
In a MODEL, I have two class - ContentDetails and CompetencyDetails which contains its properties
namespace CompetencyAssessmentServices.ServiceModel
{
public class ContentDetails
{
public int CaseStudyId { get; set; }
public string CaseStudy { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public bool IsActive { get; set; }
public bool ReviewStatus { get; set; }
public string SolutionDescription { get; set; }
public int CompetencyID { get; set; }
public string CompetencyName { get; set; }
public List<string> SolutionId { get; set; }
}
public class CompetencyDetails
{
public int CompID { get; set; }
public string CompName { get; set; }
}
}
Controller :
Action CaseStudy is retrieving the list of CompetencyDetails from database which is working fine.
namespace CompetencyAssessment.Controllers
{
public class ContentManagementController : Controller
{
// GET: ContentManagement
IContentManagementRepository repo = new ContentManagementRepository();
[HttpGet]
public ActionResult CaseStudy()
{
List<CompetencyDetails> complst = repo.GetCompetencyDetails();
ViewBag.list = complst;
return View(ViewBag.list);
}
[HttpPost]
public ActionResult CaseStudy(ContentDetails cd)
{
ContentDetails ctd = repo.CaseStudyCreationDetails(cd);
return View();
}
}
}
While loading the View, I am getting below error
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[CompetencyAssessmentServices.ServiceModel.CompetencyDetails]', but this dictionary requires a model item of type 'CompetencyAssessmentServices.ServiceModel.ContentDetails'.
View is
#model CompetencyAssessmentServices.ServiceModel.ContentDetails
#{
ViewBag.Title = "CASE-STUDY Contenet Creation (By SME)";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>CASE-STUDY Contenet Creation (By SME)</title>
</head>
<body>
#using (Html.BeginForm())
{
<h4>ContentDetails</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.CaseStudy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(model => model.CaseStudy, new { htmlAttributes = new { #class = "form-control", style = "rows=20,columns=400" } })
#Html.ValidationMessageFor(model => model.CaseStudy, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.IsActive, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.IsActive)
#Html.ValidationMessageFor(model => model.IsActive, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
Solution 1: #Html.TextBox("Sol1") #Html.DropDownList("CompetencyDetails", new SelectList(ViewBag.list, "CompID", "CompName"), "Select Competency")
Solution 2: #Html.TextBox("Sol2") #Html.DropDownList("CompetencyDetails", new SelectList(ViewBag.list, "CompID", "CompName"), "Select Competency")
Solution 3: #Html.TextBox("Sol3") #Html.DropDownList("CompetencyDetails", new SelectList(ViewBag.list, "CompID", "CompName"), "Select Competency")
Solution 4: #Html.TextBox("Sol4") #Html.DropDownList("CompetencyDetails", new SelectList(ViewBag.list, "CompID", "CompName"), "Select Competency")
<div class="form-group">
#Html.LabelFor(model => model.SolutionId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SolutionId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SolutionId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.SolutionDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.SolutionDescription, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.SolutionDescription, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
</body>
</html>
The reason, I am getting this error because my view contains the reference from both class CompetencyDetails and ContentDetails
Can someone please help on how can I pass the context from both the class in the MODEL without this error ?
PS: This is my first MVC project so would appreciate any various approaches to achieve this
you can create new class having both the model class like example given below
public class Combine
{
public List<ContentDetails> ContentDetailsList { get; set; }
public ContentDetails ContentDetailsData { get; set; }
public List<CompetencyDetails> CompetencyDetailsInfoList { get; set; }
public CompetencyDetails CompetencyDetailsData { get; set; }
}
then in MVC controller
[HttpGet]
public ActionResult CaseStudy()
{
var caseStudy = new SupplierDTO()
{
ContentDetailsList = db.ContentDetails.ToList(),
CompetencyDetailsInfoList = db.CompetencyDetails.ToList(),
};
return View(caseStudy);
}
then MVC View
#model CompetencyAssessmentServices.Models.Combine
<div class="form-group">
#Html.LabelFor(model => model.ContentDetailsData.CaseStudy, htmlAttributes: new { #class = "control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(model => model.ContentDetailsData.CaseStudy, new { htmlAttributes = new { #class = "form-control"} })
#Html.ValidationMessageFor(model => model.ContentDetailsData .CaseStudy, "", new { #class = "text-danger"})
</div>
</div>
I must not be searching with the correct phrases. This is a simple concept and I’ve done it in other languages and frameworks with ease.
I’m saving the UserID for the person who created the record and the UserID who last updated the record. Instead of displaying the UserID, I want to display the User.FirstName + ‘ ‘ + User.LastName.
The way I have it currently the LastEditBy and CreateBy is displayed on the page as blank.
Controller: I get the customer model and manually map the model to the customerViewModel then pass it to my partial view.
public ActionResult Edit(int customerId)
{
Customer customer = DbContext.Customers.FirstOrDefault(x => x.CustomerId == customerId);
CustomerViewModel customerViewModel = MapToViewModel(customer);
customerViewModel.UserSelectList = GetUserGroupList();
UserManager<ApplicationUser> _userManager = HttpContext.GetOwinContext().Get<ApplicationUserManager>();
var CreateByUser = _userManager.FindById(customerViewModel.CreateById);
var EditByUser = _userManager.FindById(customerViewModel.LastEditById);
customerViewModel.CreateBy = CreateByUser.FirstName + " " + CreateByUser.LastName;
customerViewModel.LastEditBy = EditByUser.FirstName + " " + EditByUser.LastName;
if (Request.IsAjaxRequest()) {
return PartialView("_CustomerEditPartial", customerViewModel);
}
return View("_CustomerEditPartial", customerViewModel);
}
The CustomerViewModel:
public class CustomerViewModel : DbContext{
public CustomerViewModel(): base("name=CustomerViewModel")
{
}
[Key]
public int CustomerId { get; set; }
[MaxLength(128), ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public SelectList UserSelectList { get; set; }
#region additional Fields
// This overrides default conventions or data annotations
[Required(ErrorMessage = "Please enter your first name.")]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter your last name.")]
[StringLength(100)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime CreateDate { get; set; } = DateTime.Now;
public string CreateById { get; set; }
[NotMapped]
public string CreateBy { get; set; }
public string LastEditById { get; set; }
[NotMapped]
public string LastEditBy { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime LastEditDate { get; set; } = DateTime.Now;
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class UserGroupList
{
public string Value { get; set; }
public string Text { get; set; }
}
My partial view page: _CustomerEditPartial.cshtml
#model WOA.ViewModels.CustomerViewModel
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" daa-dismiss="modal" aria-hidden="True">x</button>
<h4 class="modal-title">Edit Customer</h4>
</div>
#using (Ajax.BeginForm("Edit", "Customers", null, new AjaxOptions { HttpMethod = "Post", OnFailure = "OnFail" }, new { #class = "form-horizontal", role = "form" })) {
<div class="modal-body">
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.CustomerId)
<div class="form-group">
#Html.LabelFor(model => model.UserId, "UserId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.UserId, ViewData.Model.UserSelectList, "Select One", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.UserId, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LastName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateDate, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.CreateBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.CreateBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditBy, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditBy, new { #readonly = "readonly" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LastEditDate, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.LastEditDate, new { #readonly = "readonly" })
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary" value="Save changes" />
</div>
</div>
</div>
<script type="text/javascript">
function OnSuccess() {
alert("success");
}
function OnFail() {
alert("fail");
}
function OnComplete() {
alert("Complete");
}
</script>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I have updated my code, it is working now, however I do not believe it is the proper way to do this.
I believe I should be able to return the additional values I need via Linq on the initial call and not make two more trips to the database for the additional values.
I have not been able to figure out a way to make this work with Linq.
Thank you in advance for your time and effort.
I'm doing an mvc Theater project with entity framework code first.
I created a page to add a movie to my database.
the Movie class has a Genre property,the Genre class has an Id and a Name property.
What I'm trying to do is query all rows of the Genres table from database with Linq (if other method is better do tell) and choose one Genre to connect to a row of the movie I'm creating.
thanks,any help is appreciated.
this is my Genre class
public class Genre
{
[Key]
public int Id { get; set; }
[Display(Name="Ganre")]
public string GenreName { get; set; }
public virtual ICollection<Movie> MoviesByGenre { get; set; }
}
this is my Movie class
public class Movie
{
[Key]
public string Id { get; set; }
[Required(ErrorMessage = "Movie name is required")]
[Display(Name="Movie name")]
public string MovieName { get; set; }
[Required(ErrorMessage = "Movie length is required")]
[Display(Name="Length(minutes)")]
public int LengthInMinutes { get; set; }
[Required(ErrorMessage="Genre of the movie is required")]
[Display(Name="Genre")]
public virtual Genre MovieGenre { get; set; }
public string Description { get; set; }
[Required(ErrorMessage = "Year of release is required")]
public int Year { get; set; }
[Required(ErrorMessage="Who is the director?")]
public virtual MovieDirector Director { get; set; }
public virtual MoviePoster Poster { get; set; }
//How many users bought a ticket
public virtual ICollection<ApplicationUser> UsersWhoBoughtTicket { get; set; }
}
this is the Add Movie page
<div class="form-horizontal">
<h4>Movie</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.MovieName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MovieName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.MovieName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LengthInMinutes, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LengthInMinutes, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LengthInMinutes, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Year, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Year, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Year, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.MovieGenre.GenreName, htmlAttributes: new { #class = "btn control-label col-md-2" })
<div class="col-md-10">
#Html.ValidationMessageFor(model => model.MovieGenre.GenreName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Director, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Director, new { htmlAttributes = new { #class = "form-control dropdown" } })
#Html.ValidationMessageFor(model => model.Director, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Poster, new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input name="Image" type="file" />
#Html.ValidationMessageFor(model => model.Poster)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
I hope your entities are like this:
public class Genre
{
public int Id{ get; set; }
public string Name{ get; set; }
public ICollection<Movie> Movies{ get; set; }
}
public class Movie
{
public int Id{ get; set; }
public string Name{ get; set; }
public int GenreId {get; set; }
public Genre Genre{ get; set; }
}
Now your query would be like this:
_context.Include(x=>x.Movies).Genres; //it will return all genres with movies
_context.Movies.where(x=>x.GenreId == genreId); // it will return movies based on a genre id
I am having following ViewModel, and corresponding two models.
I am displaying data from this ViewModel on a view, but when I post data to update, following error occurs
The model item passed into the dictionary is of type 'WebMSM.Models.ComplainDetailsVm', but this dictionary requires a model item of type 'WebMSM.Models.REPAIRING'.
public partial class ComplainDetailsVm
{
public virtual REPAIRING REPAIRINGs { get; set; }
public virtual COMPLAIN COMPLAINs { get; set; }
}
REPAIRING.cs
public partial class REPAIRING
{
[Key]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
[DisplayName("IN TIME")]
public Nullable<System.DateTime> IN_TIMESTAMP { get; set; }
[DisplayName("CREATE TIME")]
public Nullable<System.DateTime> CREATE_TIMESTAMP { get; set; }
[DisplayName("LAST EDIT TIME")]
public Nullable<System.DateTime> LAST_EDIT_TIMESTAMP { get; set; }
}
COMPLAIN.cs
public partial class COMPLAIN
{
[Key]
[DisplayName("JOBSHEET NO")]
public int JOBSHEET_NO { get; set; }
[Required]
[DisplayName("COMPANY NAME")]
public string COMPANY_NAME { get; set; }
[Required]
[DisplayName("MODEL NAME")]
public string MODEL_NAME { get; set; }
}
CONTROLLER ACTION
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id,ComplainDetailsVm model)
{
if (ModelState.IsValid)
{
var r = model.REPAIRINGs;
var c = model.COMPLAINs;
db.Entry(r).State = EntityState.Modified;
db.SaveChanges();
}
return View(model);
}
UPDATE
VIEW
#model WebMSM.Models.ComplainDetailsVm
#{
ViewBag.Title = "EditRepairingComplain";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.REPAIRINGs.JOBSHEET_NO)
#Html.HiddenFor(model => model.COMPLAINs.JOBSHEET_NO)
<div class="form-group">
#Html.LabelFor(model => model.COMPLAINs.COMPANY_NAME,
htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.TextBoxFor(model => model.COMPLAINs.COMPANY_NAME, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.COMPLAINs.COMPANY_NAME, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.COMPLAINs.MODEL_NAME, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.TextBoxFor(model => model.COMPLAINs.MODEL_NAME, new { #class = "form-control", #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.COMPLAINs.MODEL_NAME, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.IN_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.IN_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.IN_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.CREATE_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, htmlAttributes: new { #class = "control-label col-md-4" })
<div class="col-md-6">
#Html.EditorFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.REPAIRINGs.LAST_EDIT_TIMESTAMP, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-5 col-md-6">
<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")
}
UPDATE ADDED GET METHOD
// GET: Repairing/Edit/5
public ActionResult Edit(int? id)
{
var vm = new ComplainDetailsVm();
var r = db.REPAIRINGs.Find(id);
var c = db.COMPLAINs.Find(id);
if (r != null)
{
vm.REPAIRINGs = r;
vm.COMPLAINs = c;
}
//ViewData["LIST_ESTIMATE_AMOUNT_OK_FROM_CUSTOMER"] = lstOKNOTOK;
return View("EditRepairingComplain",vm);
}
Thanks.
You can have your Views recognize your ViewModel in two ways: you can have the MVC framework figure that out for you, or you can use strongly typed views
In your case, your view is strongly typed but refers to the wrong object class. This can happen if you copied your view from some other file. You should see the following line on your cshtml file:
#model WebMSM.Models.REPAIRING
replace this with:
#model WebMSM.Models.ComplainDetailsVm
and you should no longer get the error.
Edit:
worth to mention that these lines should be on top of the cshtml file returned by the action methods.
I'm learning about using ViewModels to pass information from the view to the controller and vice versa. I have my create action, view, and viewmodel working perfectly but I'm having trouble with the edit one. I get the error:
The model item passed into the dictionary is of type 'CatVM.Models.Cat', but this dictionary requires a model item of type 'CatVM.Models.EditCatViewModel'.
Here is my code:
Controller Method
// GET: /Cats/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Cat cat = unitOfWork.CatRepository.GetByID(id);
if (cat == null)
{
return HttpNotFound();
}
return View(cat);
}
View
#model CatVM.Models.EditCatViewModel
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Cat</h4>
<hr />
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.ID)
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Color, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Color)
#Html.ValidationMessageFor(model => model.Color)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FurLength, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FurLength)
#Html.ValidationMessageFor(model => model.FurLength)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Size, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Size)
#Html.ValidationMessageFor(model => model.Size)
</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")
}
EditCatViewModel
public class EditCatViewModel
{
public int ID { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
[Required]
[StringLength(50)]
public string Color { get; set; }
[Required]
[StringLength(50)]
[Display(Name = "Fur Type")]
public string FurLength { get; set; }
[StringLength(50)]
public string Size { get; set; }
}
}
That's because the item you receive from CatRepository.GetByID(id); is of type Cat, not EditCatViewModel.
You can bypass this by constructing a new viewmodel from this object:
Cat cat = unitOfWork.CatRepository.GetByID(id);
var viewModel = new EditCatViewModel {
Name = cat.Name,
Color = cat.Color,
FurLength = cat.FurLength,
Size = cat.Size
};
return View(viewModel);
Alternatively you could construct implicit or explicit casting methods or use a mapping tool like AutoMapper.
Your return view should be of type CatVM.Models.EditCatViewModel now your returning a Cat
return View(cat);
transform your model in a view model and pass this object back to the view