1

我的网站上有一些我希望能够在多个页面上重复使用的功能(一些 UI 和相关功能)。就这个问题而言,假设它是一个“评论”功能。

在我的组件应用程序中有一个区域,该区域中有一个控制器:/Controllers/CommentController和两个部分视图:(/Views/Comment/Index.ascx用于列出评论)和/Views/Comment/Create.ascx(用于创建评论)。

CommentController 看起来像这样:

public class CommentController : Controller
{      
  [ChildActionOnly]
  public ActionResult Index()
  {
      return PartialView(GetComments());
  }

  [HttpGet]
  [ChildActionOnly]
  public ActionResult Create()
  {
      return PartialView(); //this is wrong.
  }

  [HttpPost]
  [ChildActionOnly]
  public ActionResult Create(FormCollection formValues)
  {
      SaveComment(formValues);

      return RedirectToAction("Index"); //this is wrong too.
  }
}

索引部分视图:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>

<div>
  <% foreach (var item in Model) { %>    
      <div>
          <%: item.Comment %>
      </div>
  <% } %>

  <%: Html.ActionLink("Add a Comment", "Create", "Comment", new { area = "Components" }, null) %>
</div>

创建局部视图:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<div>
    <% using (Html.BeginForm())
       {%>
        Enter your comment:
        <div>
            <input type="text" name="comment" />
        </div>
        <p>
            <input type="submit" value="Create" />
            <% //also render a cancel button and redirect to "Index" view  %>
        </p>
    <% } %>
</div>

Index 部分视图包含在带有 的视图中RenderAction,如下所示:

<% Html.RenderAction("Index", "Comment", new { area = "Components" }); %>

此代码不起作用,因为部分视图中的表单提交给 CommentsController 上标记的操作[ChildActionOnly](这是设计使然,我不希望独立于托管页面请求“组件”)。

我怎样才能使这种“组件”方法起作用,即有一个提交表单以更改页面内组件状态而不丢失托管页面本身的部分视图?

编辑: 澄清一下,[ChildActionOnly]这里的使用不是我的问题。如果我从我的操作方法中删除该属性,我的代码只会“起作用”,因为它不会引发异常。提交表单时,我的“组件”仍然会跳出其托管页面(因为我告诉表单提交到部分视图的 URL!)。

4

2 回答 2

3

您通过要求表单以标记为 ChildActionOnly 的操作为目标,从而使 MVC 与自己战斗。

当我设计一个高度可重用的向导框架时,我对这个问题的解决方案是不将操作标记为 ChildActionOnly,而是检测请求是 ajax 请求还是只是普通的 vanilla 请求。

所有这些的代码都被打包到一个基本的控制器类中。在您的派生控制器中,您可以执行以下操作:

[WizardStep(4, "Illness Details")]
public ActionResult IllnessDetails()
{            
    return Navigate();
}

基本控制器的 Navigate() 方法决定是返回完整视图还是仅返回部分视图,具体取决于它是否是 ajax 请求。这样,您永远不能孤立地返回局部视图。

为了确定它是否是 Ajax 请求,我使用了 Request.IsAjaxRequest() 和 TempData 的组合。需要 TempData 是因为我的向导框架实现了开箱即用的 PRG 模式,所以我需要坚持原来的帖子是 ajax 的事实。

我想这只是一个解决方案,它需要一些试验和错误才能让它正确。但现在我像 JK 罗琳一样开发了巫师后,过着幸福的生活……

于 2010-11-10T11:11:14.197 回答
1

使用 Ajax 发布部分内容。

于 2010-11-10T04:52:30.627 回答