7

我最近在使用 ASP.NET MVC3/4 时遇到了一种开发可插拔应用程序模块的方法,我喜欢这种方法的简单性。目前,我的应用程序结构如下:

在此处输入图像描述

因此,任何想要为我的应用程序开发扩展的人,都遵循上述教程中的方法并创建一个保留在Areas文件夹中的扩展。我认为当添加新的Areas(创建为新项目)时,.pdb会创建文件并将其放置在bin目录中。我的问题是这样的:

  • 如何分发Areas可插拔模块?
  • 如何更改以下代码,以便当有人将新内容Area放入bin文件夹时,应用程序会自动将其拾取并创建链接?插件作者应该怎么做才能启用它?

在我的_Layout.cshtml(全局共享布局)中,我执行以下操作来构建链接:

<ul>
      <li>@Html.ActionLink("Area1", "Index", "Area1", new { Area = "Area1" }, null)</li>
      <li>@Html.ActionLink("Area2", "Index", "Area2", new { Area = "Area2" }, null)</li>
      <li>@Html.ActionLink("Area3", "Index", "Area3", new { Area = "Area3" }, null)</li>
</ul>

为简单起见,假设区域名称是唯一的。关于如何做到这一点的任何建议?

4

5 回答 5

10

如何将区域分配为可插拔模块?

不要在托管 Web 应用程序中创建区域,而是创建单独的项目,编译为单独的 dll。将 dll 复制到您想要使用它的任何 Web 应用程序中。请记住将所有静态文件设置为“EmbeddedResource”。

如何更改以下代码,以便当有人将新区域放入 bin 文件夹时,应用程序会自动将其拾取并创建链接?插件作者应该怎么做才能启用它?

您可以使用 MvcContrib PortableAreaRegistration 的“总线”从便携式区域向“总线”上的任何人发送消息、命令。这可以是托管网络应用程序,或者理论上独立的区域可以相互发送消息。

在 github 上创建了两个粗略但实用的演示代码:

MVC3 版本:

https://github.com/AkosLukacs/PluggablePortableAreas

MVC4 RC 版本:

https://github.com/AkosLukacs/PluggablePortableAreasMVC4

首先,您定义一个可以携带您需要的信息的消息。只是一个具有一些属性的 POCO (PluggablePortableAreas.Common\RegisterAreaMessage.cs):

public class RegisterAreaMessage : IEventMessage
{
    public string LinkText { get; private set; }
    public string AreaName { get; private set; }
    public string ControllerName { get; private set; }
    public string ActionName { get; private set; }
    //...
}

为该消息类型创建一个处理程序 (PluggablePortableAreas.Common\RegisterAreaEventHandler.cs):

public class RegisterAreaEventHandler : MessageHandler<RegisterAreaMessage>{}

在这种情况下,MessageHandler 只是将接收到的消息添加到一个 staticConcurrentBag<RegisterAreaMessage>中。如果您愿意,可以使用 DI,但要保持简单。

您可以像这样从便携式区域发送消息(Areas\DemoArea1\Areas\Demo1\Demo1AreaRegistration.cs):

 //the portable area sends a message to the 'bus'
 bus.Send(new RegisterAreaMessage("Link to the Demo area", AreaName, DefaultController, DefaultAction));

通过迭代消息集合(PluggablePortableAreas.Web\Views\Shared_Layout.cshtml)来显示动态添加的链接:

                @foreach(var sor in PluggablePortableAreas.Common.RegisterAreaEventHandler.RegisteredAreas) {
                <li>@Html.ActionLink(sor.LinkText, sor.ActionName, sor.ControllerName, new{Area=sor.AreaName}, null)</li>
                }

还要注意一件事:使用“完全限定”的区域名称。如果您没有明确指定区域名称,MVC 会假定它是当前区域。没有区域没有问题,但第二个将指向"/path_to_your_app/CurrentArea/Home"而不是"/path_to_your_app/Home".

<li>@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)</li>
<li>@Html.ActionLink("I don't work from the portable area!", "Index", "Home")</li>

还要注意一件事!

VS中的开发服务器感觉有点“飘忽不定”,有时便携区不加载。在完整的 IIS 中可靠地工作...

于 2012-06-18T09:19:43.073 回答
2

你在做什么看起来很像MVCContrib的便携式区域。

他们使用消息/应用程序总线模式在 Web 元素上动态添加新的小部件。MessageHandlers 是通过反射发现的,每条消息都被传递给它们。因此,在您的情况下,插件作者应该只为标准消息实现一个处理程序(比如注册全局菜单链接)。

便携式区域的资源是嵌入的,因此可以将单个 dll 放入 bin 文件夹中。为了自动获取它并在您的应用程序中使用它,您必须通过FileSystemWatcher观看 bin 文件夹并重新启动您的应用程序(我认为没有其他方法可以将新的 .dll 加载到 asp.net 应用程序中的 AppDomain 中)。

您也可以使用 ASP.NET 4 中的 BuildManager 功能从其他文件夹加载 .dll。更多有用信息请参见此处

于 2012-06-18T09:41:46.013 回答
1

这看起来类似于 Orchard CMS 执行模块的方式。

看看他们的画廊......这些模块作为 Nuget 包分发,包含整个模块项目。

于 2012-06-15T16:15:34.160 回答
1

您好,您可以在nopcommerce项目中寻找相当不错的插件架构。

于 2012-06-18T09:28:41.810 回答
1

看看这个教程,我想它会对你有很大帮助。

于 2012-06-18T10:17:44.673 回答