[英]ASP.Net MVC3 missing model properties
我是MVC3的新手,正在嘗試編寫博客應用程序作為學習工具。
我已經為博客文章創建了一個數據庫對象,並使用帶有Read / Write動作的Controller和使用Entity Framework來控制實體的視圖生成了一個Controller。
我在編輯命令時遇到麻煩。 博客帖子大約有6個屬性,但我只想允許編輯修改帖子的標題和內容。 我的代碼如下:
public ActionResult Edit(int id)
{
blog_Post blog_post = db.blog_Post.Find(id);
return View(blog_post);
}
//
// POST: /Post/Edit/5
[HttpPost]
public ActionResult Edit(blog_Post blog_post)
{
if (ModelState.IsValid)
{
db.Entry(blog_post).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(blog_post);
}
@model BlogVersion1._0.blog_Post
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>blog_Post</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.PostContent)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.PostContent)
@Html.ValidationMessageFor(model => model.PostContent)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
出現的問題在公共ActionResult Edit(blog_Post blog_post)方法中。 在Edit(int id)方法中,我放置了一個斷點,可以看到blog_post已正確傳遞給視圖(包括填充的所有屬性)。
但是返回到[HttpPost]方法的blog_post缺少UserId,DateCreated等屬性。顯然,由於缺少必需的外鍵,db.SaveChanges調用上引發了異常。
如何確保所有屬性都返回到第二個編輯方法以正確進行更新?
因為執行POST時沒有從表單中發送這些元素的值。 解決此問題的一種方法是使用Hidden
變量將其保留在表單中
@using(Html.BeginForm())
{
@Html.EditorFor(model => model.Title)
@Html.HiddenFor(model => model.UserId)
<input type="submit" />
}
我認為干凈的解決方案是“不要在視圖中使用Domain模型,對View使用具有必要屬性的ViewModel。在這種情況下,顯然CreatedDate不應是View應該提供的東西。它應該是代碼將要提供的東西。填充到對象。
因此為此創建一個ViewModel
public class BlogPostViewModel
{
public int ID { set;get;}
public string Title { set;get;}
public string Description { set;get;}
}
並將其用於從View向控制器傳輸數據,反之亦然
public ActionResult Edit(int id)
{
var domainObject=repo.GetPost(id);
var viewModel=new BlogPostViewModel();
viewModel.ID=domainObject.ID;
viewModel.Title=domainObject.Title;
//map other REQUIRED properties also
return View(viewModel);
}
您的觀點將被強烈推定為
@model BlogPostViewModel
@using(Html.BeginForm())
{
@Html.EditorFor(model => model.Title)
@Html.HiddenFor(model => model.Description)
<input type="submit" />
}
在POST操作中,將其映射回域對象並保存
[HttpPost]
public ActionResult Edit(BlogPostViewModel model)
{
if(ModelState.IsValid)
{
var domainObject=new blog_Post();
domainObject.Title=model.Title;
domainObject.ModifiedDate=DateTime.Now;
//set other properties also
repo.Update(domainObject);
return RedirecToAction("Success");
}
return View(model);
}
可以考慮使用AutoMapper庫,而不用一一對應地手動映射屬性,該庫只需一行代碼即可為您完成!
只需為所有其他不可編輯的屬性添加隱藏字段。
@Html.HiddenFor(model => model.Id)
這些字段將包含在POST中,因此,模型綁定程序會將它們正確地放入您的blog_post實例中。
另一方面,您實際上應該使用視圖模型-簡單的POCO類將成為您的視圖模型。 不建議直接使用實體模型。
這是一些信息:
ASP.NET MVC ViewModel模式
http://stephenwalther.com/archive/2009/04/13/asp-net-mvc-tip-50-ndash-create-view-models.aspx
模型綁定程序將僅填充HTTP請求中發布的屬性。 您的視圖僅包含標題和帖子內容。
您要么需要為每個缺少的屬性都包括隱藏字段。 或者只是ID屬性,然后其余部分進行數據庫查找。
對於您的情況,我認為您應該使用HtmlHelper擴展方法“ EditorForModel”,而不是為每個屬性調用“ EditorFor”。 您在每個屬性上使用EditorFor使您的生活變得復雜(正如gred84所說,它不會在您的上下文中的HTTP請求中發布未顯示的屬性)。
在blog_Post模型類中,應該使用屬性[HiddenInput(DisplayValue = false)]標記每個您不想編輯的屬性。
然后,您可以簡單地擁有(簡化的-沒有驗證摘要)視圖中的所有代碼,而不是視圖中的所有代碼。
@using (Html.BeginForm())
{
@Html.EditorForModel()
<input type="submit" value="Save" />
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.