2011-03-17 50 views
8

我有一個實體,稱爲Domain.Models.BlogPost其中包含以下屬性:ASP.NET MVC 3模型綁定和表單域

  • 帖子ID
  • 標題
  • 作者
  • PostedDate
  • 身體

我也有一個實體叫Domain.Models.PostComment其中包含以下屬性:

  • CommentID
  • 帖子ID
  • 作者
  • 電子郵件
  • 網站
  • 身體

BlogPost包含許多PostComments。一對多的關係。

現在我有這樣的(從博客帖子的代碼通過HTML註釋分隔的評論形式)一個觀點:

@model Domain.Models.BlogPost 
@using Domain.Models; 
@{ 
    ViewBag.Title = "Post"; 
} 
<div class="postTitle">@Model.Title</div> 
<div class="subInfo"> 
    Posted by @Model.Author on @Model.PostedDate.ToString("D") 
</div> 
<div class="postBody"> 
    @Html.Markdown(Model.Body) 
</div> 
<br /> 
@Model.PostComments.Count Comment(s). 
<div class="comments"> 
@foreach (PostComment postComment in Model.PostComments) 
{ 
    Html.RenderPartial("PostComment", postComment); 
} 
</div> 

<!-- BELOW IS THE ADD COMMENT FORM --> 

<div id="addComment"> 
@using (Html.BeginForm("AddComment", "Blog")) 
{ 
    <text> 
    @Html.Hidden("PostID", Model.PostID)<br /> 
    Name: @Html.TextBox("Author")<br /> 
    Email: @Html.TextBox("Email")<br /> 
    Website: @Html.TextBox("Website")<br /> 
    Body: @Html.TextArea("Body")<br /> 
    <input type="submit" value = "Add Comment" /> 
    </text> 
} 
</div> 
@Html.ActionLink("Add Comment", "AddComment") 

的問題是,由於評論表單使用@Html.TextBox("Author")@Html.TextBox("Body"),它們填充了數據從該模型還包含屬性AuthorBody。有關如何解決此問題的任何建議,以便這些字段在頁面加載時不會獲得值?

我還試圖建立一個BlogPostViewModel和設置,作爲視圖模型和分配BlogPost財產與我的實際模型:

public class BlogPostViewModel 
{ 
    public BlogPost BlogPost { get; set; } 
    public PostComment NewComment { get; set; } 
} 

然後我做了@Html.TextBoxFor(x => x.NewComment.Author)但當形式張貼到這個操作方法:

public ActionResult AddComment(PostComment postComment) 
{ 
    // ... 
} 

postComment沒有綁定到表單值:/

+3

這是默認模型活頁夾的醜陋事實。我已經打了幾次。我的最佳解決方案是添加[綁定(排除=「作者,身體」)]的行動,然後手動修復snafu。我很樂意聽到更好的方法。 – 2011-03-17 16:21:10

+0

我很樂意聽到更好的方法。 – Chev 2011-03-17 16:24:08

+0

查看您的更新,嘗試基於NewComment前綴進行綁定。即在參數PostComment之前放置[Bind(Prefix =「NewComment」))postComment – 2011-03-17 16:39:10

回答

6

您可以將AddComment部分中的字段重命名爲不與模型中指定的屬性相沖突的部分,也可以使用不同的重載Html.TextBoxThis overload of TextBox takes a value

值(類型:System.Object)
文本輸入元素的值。如果此值爲null,則元素的值將從ViewDataDictionary對象中檢索。如果不存在值,則從ModelStateDictionary對象中檢索該值。


更新:既然你加入「NewComment」作爲屬性並解決財產命名衝突這樣一來,所有你需要做的綁定PostComment而不是POST全視圖模型的動作,是指示模型聯編程序將使用前綴。這是使用BindAttribute完成的。

public ActionResult AddComment([Bind(Prefix = "NewComment")] PostComment postComment) 
+0

嗯,好吧,這是兩個人告訴我重寫'string.Empty'的值,所以我想這就是我要做的。我只是認爲將會有更好的方式來構建模型/視圖,以便這些碰撞甚至不會發生。 – Chev 2011-03-17 16:23:43

+0

你可以用不同的方式構造它來避免碰撞。 @Jakub Konecki走上正軌。將名爲「NewComment」的PostComment屬性添加到BlogPost模型類中。然後你的視圖代碼看起來像@ Html.TextBoxFor(x => x.NewComment.Body); – 2011-03-17 16:26:44

+0

正確的除了然後我不得不接受視圖模型作爲'AddComment'操作方法中的一個參數,而不是接受一個簡單的'PostComment'對象。正如問題中提到的,我曾經嘗試過這一點。 – Chev 2011-03-17 16:30:56

0

TextBox沒有超載需要一個值?您可以通過string.Empty ...

+0

是的,但這似乎是駭人聽聞。感覺應該有更好的方法。 – Chev 2011-03-17 16:21:20

+0

但我相信他希望用戶輸入的值。在POST發生後,用戶的值被默認模型聯編程序破壞。 – 2011-03-17 16:21:54

+0

我認爲這是一個正確的方法 - 你想渲染一個空的表單。你可以綁定到PostComment的空實例.... – 2011-03-17 16:22:29

1

使用ASP NET MVC模板,以便完全控制填充內容和類型安全。

所以你要創建一個.ascx模板,它需要強類型Comment。在你的模型中,你留下一個空的。

+0

這不意味着'AddComment'操作方法將不得不接受'BlogPostViewModel'作爲參數,而不僅僅是'PostComment'?這似乎是奇怪的回發一個視圖模型對象與除了我之後的所有空屬性。也許我錯了,那完全正常。 – Chev 2011-03-17 16:26:05

+0

不可以。您可以通過'Model.EditorFor(m => m.Comment)' – Aliostad 2011-03-17 16:29:09

+0

在視圖yes中,但action方法需要接受視圖模型對象,而不是PostComment對象。我現在正在測試它來驗證。 – Chev 2011-03-17 16:34:09