如何修复局部视图的视图模型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何修复局部视图的视图模型相关的知识,希望对你有一定的参考价值。
我在SQLServer上为空表创建新记录时遇到问题当尝试传递新记录时,我得到“对象引用未设置为对象的实例”。错误当我尝试编辑现有记录时,表格正确显示内容,但保存更改将不起作用。使用Guests表,它只会重新加载旧条目而不进行更改,而对于Contacts,它会返回与创建新记录时相同的错误。应该通过显示每个表的部分视图编辑器表单来创建和编辑记录。
我是MVC的初学者。
以下是我的代码。
表模型:
[Table("GuestsTest")]
public class Guest
{
[Key]
[HiddenInput(DisplayValue = false)]
public int GuestID { get; set; }
public string GuestLastName { get; set; }
public string GuestFirstName { get; set; }
public string GuestMiddleName { get; set; }
public string GuestEmail { get; set; }
public string GuestSex { get; set; }
}
[Table("ContactsTest")]
public class Contact
{
[Key]
[HiddenInput(DisplayValue = false)]
public int ContactID { get; set; }
[HiddenInput(DisplayValue = false)]
public int GuestID { get; set; }
public int PostalCode { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
public string PhoneNumber { get; set; }
My view model
public class TableViewModel
{
public Guest GetGuest { get; set; }
public Contact GetContact { get; set; }
}
My controllers
public class AdminController : Controller
{
private IGuestRepository guestRepository;
private IContactRepository contactRepository;
private IQRCodeRepository qrcodeRepository;
public AdminController(IGuestRepository repoG, IContactRepository repoC, IQRCodeRepository repoQ)
{
guestRepository = repoG;
contactRepository = repoC;
qrcodeRepository = repoQ;
}
public ActionResult Index()
{
return View(guestRepository.Guests);
}
public ActionResult EditGuest(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
TableViewModel viewModel = new TableViewModel();
viewModel.GetGuest = guestRepository.Guests.FirstOrDefault(g => g.GuestID == id);
viewModel.GetContact = contactRepository.Contacts.FirstOrDefault(c => c.ContactID == id);
if (viewModel.GetGuest == null)
{
return HttpNotFound();
}
return View(viewModel);
}
public ActionResult GuestForm(int? id)
{
var viewModel = new TableViewModel();
viewModel.GetGuest = guestRepository.Guests.FirstOrDefault(g => g.GuestID == id);
return PartialView("_GuestForm", viewModel.GetGuest);
}
[HttpPost]
public ActionResult GuestForm(TableViewModel getGuest)
{
if (ModelState.IsValid)
{
guestRepository.SaveGuest(getGuest.GetGuest);
qrcodeRepository.CreateQRCode(getGuest.GetGuest);
TempData["message"] = string.Format("Zapisano {0} {1}", getGuest.GetGuest.GuestFirstName, getGuest.GetGuest.GuestLastName);
return RedirectToAction("EditGuest/" + getGuest.GetGuest.GuestID);
}
else
{
return PartialView(getGuest.GetGuest);
}
}
public ActionResult ContactForm(int? id)
{
var viewModel = new TableViewModel();
viewModel.GetContact = contactRepository.Contacts.FirstOrDefault(c => c.ContactID == id);
return PartialView("_ContactForm", viewModel.GetContact);
}
[HttpPost]
public ActionResult ContactForm(TableViewModel getGuest)
{
if (ModelState.IsValid)
{
contactRepository.SaveContact(getGuest.GetContact);
TempData["message"] = string.Format("Zapisano {0} {1}", getGuest.GetGuest.GuestFirstName, getGuest.GetGuest.GuestLastName);
return RedirectToAction("EditGuest/" + getGuest.GetGuest.GuestID);
}
else
{
return PartialView(getGuest.GetContact);
}
}
public ActionResult Create()
{
return View("EditGuest", new TableViewModel());
}
My view
@model MSConference.WebUI.Models.TableViewModel
@{
if (Model.GetGuest.GuestEmail == null)
{
ViewBag.Title = "Tworzenie nowego użytkownika";
}
else
{
ViewBag.Title = "Edycja";
}
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
@if (Model.GetGuest.GuestEmail == null)
{
<h2>Tworzenie nowego użytkownika</h2>
}
else
{
<h2>Edycja - @Model.GetGuest.GuestFirstName @Model.GetGuest.GuestLastName</h2>
}
@using (Html.BeginForm("EditGuest", "Admin"))
{
@Html.AntiForgeryToken()
<div class="container">
<ul class="nav nav-pills">
<li class="active"><a data-toggle="pill" href="#EditGuest">Edycja - Gość</a></li>
<li><a data-toggle="pill" href="#EditContact">Edycja - Kontakt</a></li>
<li><a data-toggle="pill" href="#EditBill">Edycja - Rezerwacja</a></li>
<li><a data-toggle="pill" href="#EditPlan">Edycja - Konferencja</a></li>
</ul>
<div class="tab-content">
<div id="EditGuest" class="tab-pane fade in active">@Html.Partial("_GuestForm", new MSConference.WebUI.Models.TableViewModel())</div>
<div id="EditContact" class="tab-pane fade">@Html.Partial("_ContactForm", new MSConference.WebUI.Models.TableViewModel())</div>
<div id="EditBill" class="tab-pane fade">sgdg</div>
<div id="EditPlan" class="tab-pane fade">gsdgsgsgsg</div>
</div>
</div>
}
<div>
@Html.ActionLink("Powrót do Listy", "Index", null, new { @class = "btn btn-success" })
</div>
I tried every method of passing model I could find and understand
EDIT
Here are my Repositories. Create error comes from if (contact.ContactID == 0)
public class EFGuestRepository : IGuestRepository
{
private EfDbContext context = new EfDbContext();
public IEnumerable<Guest> Guests
{
get { return context.Guests; }
}
public void SaveGuest(Guest guest)
{
if (guest.GuestID == 0)
{
context.Guests.Add(guest);
}
else
{
Guest dbEntry = context.Guests.Find(guest.GuestID);
if (dbEntry != null)
{
dbEntry.GuestLastName = guest.GuestLastName;
dbEntry.GuestFirstName = guest.GuestFirstName;
dbEntry.GuestMiddleName = guest.GuestMiddleName;
dbEntry.GuestEmail = guest.GuestEmail;
dbEntry.GuestSex = guest.GuestSex;
}
}
context.SaveChanges();
}
public Guest DeleteGuest(int guestId)
{
Guest dbEntry = context.Guests.Find(guestId);
if (dbEntry != null)
{
context.Guests.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}
}
public class EFContactRepository : IContactRepository
{
private EfDbContext context = new EfDbContext();
public IEnumerable<Contact> Contacts
{
get { return context.Contacts; }
}
public void SaveContact(Contact contact)
{
if (contact.ContactID == 0)
{
contact.GuestID = contact.ContactID;
context.Contacts.Add(contact);
}
else
{
Contact dbEntry = context.Contacts.Find(contact.ContactID);
if (dbEntry != null)
{
contact.GuestID = contact.ContactID;
dbEntry.PostalCode = contact.PostalCode;
dbEntry.City = contact.City;
dbEntry.Street = contact.Street;
dbEntry.HouseNumber = contact.HouseNumber;
dbEntry.PhoneNumber = contact.PhoneNumber;
}
}
context.SaveChanges();
}
public Contact DeleteContact(int guestId)
{
Contact dbEntry = context.Contacts.Find(guestId);
if (dbEntry != null)
{
context.Contacts.Remove(dbEntry);
context.SaveChanges();
}
return dbEntry;
}
public interface IGuestRepository
{
IEnumerable<Guest> Guests { get; }
void SaveGuest(Guest guest);
Guest DeleteGuest(int guestId);
}
public interface IContactRepository
{
IEnumerable<Contact> Contacts { get; }
void SaveContact(Contact guest);
Contact DeleteContact(int guestId);
}
I've built whole project working with Adam Freeman pro asp.net mvc 5 book (SportsStore project).
将实体传递给视图不是一个好习惯,并且根据您从视图返回时对它们执行的操作,这可能会使您面临数据篡改。您的“TableViewModel”应该只包含来自guest虚拟机和联系人的展平字段,或者GuestViewModel和ContactViewModel,仅显示您需要显示/编辑的密钥和详细信息。实体被设计为与DbContext相关联。在视图模型中引用它们是孤立它们。当您将它们传递回控制器时,它们将成为仅从视图中的JSON数据反序列化的POCO实例。它们没有更改跟踪等,您可能期望在从DbContext新加载时使用实体。您可以将它们附加到DbContext,但是您必须手动将实体State设置为“Modified”,否则上下文不知道实体已被更改。
您现在面临的问题可能在于您的SaveGuest方法正在执行的操作。
数据的典型MVC生命周期大致如下:
视图:
- 从上下文加载实体
- 填充视图模型
- 传递给视图。
更新:
- 针对当前会话验证视图模型
- 基于键从上下文加载实体
- 检查视图模型是否过时(最后的模态日期/时间戳/行版本匹配)
- 仅验证和复制可从视图模型更新为实体的详细信息
- 保存更改。
如果您没有看到更改,则可能是您将实体附加到新上下文而不将实体State设置为“已修改”。请注意,建议不要这样做,因为您无条件地信任来自客户端的数据。例如,您可能只想看到用户修改了您为其创建控件的数据,但是通过附加实体,您可以打开门,以便截取或使用实体上的任何/所有数据回放POST调用。改变。您无论如何都需要加载现有实体,以验证不应更改任何不应更改的内容。另一种可能性是你可能在没有意识到的情况下重新加载实体,在调用SaveChanges之前没有从视图模型的实体复制值,或者将实体添加到上下文中,认为它会更新现有行,但是它正在保存一个全新的行新的PK。
我通过替换解决了我的问题
@Html.Partial("PartialView", Model)
使用@ {Html.RenderPartial(“PartialView”,Model);}
我也重建了我的模型
现在我的实体模型看起来像这样:
[Table("GuestsTest")]
public class Guest
{
[Key]
public int GuestID { get; set; }
public string GuestLastName { get; set; }
public string GuestFirstName { get; set; }
public string GuestMiddleName { get; set; }
public string GuestEmail { get; set; }
public string GuestSex { get; set; }
[Required]
public virtual Contact Address { get; set; }
}
[Table("ContactsTest")]
public class Contact
{
public int ContactID { get; set; }
[Key, ForeignKey("Guest")]
public int GuestID { get; set; }
public int PostalCode { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
public string PhoneNumber { get; set; }
public virtual Guest Guest { get; set; }
}
我的视图模型得到了完全重建:
public class TableViewModel
{
public GuestViewModel GetGuest { get; set; }
public ContactViewModel GetContact { get; set; }
}
public class GuestViewModel
{
[Key]
[HiddenInput(DisplayValue = false)]
public int? GuestID { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Proszę podać nazwisko.")]
[Display(Name = "Nazwisko")]
public string GuestLastName { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Proszę podać imię.")]
[Display(Name = "Imię")]
public string GuestFirstName { get; set; }
[MaxLength(50)]
[Display(Name = "Drugie imię")]
public string GuestMiddleName { get; set; }
[MaxLength(50)]
[Required(ErrorMessage = "Proszę podać adres email.")]
[RegularExpression(".+\@.+\..+", ErrorMessage = "Proszę podać prawidłowy adres e-mail.")]
[Display(Name = "Email")]
public string GuestEmail { get; set; }
[MaxLength(1)]
[Required(ErrorMessage = "Proszę podać płeć.")]
public string GuestSex { get; set; }
}
public class ContactViewModel
{
[HiddenInput(DisplayValue = false)]
public int ContactID { get; set; }
[Key, ForeignKey("Guest")]
[HiddenInput(DisplayValue = false)]
public int GuestID { get; set; }
[Required(ErrorMessage = "Proszę podać kod pocztowy.")]
[Display(Name = "Kod pocztowy")]
public int PostalCode { get; set; }
[Required(ErrorMessage = "Proszę podać Miejscowość.")]
[Display(Name = "Miejscowość")]
public string City { get; set; }
[Required(ErrorMessage = "Proszę podać ulicę.")]
[Display(Name = "Ulica")]
public string Street { get; set; }
[Required(ErrorMessage = "Proszę podać numer domu/mieszkania.")]
[Display(Name = "Numer domu/mieszkania")]
public string HouseNumber { get; set; }
[Required(ErrorMessage = "Proszę podać numer telefonu.")]
[Display(Name = "Numer telefonu")]
public string PhoneNumber { get; set; }
}
最后,我重载了我的保存功能以使用新模型
以上是关于如何修复局部视图的视图模型的主要内容,如果未能解决你的问题,请参考以下文章