ASP.NET MVC3 - области в отдельных сборках - PullRequest
19 голосов
/ 21 марта 2011

Я пытаюсь настроить решение MVC3, используя области, но я хочу, чтобы мои области были в разных сборках. Например, мне нужна родительская сборка, которая содержит общие ресурсы, такие как главные страницы, таблицы стилей, сценарии, страницы входа и т. Д. Но я хочу, чтобы в отдельных сборках были отдельные области бизнес-функций.

Я попробовал этот пример, который был написан для предварительного просмотра MVC2: http://msdn.microsoft.com/en-us/library/ee307987%28VS.100%29.aspx. (Обратите внимание, я первоначально нашел это из этого потока переполнения стека: ASP.NET MVC - отделение большого приложения ). Но, похоже, у MVC3 нет возможности перемещать файлы просмотра в основной проект. Я не в восторге от использования опции встроенного ресурса / VirtualPathProvider.

Любые предложения о том, как заставить это работать с MVC3?

Спасибо, Пропустить

Ответы [ 4 ]

13 голосов
/ 28 сентября 2012

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 (Area)

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/

2 голосов
/ 08 октября 2011

Вы можете использовать MvcContrib с переносными областями , но таким образом у вас будут встроенные представления.

Просто создайте MVC и проект библиотеки классов. Создайте свою область в проекте MVC и после завершения переместите все, кроме Views, из области в библиотеку классов.

Используйте NuGet, чтобы получить этот пакет, и вуаля, вы можете использовать новую область NuGet в каждом проекте MVC.

1 голос
/ 22 марта 2011

Вы можете разделить свои контроллеры и представления без использования областей. Для контроллеров вы можете использовать Windsor или любой другой контейнер IoC для разрешения контроллеров из разных сборок. Например, вы можете зарегистрировать все свои контроллеры следующим образом:

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

Также необходимо реализовать IDependencyResolver, затем установить DependencyResolver.SetResolver (...).

Для просмотра у вас есть два варианта:

  1. Встроенные ресурсы и VirtualPathProvider
  2. Простое копирование файлов представления в соответствующее место после сборки / развертывания

Мы создали простую структуру (похожую на Portable Areas) с использованием Windsor и встроенных представлений ресурсов, предоставляемых реализацией VirutalPathProvider.

0 голосов
/ 04 марта 2013

См. в этой статье , чтобы узнать, как создать проект, который работает как Area в другом приложении MVC.По сути, файлы в проекте области находятся в папке Area в основном проекте, но не включены как часть основного проекта (не указаны в файле проекта).

...