【问题标题】:ASP.NET MVC 3 Model-binding and form fieldsASP.NET MVC 3 模型绑定和表单字段
【发布时间】:2011-03-17 16:16:37
【问题描述】:

我有一个名为 Domain.Models.BlogPost 的实体,它包含以下属性:

  • 邮政编号
  • 标题
  • 作者
  • 发布日期
  • 身体

我还有一个名为 Domain.Models.PostComment 的实体,它包含以下属性:

  • 评论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 =&gt; x.NewComment.Author) 但是当表单发布到这个操作方法时:

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

postComment 没有绑定到表单值:/

【问题讨论】:

  • 这是默认模型绑定器的一个丑陋事实。我已经打过几次了。我最好的解决方案是将 [Bind(Exclude="Author, Body")] 添加到操作中,然后手动修复问题。我很想听听更好的方法。
  • 我也很想听听更好的方法。
  • 看到你的更新,尝试基于 NewComment 前缀绑定。即把 [Bind(Prefix = "NewComment")] 放在参数 PostComment postComment 之前
  • 我会试试这个,让你知道它是怎么回事。
  • 属性“绑定”在此声明类型上无效。它仅对“类,参数”声明有效。 public ActionResult AddComment(PostComment postComment)

标签: c# asp.net-mvc asp.net-mvc-3 razor model-binding


【解决方案1】:

您可以将 AddComment 部分中的字段重命名为不与模型中命名的属性冲突的内容,或者您​​可以使用不同的重载 Html.TextBox This overload of TextBox takes a value 覆盖视图中的值:

值(类型:System.Object)
文本输入元素的值。如果此值为 null,则从 ViewDataDictionary 对象中检索元素的值。如果那里不存在值,则从 ModelStateDictionary 对象中检索该值。


更新:由于您将“NewComment”作为属性添加并以这种方式解决了属性命名冲突,因此您需要做的是将 PostComment 而不是 POST 上的整个视图模型绑定到操作,只需指示模型将使用前缀的活页夹。这是使用BindAttribute 完成的。

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

【讨论】:

  • 嗯,好吧,那是两个人告诉我将值覆盖为string.Empty,所以我想这就是我要做的。我只是认为会有更好的方法来构建模型/视图,这样甚至不会发生这些冲突。
  • 你可以用不同的方式构造它来避免碰撞。 @Jakub Konecki 走在正确的轨道上。将名为“NewComment”的 PostComment 属性添加到 BlogPost 模型类。然后你的视图代码看起来像 @Html.TextBoxFor(x => x.NewComment.Body);
  • 对,除非我必须接受视图模型作为 AddComment 操作方法中的参数,而不是接受简单的 PostComment 对象。如问题中所述,我已经尝试过一次。
  • 喜欢这个更新。解决了我所有的问题,没有任何俗气的价值压倒一切。谢谢!
【解决方案2】:

使用 ASP NET MVC 模板,这样您就可以完全控制填充的内容并且它是类型安全的。

因此,您将创建一个.ascx 模板,该模板采用强类型Comment。在你的模型中,你留下一个空的。

【讨论】:

  • 这是否意味着AddComment 操作方法必须接受BlogPostViewModel 作为参数而不仅仅是PostComment?这似乎很奇怪,发回一个具有所有空属性的视图模型对象,除了我之后的那个。也许我错了,这很正常。
  • 没有。你会通过Model.EditorFor(m =&gt; m.Comment)
  • 在视图中是的,但是操作方法需要接受视图模型对象,而不是PostComment 对象,对吗?我现在正在测试它以验证。
  • 是的,刚刚检查过。因为NewCommentBlogPostViewModel 的属性,所以我需要接受BlogPostViewModel 作为AddComment 操作方法的参数,而不是简单的PostComment 更简洁的参数。
  • 查看这个截图codetunnel.com/POST_ScreenShot.jpg,你会注意到表单值前面有NewComment.Property,而不是视图模型对象的一部分,它们只是PropertyNewComment.Property 导致它不绑定,除非我接受视图模型对象本身作为参数。
【解决方案3】:

TextBox 上不是有一个需要一个值的重载吗?你可以通过string.Empty...

【讨论】:

  • 是的,但这似乎很骇人听闻。感觉应该有更好的办法。
  • 但我相信他想要用户输入的值。在 POST 发生后,用户的值被默认模型绑定器破坏了。
  • 我认为这是一种正确的方式——你想渲染一个空的表单。您可以绑定到 PostComment.... 的空实例。
  • 没关系,我读错了这个问题。无视我:)
  • @Matt 不,POST 很好。如果用户删除模型绑定器放入的现有值并发布表单,则值正确提交。令人讨厌的是,表单字段预加载了来自 BlogPost 模型的值,即使它们本来是空的 PostComment 字段。
猜你喜欢
  • 1970-01-01
  • 2011-08-07
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 1970-01-01
  • 2020-03-14
  • 1970-01-01
相关资源
最近更新 更多