Подтвердить что ты не робот

ASP.NET MVC3 - области в отдельных сборках

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

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

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

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

4b9b3361

Ответ 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 (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

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

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

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

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

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

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

Ответ 3

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

Просто создайте проект MVC и библиотеки классов. Создайте свою область в проекте MVC и после того, как вы закончили, переместите все объекты, кроме представлений из области, в библиотеку классов.

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

Ответ 4

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