What am I doing?
I am trying using two modal in one view.
What’s the problem?
When run give this error:
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'ProgramaEstagio.Models.Person', but this ViewDataDictionary instance requires a model item of type 'ProgramaEstagio.Models.RegisterViewModel'.
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary.EnsureCompatible(object value)
Part of "PersonController.cs":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using ProgramaEstagio.Data;
using ProgramaEstagio.Models;
namespace ProgramaEstagio.Controllers
{
public class PersonController : Controller
{
private readonly ApplicationDbContext _context;
public PersonController(ApplicationDbContext context)
{
_context = context;
}
// GET: Person
public async Task<IActionResult> Index()
{
return View(await _context.Person.ToListAsync());
}
// GET: Person/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var person = await _context.Person.FindAsync(id);
if (person == null)
{
return NotFound();
}
return View(person);
}
// POST: Person/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,FullName,BirthDate,sex")] Person person)
{
if (id != person.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(person);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(person.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(person);
}
RegisterViewModel.cs:
namespace ProgramaEstagio.Models
{
public class RegisterViewModel
{
public Person Person { get; set; }
public Address Address { get; set; }
}
}
Edit.cshtml:
@model ProgramaEstagio.Models.RegisterViewModel
@{
ViewData["Title"] = "Edit";
}
<h1>Edit</h1>
<h4>Person</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Person.ID" />
<div class="form-group">
<label asp-for="Person.FullName" class="control-label"></label>
<input asp-for="Person.FullName" class="form-control" />
<span asp-validation-for="Person.FullName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Person.BirthDate" class="control-label"></label>
<input asp-for="Person.BirthDate" class="form-control" />
<span asp-validation-for="Person.BirthDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Person.sex" class="control-label"></label>
<input asp-for="Person.sex" class="form-control" />
<span asp-validation-for="Person.sex" class="text-danger"></span>
</div>
<h4>Address</h4>
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Address.ID" />
<div class="form-group">
<label asp-for="Address.Country" class="control-label"></label>
<input asp-for="Address.Country" class="form-control" />
<span asp-validation-for="Address.Country" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.Complement" class="control-label"></label>
<input asp-for="Address.Complement" class="form-control" />
<span asp-validation-for="Address.Complement" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.Distric" class="control-label"></label>
<input asp-for="Address.Distric" class="form-control" />
<span asp-validation-for="Address.Distric" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.City" class="control-label"></label>
<input asp-for="Address.City" class="form-control" />
<span asp-validation-for="Address.City" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.State" class="control-label"></label>
<input asp-for="Address.State" class="form-control" />
<span asp-validation-for="Address.State" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Address.PersonID" class="control-label"></label>
<select asp-for="Address.PersonID" class="form-control" asp-items="ViewBag.PersonID"></select>
<span asp-validation-for="Address.PersonID" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
What I have to do? please help me. If need more information, ask please. And sorry for any error orthography and grammar I am studing English.
Project Link: https://github.com/vitorhugo1207/Sys-Vacina/tree/EditPagePersonAdress
Edit:
AddressController.cs:
// GET: Addresse/Edit/5
public async Task<IActionResult> Edit(int? id)
{
RegisterViewModel register = new RegisterViewModel();
if (id == null)
{
return NotFound();
}
var address = await _context.Address.FindAsync(id);
if (address == null)
{
return NotFound();
}
ViewData["PersonID"] = new SelectList(_context.Person, "ID", "FullName", address.PersonID);
register.Address = address;
return View(register);
}
// POST: Addresse/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Country,Complement,Distric,City,State,PersonID")] Address address)
{
if (id != address.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(address);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AddressExists(address.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
ViewData["PersonID"] = new SelectList(_context.Person, "ID", "FullName", address.PersonID);
return View(address);
}
2
Answers
It is happening on this line:
return View(person);
. You are sending aModel
of type Person but you need to send aModel
of RegisterViewModel. You need to send the correctModel
to yourView
:You essentially made a promise to C# that you would send a model of type
RegisterViewModel
, when you wrote this:But then you actually sent a Person instead:
It doesn’t really matter what these two things are, so long as they agree; if you upgrade/change the type in one place (like the cshtml), you have to change it everywhere else (like the controller
View(..)
calls) to ensure they remain in agreement with each other