ASP.NET MVC中的可重用组件

时间:2010-11-10 04:11:20

标签: asp.net-mvc asp.net-mvc-2 partial-views renderaction

我的网站上有一些功能(一些用户界面和相关功能),我希望能够在多个页面上重复使用。出于这个问题的目的,让我们说这是一个“评论”功能。

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

CommentController看起来像这样:

/Views/Comment/Create.ascx

索引部分视图:

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> 的视图中,如下所示:

RenderAction

此代码不起作用,因为部分视图中的表单提交给标记为<% Html.RenderAction("Index", "Comment", new { area = "Components" }); %> 的CommentsController上的操作(这是设计的,我不希望独立于“组件”请求托管页面)。

如何使这个“组件”方法起作用,即有一个部分视图提交表单以更改页面中组件的状态而不会丢失托管页面本身?

修改 为了澄清,使用[ChildActionOnly]不是我的问题。如果我从我的动作方法中删除属性,我的代码只会“起作用”,因为它不会引发异常。提交表单时,我的“组件”仍会突破其托管页面(因为我告诉表单提交到部分视图的URL!)。

2 个答案:

答案 0 :(得分: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罗琳那样开发巫师之后幸福地生活......

答案 1 :(得分:1)

使用Ajax发布部分内容。