ASP.NET MVC 3 RC Aregistration.registreAllareas () и динамически загруженные сборки

StackOverflow https://stackoverflow.com/questions/4241399

Вопрос

В настоящее время я экспериментирую с динамически загруженными областями с ASP.NET MVC 3 RC. Я видел, как это написано во многих местах, что это не в том, какие области предназначены для, а (по крайней мере, до MVC 2) невозможно, скажем здесь Например.

Но все равно! Должно быть возможно получить его на работу, верно? Я создал решение, добавил проект MVC 3, добавил область и некоторый контент. Все работает хорошо. Теперь я создал новый проект библиотеки класса (в том же решении), добавил ссылку на него из MVC-проекта и начал перемещаться по части, связанным с областью в библиотеку. Изменена вывод-каталог библиотечного проекта в область-папку MVC-проекта и убедился, что представления и их Web.config скопированы в выходную папку.

Прочитав так много о том, как вы не могли иметь внешние области, было немного удивительно, что это сработало. Нет проблем вообще не очень! Проблема начинается при удалении ссылки между проектами и вместо этого загружаю библиотеку в коде. (Перед звонком AreaRegistration.RegisterAllAreas().) Теперь это не работает. Вообще.

Я немного покинул в источнике для MVC 3, и проблема, кажется, с BuildManager.GetReferencedAssemblies() который используется для получения собраний для поиска реализаций AreaRegistration.

Теперь я не на 100% уверен в этом, но кажется, что этот метод смотрит только на сборки, которые присутствовали / упоминались при компиляции времени, может кто-то подтвердить, если это на самом деле так?

Я отладил это, и этот метод-звонок действительно не находит сборку, которую я загрузил только до вызова к нему. Это может быть из-за чего-то другого, что я пропустил, наверное .. Есть идеи?

Это было полезно?

Решение

То, как вещи работают немного сложны.

GetReferencedAssemblies Включает в себя ссылочные сборки, не загруженные сборки. Это включает в себя:

  • Все собрания, на которые ссылаются в вас Web.config (например, System.Web.Mvc)
  • Все унаследовано от root web.config, который включает в себя такие вещи, как System, System.Web И другие, которые вам не нужно добавлять себя. (Вы можете взглянуть на список здесь: C:\Windows\Microsoft.Net\Framework\v4.0.30319\web.config).
    Это также содержит специальный * предмет, который:
  • включает в себя все на вашем сайте bin папка

Так что теперь возьмите свое приложение V1 (все в одном приложении). Все работает, потому что код приложения компилируется в папку Bin, которая автоматически включается. Кроме того, все виды видов и т. Д. Находятся в самом приложении, поэтому они доступны.

Теперь в приложении V2 (другой проект с ссылкой PROJ-PROJ а также Пользовательская задача сборки, которая копирует вид на правильное местоположение в вашем основном приложении), все еще работает, по умолчанию по умолчанию ProJ-ProJ ссылки означает, что двоичный бинарный библиотека класса скопирован в папку Bin App. Так что по вышеуказанным правилам код города все еще загружается правильно. Тот факт, что вы установили выходной путь библиотеки, чтобы быть некоторого местоположения в папке ваших основных приложений, на самом деле не имеет значения - вы просто в конечном итоге с двумя копиями двоичных.

Сейчас в приложении V3 (NO PROJ-PROJ Ref, Assistance Library Library загружена вручную) Ваша библиотека сборка загружается слишком поздно. К тому времени, когда ваш код запускается набор ссылок с монтажами уже заблокирован и больше не может быть изменен.

Есть способ запустить код и добавить элементы в список зарегистрированных собраний: вы можете сделать это, используя AddReferencedAssembly метод, который должен быть вызванным из PreApplicationStartMethodAttribute метод.

Конечно, вам все еще нужно иметь дело с тем, как вы управляете файлами вашего просмотра. То, как вы в настоящее время настроили его, в значительной степени так же, как имеющие представления в основном приложении (поскольку они эффективно копируются в правильное местоположение).

Другие советы

1 - отделяйте свои области MVC в разные проекты MVC, которые будут скомпилированы в свои собственные отдельные сборки

2 - Добавьте это к классу AssocusInfo.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}
                );
        }
    }
}

Sourcecode и дополнительные ссылки можно найти здесь:http://blog.longle.io/2012/03/29/building-a-composite-mvc3-Application-with-pluggable-areas.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top