在运行时加载模块化ASP.NET组件

时间:2012-12-06 23:03:55

标签: c# asp.net

我正在构建一个ASP.NET网站,它将充当“框架”并显示有关Web服务器上运行的某些服务的信息。站点需要做的一件事是为服务加载的某些模块提供自定义配置页面。这些模块都将实现一个通用的API,所以不用担心 - 我关心的是如何获得配置页面,这些页面是每个模块独有的,由公共前端提供服务?

页面需要验证用户输入,处理按钮点击等。因此,这并不像在每个模块上使用方法那么简单:

public string getHTMLConfigPage()

这只有在模块的配置页面不需要用户输入时才有效。在这种情况下,所有模块都需要某种形式的配置,至少一个复选框指示“打开/关闭”

这是理想的用例:

  1. 在运行时,IIS进程与后端服务进行通信,并确定有N个模块正在运行
  2. 服务器将这些N#模块的链接添加到下拉菜单
  3. 当用户单击模块的菜单项时,将显示模块的配置页面
  4. 用户按照自己的意愿配置模块,单个模块控制整个序列
  5. 我们已经在C#winforms中成功实现了这一点。我们这样做的方法是让每个模块实现一个方法public void showConfigDialog(IWin32Window parent);。这适用于常规桌面应用程序 - 但显然无法帮助我对Web服务器做任何事情。

    到目前为止,我唯一想到的是让每个模块也在IIS Web服务器上安装一些东西,然后只需执行iFrame,其中主“框架”页面可以显示模块的页面在框架(或弹出窗口)中,但这看起来很混乱,因为模块开发人员必须包含某种设置脚本以将内容放入IIS空间......

    那么 - 有更好的方法吗,或者iFrame方法是唯一的方法吗?

    Systen详细信息:

    • ASP.NET 4.0
    • C#.NET 4.0
    • IIS 7.5(Server 2008 R2)

    编辑:其他详细信息

    我还想过让模块在ASP.NET将在运行时探测的目录中放置一个特殊的ASP.NET DLL。但问题的根源仍然存在 - 模块提供的DLL如何集成到主要的网页集中?主要的网页集有一个Site.Master页面,提供一些必需的项目(CSS,菜单栏,一些jQuery插件等)。来自模块的DLL可能需要这些信息以及主网页用来与我们编写的底层Windows服务进行对话的命名管道。

4 个答案:

答案 0 :(得分:3)

听起来你需要一个ASP.NET的插件框架。您可以通过使用MEF(托管扩展性框架)来实现这一点,它允许您将复杂的页面和配置放入插件并在运行时加载它;或者我相信。

首先查看代码项目文章here,可能还有MSDN示例here

答案 1 :(得分:1)

您描述的大多数内容都是在Orchard CMS中实现的。 http://orchardproject.net。您可以考虑将其代码视为如何完成此动态模块加载的示例,或者如果可能,只需切换到Orchard作为应用程序的框架。它被称为CMS,但实际上它是一个很好的框架来构建.NET应用程序。

他们使用Autofac进行依赖注入,模块可以通过实现接口注入自己的路由,内容,页面等。 Orchard的核心框架扫描这些模块以获取实现特定接口的类,然后调用这些接口上的方法从模块中提取特定内容。您可以从命令行或Web界面启用/禁用模块。

例如,我可以创建一个模块,然后在那里,我将有一个实现名为INavigationProvider的接口的类,该接口具有Orchard用于获取管理仪表板的菜单项的方法。然后我可以在另一个类中实现IRouteProvider接口,告诉Orchard我的应用程序的所有路由(前端和管理仪表板)。您还可以对视图/控制器/路由使用MVC约定。支持Razor和WebForms视图引擎。

答案 2 :(得分:0)

如果您已经明确定义了不同的场景,我认为处理来自其他类或其他已嵌入项目或库中的页面的数据不是问题。例如,要填充DropDownList中的数据,您可以执行以下操作:

Partial Class Default
  Inherits System.Web.UI.Page

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      If Not Page.IsPostBack Then
          Dim itemList As List(Of ListItem) = ClassForTheMagic.GetItemsForComboBox(txtBox1.Text, checkBox2.check, ...)
          For Each item As ListItem In itemList
              DropDownList1.Items.Add(item)
          Next
      End If
  End Sub

结束班

然后,您可以拥有其他文件:

Public Class ClassForTheMagic

  Public Shared Function GetItemsForComboBox(ByVal txtBox1 As String, ByVal checkBox2 As Boolean, ...) As List(of ListItem)
      Dim itemList As New List(Of ListItem)
      itemList.Add(New ListItem(txtBox1, "..."))
      itemList.Add(New ListItem(checkBox2, "..."))
      ...
      Return itemList
  End Function

End Class

ps:对不起vb代码

答案 3 :(得分:0)

我建议:

  • 具有相互结构访问权限的基线插件结构模型,因此插件主机可以实例化/初始化各个插件,并将自身(或选择的模型类)作为参考传递。
  • HTTP模块,为了迭代加载的插件并推送上下文页面,以便管道模型中的插件可以处理它们。这样,您甚至可以在特定时刻选择要触发的特定事件 - 例如,在用户键入电子邮件后触发搜索Gravatar图标/ OpenID身份验证,并将收集的数据发布到插件主机提供的模型类上