如何发现一个web应用程序并将其加载到另一个

本文关键字:加载 另一个 应用程序 一个 何发现 发现 web | 更新日期: 2023-09-27 18:25:50

我已经在谷歌上搜索了一段时间,也许我没有搜索到正确的术语。我想要一个能够加载/运行其他web应用程序的"shell"asp.net web应用程序(很像prism对Silverlight xap文件所做的那样)。然而,除了"子项目"之外,我似乎找不到任何其他措辞,因为它需要将项目添加到解决方案中。我只想把WebApplicationB.dll放到Bin文件夹中,让ShellWebApplication加载dll并在iframe或其他文件中显示默认页面。

如何做到这一点,或者我在哪里可以找到如何做到的信息?

更新:向能够显示代码或向我介绍如何做到这一点的示例项目的人提供奖励。希望能够"加载"另一个asp.net网站/web应用程序及其依赖项(dll或否),并显示已加载的asp.net web应用程序的default.aspx起始页,而无需更改已包含shell asp.net web应用程序的Visual Studio解决方案。

如何发现一个web应用程序并将其加载到另一个

这实际上是相当微不足道的;我们做到了。

关键是你的"模块"应该有自己的内容文件夹,或者你需要小心不要在同一位置有完全相同的文件名。

考虑以下人为的例子:

Shell
  'default.aspx
  'login.aspx
  'Images          <- images used by shell
  'css             <- primary CSS files
  'Pages'Accounts  <- all of the account editing pages here.
Module1
  'Module1'Pages       <- web pages specific to Module 1 
  'Module1'Images      <- images specific to module 1
  'CSS'Module1.css     <- Optionally, you can place the Module 1 CSS file into the main CSS directory.  

使用这种结构,您将能够将两个web应用程序复制到同一目标目录中。由于.Net的功能,这将很好地工作,并且两者都将在同一进程空间内执行。

当然,您需要一种方法让Shell了解模块1。并且您希望能够在没有Module1的情况下部署Shell。这里最好的方法是添加一个包含所需接口定义的程序集项目。您将此项目的引用添加到Shell和Module 1中。类似于:

Core
  'ObjectModel'MenuOption.cs
  'Extension'IAppModule.cs
  'Extension'PluginFactory.cs

IAppModule.cs看起来像什么:

public interface IAppModule {
  Collection<MenuOption> GetMenu( );
}

MenuOption.cs看起来像:

public class MenuOption {
  public string Href { get; set; } // url the option goes to
  public string Title { get; set; } // display name of the menu option
}

PluginFactory.cs类似于:

public sealed class PluginFactory {
  PlugingFactory() { }
  public static IAppModule LoadPlugin( string typeName ) {
    Type theType = Type.GetType(typeName);
    return (IAppModule)Activator.CreateInstance(theType);
  }
}

此处GetMenu的目的是返回对模块中可用页面的引用集合。

在Module1中,您可以实现如下接口:

public class AppModule : IAppModule {
  public Collection<MenuOption> GetMenu() {
    Collection<MenuOption> result = new Collection<MenuOption>();
    result.add(new MenuOption() { Href = "~/Module1/Pages/AccountList.aspx", Title="Account List"});
    result.add(new MenuOption() { Href = "~/Module1/Pages/NewAccount.aspx", Title="New Account"});
    return result;
  }
}

因此,在这一点上,我们有2个web应用程序项目和1个汇编项目。网络应用程序项目彼此一无所知。

下一步是告诉Shell Module1的存在。我们通过拥有可用模块的数据库表来实现这一点。您可以在web.config文件中执行同样的操作。主要是shell项目需要TypeName和对Module 1的AppModule类的引用。例如:"Module1.AppModule, Module1"

然后,在您的shell主页中,您可以执行以下操作:

protected void LoadMenu() {
  // get list of available modules, just assuming mdules is string[] 
  foreach(String moduleId in moduleIds) {
    IAppModule module = PluginFactory.LoadPlugin(moduleId);    // now you have a reference to the module
    Collection<MenuOption> options = module.GetMenu();
    // and now we have all of the menu options for that module...
  }
}

为了获得奖励,我们在shell项目的根目录中有一个名为"Main.Master"的母版页。我们的每个模块在其根目录中也有一个"Main.mast"母版页。模块中的构建操作设置为none,复制到输出设置为Do not copy。

主页面是我们实际加载菜单选项的地方。此外,每个模块中的所有其他主控器都继承自该主控器。有趣的是,派生母版页并不关心父版的实际"类型",只关心该页的位置。这意味着你可以从shell控制你的主主页面,并让每个模块"继承"它,只需不部署它们的整个主页面。

例如:

Shell
  /main.master  <- includes the basic CSS references, content structure and loads the various menus.
Module1
  /main.master  <- this file will NEVER be deployed and is only here to aid in testing the module independently of the shell
  /Module1/Module1.master <- inherits from main.master, adding other common elements for the module.

由于母版页继承的工作方式,Module1.master文件通过"~/main.master"引用其父级。通过不部署模块main.master,而只部署shell的main.master我们获得了很大的灵活性。

最后,您可以将shell项目部署到IIS服务器上。稍后,您可以在shell项目的顶部部署ModuleX(不需要虚拟目录),它就可以正常工作了。

dll包含web应用程序的编译代码。"加载dll"没有意义。您可能想加载一个控件或一个页面,然后让用户导航到此应用程序中的另一个页面或控件,其代码也包含在此dll中。因此,有几个选项可供选择:

  1. 使用iframe并指向它来加载其他web应用程序的页面。这将加载该应用程序的dll,以便执行该页面后面的代码。您可以让用户从该页面导航到应用程序的其他页面。

  2. 在shell应用程序中放置一个链接,当单击该链接时,用户将导航到另一个应用程序的页面。同样,将加载另一个应用程序的dll,以便执行该页面后面的代码。

  3. 动态加载另一个应用程序的用户控件。在shell应用程序中,您可以拥有Page.LoadControl,然后将控件添加到shell应用程序的某个占位符中。将加载另一个应用程序的dll,以便在后面执行控件的代码。Page.LoadControl要求您为提供ASCX文件的URL。您可以将此URL放在web.config文件或数据库中,也可以在shell应用程序中加载不同的控件(也可以是不同应用程序的控件)。

  4. 使用反射可以动态地创建其他应用程序的类的对象。如果你这样做,你可能希望你的shell应用程序引入一个可以由其他web应用程序的类实现的接口,所以当你使用反射来创建这样一个类的实例时,你知道它实现了什么接口,并且可以执行它的方法。

前两个选项是最简单的,另外两个选项更高级,功能更强大。如果你提供更多关于你的用例的信息,也许我可以推荐最适合你的。