debracey
debracey

Reputation: 6597

Loading Modular ASP.NET Components at Runtime

I'm building an ASP.NET website that will act as a "framework" and display information about some services that are running on the web server. One of the things that the site needs to do is serve up custom configuration pages for some modules that have been loaded by the service. The modules will all implement a common API, so there is no concern there -- my concern is how can I get configuration pages, which are unique to each module, served up by a common front end?

The pages need to validate user input, handle button clicks, etc. So it's not as simple as having a method on each module:

public string getHTMLConfigPage()

That would only work if the module's config page didn't require user input. In this case, all of the modules will require some form of configuration, at the very least a checkbox indicating "turn on/off"

Here's the ideal use case:

  1. At run time the IIS process talks to the back end service and figures out there are N modules running
  2. The server adds links for these N # modules to a drop down menu
  3. When the user clicks the menu item for a module, the module's configuration page is displayed
  4. The user configures the module however they wish, with the individual module controlling that entire sequence

We've already implemented this successfully in C# winforms. The way we did it there was to have each module implement a method public void showConfigDialog(IWin32Window parent);. That works well for a regular desktop app -- but obviously doesn't help me do anything with the web server.

The only thing that I have thought of so far is to have each module also install some stuff onto the IIS web server, and then just do an iFrame where the main "framework" page can display the module's page in the frame (or a popup window), but that seems messy in that the module developer has to then include some kind of setup scripts to put stuff into the IIS space...

So - is there a better way to do this, or is the iFrame method the only way?

Systen Details:

EDIT: Additional Details

I have also thought about having the modules place a special ASP.NET DLL in a directory that ASP.NET will probe at runtime. But the root of the problem remains -- how can the DLL provided by module get integrated into the main set of web pages? The main set of web pages have a Site.Master page that provides some required items (CSS, menu bar, some jQuery addons, etc.). The DLLs from the modules will likely need this information plus a named pipe that the main web pages use to talk back to an underlying windows service we have written.

Upvotes: 1

Views: 1849

Answers (4)

Giscard Biamby
Giscard Biamby

Reputation: 4619

Most of what you described is implemented in Orchard CMS. http://orchardproject.net. You might consider looking at their code as an example for how to accomplish this dynamic module loading, or if possible just switching over to Orchard as the framework for your app. It's known as a CMS, but really it's a nice framework to build a .NET app on top of.

They use Autofac for depedency injection, and modules can inject their own Routes, Content, Pages, etc, by implementing interfaces. Orchard's core framework scans those modules for classes that implement specific interfaces, and then call the methods on those interfaces to pull the specific content from the modules. You can enable/disable modules from the command line or from the web interface.

For example I can create a module, and then in there I'll have a class that implements an interface called INavigationProvider that has methods Orchard uses to get the menu items for the admin dashboard. Then I can implement the IRouteProvider interface in another class, that tells Orchard about all the routes for my app (both front end and admin dashboard). You can also use MVC conventions for Views/Controllers/Routes. There is support for both Razor and WebForms view engines.

Upvotes: 1

OnoSendai
OnoSendai

Reputation: 3970

I would suggest:

  • A baseline plugin structure model with mutual structure access, so the plugin host would be able to instantiate/initialize the individual plugins, and pass itself (or a choice of model classes) as reference.
  • A HTTP Module, in order to iterate through loaded plugins and push the context pages so they can be processed by the plugins in a pipeline model. That way you would even be able to choose specific events to fire in specific moments - say, fire a search for a Gravatar icon/OpenID auth after the user types an email, and post the collected data on the model classes served by the plugin host.

Upvotes: 0

Quinton Bernhardt
Quinton Bernhardt

Reputation: 4803

It sounds like you need a plug-in framework for ASP.NET. You could achieve this by using MEF (Managed Extensibility Framework) which will allow you to put the complex pages and configuration into a plug-in and load it at runtime; or so I believe.

Start by checking out a Code Project article here, and there maybe the MSDN example here.

Upvotes: 3

adripanico
adripanico

Reputation: 1058

If you have the different scenarios well defined, I think is not a problem to treat with data from a page in other class or from another embebed project or library. For example, for populate the data in the DropDownList you can do:

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

End Class

Then, you can have in other file:

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: sorry for the vb code

Upvotes: 0

Related Questions