ASP.NET Core MVC如何将ViewModel发送到不同的控制器方法

时间:2017-12-10 17:56:30

标签: c# asp.net-mvc asp.net-core-mvc asp.net-core-2.0

所以我有2个控制器类;

AnnouncementsController,这只会生成一个主页,其中包含来自用户的帖子。

// GET: Announcements
    public async Task<IActionResult> Index()
    {
        var announcements = await _context.Announcement.ToListAsync();
        announcements = announcements.OrderByDescending(x => x.CreatedOn).ToList();
        foreach (var ann in announcements)
        {
            ann.TimeAgo = ann.CreatedOn.TimeAgo();
        }

        var users = await _context.Users.ToListAsync();
        var comments = await _context.Comment.ToListAsync();
        AnnouncementAndCommentsViewModel aacVM = new AnnouncementAndCommentsViewModel();

        AnnouncemenstViewModel announcemenstViewModel = new AnnouncemenstViewModel();
        announcemenstViewModel.Announcement = announcements;
        announcemenstViewModel.User = users;
        announcemenstViewModel.Comment = comments;

        CommentViewModel commentViewModel = new CommentViewModel();

        aacVM.announcemenstViewModel = announcemenstViewModel;
        aacVM.commentViewModel = commentViewModel;

        ViewData.Add("currentUserID",GetCurrentUser().Id);

        return View(aacVM);
    }

然后我有了CommentsController

[HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(CommentViewModel commentViewModel)
    {
        if (ModelState.IsValid)
        {
            var comment = new Comment();
            comment.CreatedOn = DateTime.Now;
            comment.Body = commentViewModel.Comment.Body;

            Announcement announcement = GetAnnouncement(commentViewModel.Announcement.AnnouncementID);
            comment.Announcement = announcement;
            ApplicationUser user = GetCurrentUser();
            comment.User = user;

            _context.Add(comment);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(commentViewModel);
    }

从我的AnnouncementController索引视图中我有一个帖子列表,然后我希望能够直接在该视图中编写和添加注释,而不是转到另一个视图。

我有2个ViewModel,一个用于存储公告,另一个用于评论。

我试图在评论控制器中使用它接受CommentViewModel的参数调用Create Post方法,尽管我无法弄明白。 我一直被发送到创建获取方法,并填充了正文。

这是我的索引视图以及我如何尝试将数据发布到CommentsController

@model Treharris.Models.AnnouncementAndCommentsViewModel;
.
.
.
@foreach (var item in Model.announcemenstViewModel.Announcement)
        {
.
.
.
<div class="announcement-body">
                    <p>@Html.DisplayFor(modelItem => item.Body)</p>
                </div>
                <div class="comments">
                    <p id="comment">Comments</p>
                    @using(Html.BeginForm("Create","Comments", FormMethod.Post, 
                     new { cvm = Model.commentViewModel }))
                    {
                        @@Model.commentViewModel.Announcement = item;
                        @Html.HiddenFor(m => m.commentViewModel.Announcement)
                        @Html.TextBoxFor(m => m.commentViewModel.Comment.Body, 
                        new { placeholder = "Comment body" })
                        <input type="submit" value="Create" />

                    }

1 个答案:

答案 0 :(得分:2)

正如@Shyju评论的那样,为了使用表单扩展进行模型绑定,传递给View的Model必须与post动作接收的模型相同。

如果查看生成的HTML,

@Html.HiddenFor(m => m.commentViewModel.Announcement)

输出一些内容

<input type="hidden" name="commentViewModel.Announcement" value="propVal" />

在操作上,您希望CommentViewModel对象具有名为commentViewModel无属性,但具有名为Announcement的属性 。这就是没有发生绑定的原因。

更改post action方法上的参数以匹配View Model,但请注意表单上不存在的所有属性都将发布为null,

删除在.NET Core中不推荐使用的Html表单扩展方法,并使用简单的Html进行这些类型的绑定,如下所示:

<form asp-controller="Comments" asp-action="Create" method="post">
        <input type="hidden" name="Announcement" value="@Model.commentViewModel.Announcement" />
        <input type="text" name="Comment.Body" placeholder="Comment body" value="@Model.commentViewModel.Comment.Body" />
        <input type="submit" value="Create" />
</form>

请记住将有关Announcement对象的所有信息都包含为隐藏字段,因为您无法在表单上发布复杂对象。这是一个HTML功能/限制。

例如,simple包含表单中的公告ID:

<input type="hidden" name="Announcement.Id" value="@item.id" />