簡體   English   中英

ASP.Net MVC3缺少模型屬性

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM