【问题标题】:ASP.NET MVC3 – Areas in Separate AssembliesASP.NET MVC3 – 单独程序集中的区域
【发布时间】:2011-07-19 22:41:20
【问题描述】:

我正在尝试使用区域设置 MVC3 解决方案,但我希望我的区域位于不同的程序集中。例如,我想要一个包含共享资源(如母版页、样式表、脚本、登录页面等)的父程序集。但我希望在单独的程序集中具有不同的业务功能区域。

我尝试了这个为 MVC2 预览编写的示例:http://msdn.microsoft.com/en-us/library/ee307987%28VS.100%29.aspx。 (注意,我最初是从这个 Stack Overflow 线程中找到的:ASP.NET MVC - separating large app)。但似乎 MVC3 没有将视图文件移动到主项目中的选项。我并不热衷于使用嵌入式资源/V​​irtualPathProvider 选项。

关于如何使用 MVC3 进行这项工作的任何建议?

谢谢, 跳过

【问题讨论】:

标签: asp.net-mvc-3 asp.net-mvc-areas


【解决方案1】:

1 - 将 Mvc 区域分成不同的 Mvc 项目,以编译成它们自己的单独程序集

2 - 将此添加到您的 AssemblyInfo.cs 类中,以便在加载应用程序时调用方法

[assembly: PreApplicationStartMethod(typeof(PluginAreaBootstrapper), "Init")]

3 - 这是加载期间调用 Init 方法时的样子

public class PluginAreaBootstrapper
{
    public static readonly List<Assembly> PluginAssemblies = new List<Assembly>();

    public static List<string> PluginNames()
    {
        return PluginAssemblies.Select(
            pluginAssembly => pluginAssembly.GetName().Name)
            .ToList();
    }

    public static void Init()
    {
        var fullPluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Areas");

        foreach (var file in Directory.EnumerateFiles(fullPluginPath, "*Plugin*.dll"))
            PluginAssemblies.Add(Assembly.LoadFile(file));

        PluginAssemblies.ForEach(BuildManager.AddReferencedAssembly);
    }
}

4 - 添加自定义 RazorViewEngine

public class PluginRazorViewEngine : RazorViewEngine
{
    public PluginRazorViewEngine()
    {
        AreaMasterLocationFormats = new[]
        {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
        };

        AreaPartialViewLocationFormats = new[]
        {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
        };

        var areaViewAndPartialViewLocationFormats = new List<string>
        {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/{1}/{0}.vbhtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.vbhtml"
        };

        var partialViewLocationFormats = new List<string>
        {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
        };

        var masterLocationFormats = new List<string>
        {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/{1}/{0}.vbhtml",
            "~/Views/Shared/{0}.cshtml",
            "~/Views/Shared/{0}.vbhtml"
        };

        foreach (var plugin in PluginAreaBootstrapper.PluginNames())
        {
            masterLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.cshtml");
            masterLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.vbhtml");
            masterLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/Shared/{1}/{0}.cshtml");
            masterLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/Shared/{1}/{0}.vbhtml");

            partialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.cshtml");
            partialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.vbhtml");
            partialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/Shared/{0}.cshtml");
            partialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/Shared/{0}.vbhtml");

            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.cshtml");
            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Views/{1}/{0}.vbhtml");
            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Areas/{2}/Views/{1}/{0}.cshtml");
            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Areas/{2}/Views/{1}/{0}.vbhtml");
            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Areas/{2}/Views/Shared/{0}.cshtml");
            areaViewAndPartialViewLocationFormats.Add(
                "~/Areas/" + plugin + "/Areas/{2}/Views/Shared/{0}.vbhtml");
        }

        ViewLocationFormats = partialViewLocationFormats.ToArray();
        MasterLocationFormats = masterLocationFormats.ToArray();
        PartialViewLocationFormats = partialViewLocationFormats.ToArray();
        AreaPartialViewLocationFormats = areaViewAndPartialViewLocationFormats.ToArray();
        AreaViewLocationFormats = areaViewAndPartialViewLocationFormats.ToArray();
    }
}

5 - 从不同的 Mvc(区域)项目中注册您的区域

namespace MvcApplication8.Web.MyPlugin1
{
    public class MyPlugin1AreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get { return "MyPlugin1"; }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "MyPlugin1_default",
                "MyPlugin1/{controller}/{action}/{id}",
                new {action = "Index", id = UrlParameter.Optional}
                );
        }
    }
}

源代码和其他参考可以在这里找到:http://blog.longle.io/2012/03/29/building-a-composite-mvc3-application-with-pluggable-areas/

【讨论】:

  • 请告诉我这是否也适用于 aspx 页面
【解决方案2】:

您可以使用MvcContrib with Portable Areas,但这样您将拥有嵌入式视图。

只需创建一个 MVC 和一个类库项目。在 MVC 项目中创建您的区域,完成后将除视图之外的所有内容从该区域移动到类库中。

使用 NuGet 进行打包,瞧,您可以在每个 MVC 项目中使用新的 NuGet 区域。

【讨论】:

    【解决方案3】:

    您可以在不使用区域的情况下分离控制器和视图。对于控制器,您可以使用 Windsor 或任何其他 IoC 容器来解析来自不同程序集的控制器。 例如,您可以通过这种方式注册所有控制器:

    container.Register(AllTypes.FromAssemblyInDirectory(new AssemblyFilter(HttpRuntime.BinDirectory)).BasedOn<IController>().Configure(c => c.LifeStyle.Transient));
    

    您还必须实现 IDependencyResolver 然后设置 DependencyResolver.SetResolver(...)。

    对于视图,您有两种选择:

    1. 嵌入式资源和 VirtualPathProvider
    2. 在构建/部署后简单地将视图文件复制到适当的位置

    我们使用 Windsor 和 VirutalPathProvider 实现提供的嵌入式资源视图构建了一个简单的框架(类似于 Portable Areas)。

    【讨论】:

    • 抱歉,我不能分享该代码,因为它属于我以前的员工。顺便说一句,我可以告诉你,最终我们删除了嵌入式视图,但控制器仍保留在单独的程序集中。您对该解决方案的哪个特定部分感兴趣?
    • 嵌入式视图和 virtualPathProvider
    • 好的,在这里你可以找到嵌入式资源处理类:gist.github.com/speier/6037842
    【解决方案4】:

    请参阅this article,了解如何创建在另一个 MVC 应用程序中作为区域工作的项目。 基本上,区域项目中的文件位于主项目中的Area 文件夹下,但不包含在主项目中(未在项目文件中引用)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-06
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多