ASP.NET MVC模型绑定子对象

时间:2011-05-17 07:33:49

标签: asp.net-mvc model-binding

我正在研究ASP.NET MVC 3应用程序。我有一个Comment类,它封装了一个Post类(每条评论都与博客中的帖子相关联),还有一个用于编辑评论的动作方法,如下所示,

    [HttpPost]
    [Authorize(Users = admin)]
    public string EditComment(Comment comment)
    {
        //update the comment by calling NHiberante repository methods
    }

从javascript我只发布注释对象值,如注释id,描述到服务器,所以在绑定时我看到注释对象里面的Post属性为null,当我做ModelState.IsValid我变空错误。我的问题是如何将post对象绑定到注释?我可以将post id和其他值一起传递给服务器。

由于 Vijaya Anand

2 个答案:

答案 0 :(得分:4)

提供其他字段

如果您希望预先填充帖子实例,则还必须包含其必填字段。

我怀疑你有一个帖子视图,其中用户有一个显示评论字段的表单,以便他们可以在帖子上发表评论。

假设你有以下课程:

public class Post
{
    public int Id { get; set; }

    [Required]
    public string Title { get; set; }

    public string Content { get; set; }
}

public class Comment
{
    public int Id { get; set; }

    [Required]
    public string Author { get; set; }

    [Required]
    public string Content { get; set; }

    public Post Post { get; set; }
}

通常的浏览器POST

您需要做的是在表单中添加帖子字段(隐藏类型)。无论你是否使用强类型视图,我都不知道你是如何创建表单的......无论如何。您的输入必须具有名称:

  • Post.Id(为了将新评论附加到特定帖子
  • Post.Title(因为我已经根据需要设置了它,但你可以在这里输入任何虚拟文本,如果你将要使用的是Post.Id;标题只需要设置,这样你的模型验证就不会失败)
  • 作者 - 可见(这是评论作者)
  • 内容 - 可见(这是评论内容)

您是使用Html帮助程序创建这些字段还是手动创建并不重要。默认模型绑定器将能够创建post对象实例,并且模型验证不会失败。

Ajax POST

如果您使用Ajax发布您的评论,您可以执行与上一个示例中所述相同的操作,只需使用jQuery的.serialize()函数,该函数将在调用$.ajax()时序列化表单字段。

但你也可以使用Javascript以programmaticaly方式收集所有字段并将该数据发布到服务器上。您只需创建一个JSON对象:

var comment = {
    Author: $("#Author").val(),
    Content: $("#Content").val(),
    Post: {
        Id: $("#Post_Id").val(),
        Title: $("#Post_Title").val()
    }
};

$.ajax({
    url: "someURL",
    type: "POST",
    data: $.toDictionary(comment),
    success: function(data) {
        // probably get a partial view with comment you can append it to comments
    },
    error: function(xhr, status, err) {
        // process error
    }
});

这里有两件事需要解释:

  1. Ajax错误处理也会消耗无效的模型状态错误(模型验证失败)并且可以完成this way

  2. 通过使用可以be found here的特殊$.toDictionary()插件来转换复杂(多级)JSON对象,并提供了简单地使用复杂的JSON对象的能力。 Asp.net MVC默认模型绑定器。它的日期和清单也很糟糕。

答案 1 :(得分:0)

我认为您在Controller上寻找TryUpdateModel或UpdateModel方法。您可以通过将Comment作为参数传递(如您在示例中所做的那样)或通过调用UpdateModel方法进行绑定。

如果您从数据库中获取(正如您所做的那样),则应使用这些方法更新现有实体,而不是创建新实体。

我可能看起来像这样:

       [HttpPost]
       [Authorize(Users = admin)]
        public string EditComment(int id, FormCollection form)
        {
               //update the comment by calling NHiberante repository methods

               // Fetch comment from DB
                var comment =  NHibernateHelper.Get<Comment>(id);

                // Update the comment from posted values
                TryUpdateModel(comment);

                // Handle binding errors etc.
                if (!ModelState.IsValid)
                {
                    // On error
                }

            // Commit to DB
            NHibernateHelper.Update<Comment>(comment);


            //Done!



        }

我也在使用NHibernate,它在这个实现中效果很好。