如何在ASP.NET MVC 5中使用不同模型的部分视图?

时间:2015-05-03 20:58:45

标签: asp.net asp.net-mvc asp.net-mvc-5

您好我正在尝试使用ASP.NET MVC 5 Framework编写一个简单的博客。我做了帖子的CRUD操作。我的意思是我可以添加新文章并管理它们。当我想为文章添加评论时,我坚持了下来。评论将添加到文章的详细信息页面。所以我应该在详细信息页面添加创建评论页面。

我使用Code First模型,我有两个模型。文章和评论。我决定使用部分视图来输入评论。但结果是一个错误:

传入字典的模型项的类型为&System; System.Data.Entity.DynamicProxies.Article,但此字典需要类型为' Blog.Models.Comment'的模型项。 。评论无法添加。我创建了2个 PartialViews ,其中一个是 _CreateComments PartialView ,另一个是 _Index PartialView

详细信息视图

@model Blog.Models.Article

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

 <div>
<h4>Article</h4>
<hr />
<dl class="dl-horizontal">
    <dt>
        @Html.DisplayNameFor(model => model.Title)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Title)
    </dd>

    <dt>
        @Html.DisplayNameFor(model => model.Author)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Author)
    </dd>

    <dt>
        @Html.DisplayNameFor(model => model.Date)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.Date)
    </dd>

    <dt>
        @Html.DisplayNameFor(model => model.ArticleContent)
    </dt>

    <dd>
        @Html.DisplayFor(model => model.ArticleContent)
    </dd>

</dl>
 </div>
 <div class="jumbotron">
  @Html.Partial("~/Views/Comments/_CreateComments.cshtml", new Blog.Models.Comment())
  @Html.Partial("~/Views/Comments/_Index.cshtml", new List<Blog.Models.Comment> { new Blog.Models.Comment() })
   </div>

_CreateComment PartialView

  @model Blog.Models.Comment
   @using (Html.BeginForm("Create")) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Comment</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.Date, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Date, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Date, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.CommentContent, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.CommentContent, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.CommentContent, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
 }

<div>
@Html.ActionLink("Back to List", "Index")
</div>

_Index PartialView      @model IEnumerable

 <table class="table">
<tr>
    <th>
        @Html.DisplayNameFor(model => model.Date)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.CommentContent)
    </th>
    <th></th>
</tr>

 @foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => item.Date)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.CommentContent)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id=item.CommentId }) |
        @Html.ActionLink("Details", "Details", new { id=item.CommentId }) |
        @Html.ActionLink("Delete", "Delete", new { id=item.CommentId })
    </td>
</tr>
 }

 </table>

2 个答案:

答案 0 :(得分:1)

您的代码存在许多问题。

  1. @using (Html.BeginForm())表示它会回发给 Details()方法(假设是生成该方法的动作) 视图),所以需要@using (Html.BeginForm("Create"))
  2. 您的生成控件将具有name属性,例如 与name="Item2.Date"无关的Comment class(Comment没有名为Item的属性 具有名为Date
  3. 的属性的复杂对象
  4. DateTime属性的默认值为1.1.0001 00:00:00 意味着您尚未初始化该值(例如Date = DateTime.Today;),但不清楚为什么需要用户 无论如何输入一个日期 - 肯定会设置为今天的日期 保存评论之前的控制器。
  5. 您尚未说明哪些脚本 @Scripts.Render("~/bundles/jqueryval")正在生成,但假设 你使用jQueryUI datepicker,至少需要你 jquery-{version}.jsjquery-ui-{version}.js(加jquery.validate.jsjquery.validate.unobtrusive.js进行验证)
  6. 您的表单中有一个表格,不会显示任何其他表格 新Comment的初始值(与...完全相同) 正在显示在文本框中)所以它似乎有点无意义
  7. 另请注意,您的视图不会显示任何看似不寻常的文章的现有评论。

    有很多方法可以解决这个问题,包括ajax,以便用户可以保持在同一页面上并继续添加更多评论,但根据您当前的用户界面,那么Details视图中的模型应该只需Article并使用部分代码为新Comment

    呈现表单

    控制器

    public ActionResult Details(int? id)
    {
        ....
        Articles article = db.Articles.Find(id);
        ....
        return View(article);
    }
    
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Comment model)
    {
        if (ModelState.IsValid)
        {
            model.Date = DateTime.Today; // set date before saving
            db.Comments.Add(model);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ....
    }
    

    查看

    @model yourAssembly.Article
    
    // Render properties of Article 
    ....
    
    // Add form for creating a new comment
    @Html.Partial("_Comment", new yourAssembly.Comment)
    
    // Add required scripts including jquery ui
    

    和部分视图(_Comment.cshtml)

    @model yourAssembly.Comment
    @using (Html.BeginForm("Create"))
    {
      @Html.LabelFor(m => m.Content, new { @class = "control-label col-md-2" })
      @Html.TextBoxFor(m=> .m.Content, new { @class = "form-control" } })
      @Html.ValidationMessageFor(m=> m.Content, new { @class = "text-danger" })
      <input type="submit" value="Create" class="btn btn-default" />
    }
    

    附注:

    1. 请勿在视图中使用Tupple,尤其是视图 涉及编辑,因为它生成没有的name属性 与你的模型的关系。始终使用视图模型。
    2. 您没有为CommentId属性生成控件 在[Bind]属性中(并且实际上)并不包括它 意味着某人可以回发一个值并导致您的代码 抛出异常。
    3. 使用<dl><dt><dd>标签不适合您 view(它们用于一个描述列表,带有术语和 描述)。使用<div><span>元素。

答案 1 :(得分:1)

您必须为此目的使用ViewModel。在POST中,它将获得所需的信息。在GET中,您将发送所需的信息。

例如:在GET中,您将发送文章和所需的区域。但在POST中,您将收到评论和评论者的姓名和日期等。