我现在一直在谷歌搜索,也许我不是在寻找正确的术语。我想拥有一个能够加载/运行其他Web应用程序的“shell”asp.net Web应用程序(就像prism对Silverlight xap文件一样)。但是,除了“子项目”之外,我似乎无法找到任何其他版本,这需要将项目添加到解决方案中。我只是想将WebApplicationB.dll放到Bin文件夹中,让ShellWebApplication加载dll并在iframe中显示默认页面。
如何做到这一点或在哪里可以找到有关如何做到这一点的信息?
更新:向能够展示代码或指向示范项目的人提供奖励,以展示如何完成此操作。希望能够“加载”另一个asp.net网站/ Web应用程序及其依赖项(dll或no)并显示加载的asp.net Web应用程序的default.aspx起始页面,而不更改已包含shell的Visual Studio解决方案asp.net web应用程序。
答案 0 :(得分:3)
这实际上是相当微不足道的;我们这样做。
主要关键是您的“模块”应该有自己的内容文件夹,或者您需要注意不要在同一位置使用完全相同的文件名。
考虑以下设想的例子:
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个程序集项目。 Web应用程序项目彼此之间一无所知。
下一步是告诉Shell,Module1存在。我们通过提供可用模块的数据库表来实现这一点。您可以在web.config文件中执行相同的操作。主要的是shell项目需要Type Name并引用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”的Master页面。我们的每个模块的根目录中都有一个“Main.master”母版页。模块中的构建操作设置为none,复制到输出设置为Do not copy。
母版页是我们实际加载菜单选项的地方。此外,每个模块中的所有其他主服务器都继承自此主模块。有趣的是,后代母版页并不关心父母的实际“类型”,只关心该页面的位置。这意味着您可以从shell控制主母版页,并让每个模块“继承”,只需通过NOT部署其整体母版页。
例如:
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(不需要虚拟目录),它就可以正常工作。
答案 1 :(得分:2)
dll包含Web应用程序的已编译代码。 “加载dll”没有意义。您可能想要加载控件或页面,然后让用户导航到此应用程序中的其他页面或控件,其代码也包含在此dll中。 所以有几种选择:
使用iframe并指向它以加载其他Web应用程序的页面。这将加载该应用程序的DLL以执行该页面后面的代码。您可以让用户从该页面导航到应用程序的其他页面。
在shell应用程序中放置一个链接,单击该链接后会将用户导航到另一个应用程序的页面。同样,将加载另一个应用程序的DLL以执行该页面后面的代码。
动态加载其他应用程序的用户控件。在shell应用程序中,您可以使用Page.LoadControl,然后将控件添加到shell应用程序中的某个占位符。将加载另一个应用程序的DLL以执行后面的控件代码。 Page.LoadControl要求您提供ASCX文件的URL。您可以将此URL放在web.config文件或数据库中,并可以在shell应用程序中加载不同的控件(也可以是不同应用程序的控件)。
使用反射动态创建其他应用程序的类对象。如果你这样做,你可能希望你的shell应用程序引入一个可以通过其他Web应用程序类实现的接口,所以当你使用反射来创建这样一个类的实例时,你知道它实现了什么接口,并且可以执行其方法。
两个第一选项是最简单的,另外两个选项更先进,功能更强大。如果您提供有关您的用例的更多信息,也许我可以推荐最适合的用途。