【问题标题】:Why does the PartialView keep calling itself?为什么 PartialView 一直在调用自己?
【发布时间】:2023-04-06 04:02:02
【问题描述】:

我尝试设置一个小演示,其中一篇文章有​​多个 cmets。文章详细信息视图应在部分视图中呈现 cmets。 partialView 本身包含另一个用于添加新评论的局部视图。

当我尝试添加另一条评论时,我收到了InsufficientExecutionStackException,因为控制器中的操作一直在调用自身。为什么会这样?

(如果有人手头有课程资料。类似的例子应该是 Msft 的 70-486 课程的第 9 单元;这就是我试图建立的。)

编辑:完整代码在github

Edit2: Github 上的示例已修复。正如 Stephen Muecke 指出的那样,GETPOST 方法名称相同的事实导致了循环引用。 在更多人指出之前,缺少 DI 和视图模型并且重新渲染所有 cmets 是次优的:是的,我知道,不,这些事情都不是我想要完成的。这只是一个快速的肮脏演示。

控制器:

[ChildActionOnly]
public PartialViewResult _GetCommentsForArticle(int articleId)
{
    ViewBag.ArticleId = articleId;
    var comments = db.Comments.Where(x => x.Article.ArticleId == articleId).ToList();
    return PartialView("_GetCommentsForArticle", comments);
}


public PartialViewResult _CreateCommentForArticle(int articleId)
{
    ViewBag.ArticleId = articleId;
    return PartialView("_CreateCommentForArticle");
}

[HttpPost]
public PartialViewResult _CreateCommentForArticle(Comment comment, int articleId)
{
    ViewBag.ArticleId = articleId;
    comment.Created = DateTime.Now;
    if (ModelState.IsValid)
    {
        db.Comments.Add(comment);
        db.SaveChanges();
    }
    var comments = db.Comments.Where(x => x.Article.ArticleId == articleId).ToList();
    return PartialView("_GetCommentsForArticle", comments);
}

Details.cshtml 中文章的相关行:

@Html.Action("_GetCommentsForArticle", "Comments", new { articleId = Model.ArticleId})

_GetCommentsForArticle:

@model IEnumerable<Mod9_Ajax.Models.Comment>
<div id="all-comments">
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Text)
            </th>
        </tr>

        @foreach (var item in Model)
        {
           @* ... *@
        }
    </table>
</div>
@Html.Action("_CreateCommentForArticle", "Comments", new { articleId = ViewBag.ArticleId })

_CreateCommentForArticle:

@model Mod9_Ajax.Models.Comment
@using (Ajax.BeginForm("_CreateCommentForArticle", "Comments", new AjaxOptions
{
    HttpMethod = "POST",
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "all-comments"
}))
{
    @* ... *@

        <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>
}

【问题讨论】:

  • 顺便说一句,如果培训材料指示您将实体模型类用作 ViewModel 或 DTO,那么我应该告诉您这是不好的做法 - 始终使用专用的 ViewModel/DTO 类型而不是重新- 使用实体模型类型。
  • 我刚刚通过一个简单的CommentsController::Details 操作在一个新的空项目中复制了您的观点,但我无法重现此问题。你能把你的整个项目发布在某个地方的 Zip/存档中吗?
  • 当视图中已经包含所有 cmets 时,为什么 POST 方法会返回它们(而不是仅仅将新注释附加到视图中)
  • @StephenMuecke 理论上:添加新评论;获取所有 cmets;用新的有效载荷替换现有的 cmets。 Dai:在这种情况下,我不关心 vms、DI、存储库或任何其他好的实践。只是想完成它。
  • 似乎没有必要再次重新渲染所有现有的 cmets,但我同意@Dai - 您显示的代码不会导致 控制器中的操作不断调用自己 - 这是你没​​有向我们展示的其他东西。

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


【解决方案1】:

为了解释正在发生的事情,您有一个向您发布_CreateCommentForArticle() 方法的表单,该方法然后呈现您的_GetCommentsForArticle.cshtml 部分,而这又包含@Html.Action("_CreateCommentForArticle", ...)

Details() 的初始 GET 方法中,视图将正确呈现,但是当您提交表单时,_GetCommentsForArticle 页面的当前请求是 [HttpPost] 方法,因此 @Html.Action() 将寻找[HttpPost] 方法(不是 [HttpGet] 方法)。 [HttpPost] 依次渲染 _GetCommentsForArticle.cshtml 部分并再次调用 _CreateCommentForArticle() POST 方法,该方法渲染 _GetCommentsForArticle.cshtml 部分等等,直到内存不足并引发异常。

您可以通过更改 POST 方法的名称来解决此问题,例如

[HttpPost]
public PartialViewResult Create(Comment comment, int articleId)

并修改表格以适应

@using (Ajax.BeginForm("Create", "Comments", new AjaxOptions { ...

【讨论】:

  • 我只是坐在实验室里,得出了同样的结论。这正是失败的原因。一旦我用[HttpPost, ActionName("_PostCreate")] 修饰了动作并修改了Ajax.BeginForm,它就开始起作用了。
  • 您的应用程序中有很多不必要的代码,并且您通过至少进行 2 次不必要的数据库调用而降低了性能。当我有机会时,我会用更多的 cmets 更新答案。
  • 我完全了解所有(嗯,大多数)缺点。我正在为循环引用挠头。该代码是 Visual Studio 的默认 mvc 模板,然后添加了模型和 DAL 来证明我的观点。 (这确实是 70-486 课程演示 Ajax 的方式。仔细检查)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
相关资源
最近更新 更多