5

您将如何在 ASP.NET MVC 视图中支持外部可组合部件?

我这是什么意思?想想“每个页面上的登录框”或“iGoogle”。这是需要在每个控制器/视图外部的某些地方的东西。

一种方法是在视图中添加组件,如下所示:

<% foreach (var component in GetComponents()) {%>
    <%= Html.RenderPartial(component.ViewName, component.ViewData)%>
<%} %>

在上面的示例中,我正在寻找一种让每个组件的控制器而不是显示它们的视图的控制器传递视图名称和视图数据的好方法。您可以建议的任何完全不同的解决方案也会很有趣。过滤器、WebForms 等

更新:我将尝试用一个例子来解释我想要理解的内容。我将选择登录功能。

在典型的 webforms 应用程序中,这可能是一个用户控件,它在页面生命周期的加载事件中检索适当的数据并更新一些 UI 控件。单击页面后,页面将回发,我们可以对同一用户控件中单击事件中发布的信息采取行动。

根据我目前对 ASP.NET MVC 样式的理解,首先接受请求的控制器将检索适当的数据并将其传递给视图,该视图又将其传递给登录部分视图。登录视图将定义一个表单,其发布操作针对登录控制器的登录操作。发布的信息由登录操作使用,我们可以选择使用一些漂亮的方案将请求传递给原始控制器。

我假设有一种比上面更聪明的方法,不需要我将控制器逻辑放在视图/母版页中。

4

4 回答 4

5

有两种方法可以做到这一点:

一:制作一个BaseController,它总是获取这些组件所需的数据,设置ViewData[“loginbox”] = loginBoxData,然后你可以像这样传递它。

<% foreach (var component in GetComponents()) {%>
        <%= Html.RenderPartial(component.ViewName, ViewData[component.Name])%>
<%} %>

这种方法的问题在于,您需要有逻辑来说明何时获取组件所需的所有这些数据,以及何时不获取。

二:

有一个 MVC Futures DLL,您可以从这里下载。

如果您引用它,并记住将其命名空间添加到您的 web.config,那么您应该能够说:Html.RenderAction("blah")- 此方法通过联系控制器、启动视图并返回 HTML 来完成整个行程。

于 2009-01-18T09:17:26.070 回答
2

您可以使用母版页并使用内容占位符来查看内容页面和查看用户控件。

ASP.NET MVC Framework Beta 中的默认项目模板具有用于查看内容页面的内容占位符。页面右上角还有一个用于登录/注销链接的查看用户控件。

查看内容页面

视图内容页面应该与来自您正在查看的视图的数据一起使用。即,如果您正在浏览 中的Index操作HomeController,服务器将呈现Home/Index.aspx视图内容页面。

在母版页中,您需要以下行:

<asp:ContentPlaceHolder ID="Holder1" runat="server" />

在查看内容页面本身中,您为该占位符撰写以下内容:

<asp:Content ID="Content1" ContentPlaceHolderID="Holder1" runat="server">
  <p>This text goes to "Holder1" content place holder and
     I can access the ViewData.</p>
  <p><%= ViewData["Message"] %>
</asp:Content>

每个都通过 idasp:ContentPlaceHolder对应于视图。asp:Content所以如果你想要几个这样的占位符:

<asp:ContentPlaceHolder ID="Holder1" runat="server" />
<asp:ContentPlaceHolder ID="Holder2" runat="server" />

…您可以像这样在视图内容页面中处理它们:

<asp:Content ID="Content1" ContentPlaceHolderID="Holder1" runat="server">
  <p>This text goes to "Holder1" content place holder</p>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Holder2" runat="server">
  <p>This text goes to "Holder2" content place holder</p>
</asp:Content>

查看用户控件

无论您正在查看什么视图,都可以使用视图用户控件。以下是查看用户控件的一些示例,取自Wekeroad 关于查看用户控件的博客文章。要使用视图用户控件:

<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”)%>

如果您有需要,您还可以将数据和匿名类型传递给它。

<%=Html.RenderUserControl(“~/UserControls/UserList.ascx”,ViewData.Users, new {GroupID=2})%>
于 2009-01-18T08:41:12.693 回答
1

在没有正确理解问题的情况下,我建议采用母版方法。IE。让母版页呈现从母版页派生的组件和页面。

我担心这不是一个好的答案。我不明白这一点:“..每个组件的控制器而不是它们所显示的视图的控制器提供的视图名称和视图数据。”

于 2009-01-17T10:43:54.507 回答
0

这是一个老问题,但这是我对它的看法:

在 CQRS 风格的应用程序中,您可以将 ICommand 推送到单个服务端点,服务会计算出如何路由它。

一个很好的例子:https ://github.com/ncqrs/ncqrs/blob/master/Framework/src/Ncqrs/Commanding/ServiceModel/CommandService.cs

怎么说 - 我们试图执行查询而不是尝试执行命令?

而不是 1 我们传递 1 或更多作为 IViewModelExecutor 的列表?

在您的主页中,您有一个主 ViewModel,它对每个子 ViewModel 都有一个定义,当页面加载时,我们要求服务获取与该视图相关的所有视图模型:

service.Load(new List<IViewModelExecutor>{UserinfoViewModel, UserAccountViewModel });

该服务从 readmodel 加载数据并在需要的地方缓存。子视图模型使用传递给子视图Html.RenderPartial("subviewname", Model.SubViewModel)

子视图知道如何根据模型渲染自己。

现在 - 因为我们有一个带有 ajax 更新的组合 UI - 假设我们想要更新页面的 UserAccount 部分。在控制器中,我们有一个动作负责渲染该部分。

它也可以从service.Load(new List<IViewModelExecutor>{UserAccountViewModel })

并且只取回它需要的视图模型的一部分——可能是缓存的。除非参数改变 obv。

现在我们有了一个可以全部或部分构建的组合 UI。

使用内容协商,我们可以根据请求中的 HTTP 标头提供 HTML 片段、JSON 或 XML。

于 2012-02-04T01:54:09.157 回答