ASP.NET MVC 3 RC AreaRegistration.RegisterAllAreas() i dynamicznie ładowane zespoły

Obecnie eksperymentuję z dynamicznie ładowanymi obszarami z ASP.NET MVC 3 RC. Widziałem to napisane w wielu miejscach, że to nie jest to, co obszary są przeznaczone, i (przynajmniej pre-MVC 2) nie jest możliwe, powiedzmy tutaj na przykład.

Ale i tak! Powinno być możliwe, aby to zadziałało, prawda? Stworzyłem rozwiązanie, dodałem projekt MVC 3, dodałem obszar i trochę treści. Wszystko działa dobrze. Teraz stworzyłem nowy projekt biblioteki klas( w tym samym rozwiązaniu), dodałem referencję do niego z projektu MVC i zaczął przenosić części związane z obszarem do biblioteki. Zmieniono output-directory projektu biblioteki na Area-folder projektu MVC i upewniono się, że widoki i ich www.config są kopiowane do folderu wyjściowego.

Po przeczytaniu tyle o tym, jak nie można mieć zewnętrznych obszarów, to było trochę zaskakujące, że to działa. Żaden problem naprawdę! Problem zaczyna się, gdy usuwam odniesienie między projektami, a zamiast tego Ładuję Biblioteka w kodzie. (Przed wywołaniem AreaRegistration.RegisterAllAreas(). Teraz to nie działa. W ogóle.

Grzebałem trochę w źródle MVC 3 i problem wydaje się być z BuildManager.GetReferencedAssemblies() który jest używany, aby zespoły szukały implementacji AreaRegistration.

Teraz, nie jestem 100% pewien tego, ale wydaje się, że ta metoda patrzy tylko na zespoły, które były obecne / odwołuje się w czasie kompilacji, czy ktoś może potwierdzić, czy tak jest w rzeczywistości?

Debugowałem to i ta metoda-call rzeczywiście nie znajduje zestawu, który załadowałem tuż przed wywołaniem do niego. Może dlatego, że przegapiłem coś innego.. Jakieś pomysły?

Author: marcind, 2010-11-22

2 answers

Sposób działania jest nieco skomplikowany.

GetReferencedAssemblies zawiera zespoły odwołane, a nie załadowane. Dotyczy to:

  • wszystkie zespoły odwołujące się w sieci aplikacji.config (np. System.Web.Mvc)
  • Wszystko odziedziczone po sieci korzeniowej.config, który zawiera takie rzeczy jak System, System.Web i inni, że nie trzeba dodawać siebie. (Możesz spojrzeć na listę tutaj: C:\Windows\Microsoft.Net\Framework\v4.0.30319\web.config).
    zawiera również specjalny * element, który :
  • zawiera wszystko w folderze bin Twojej witryny

Więc teraz weź swoją aplikację v1 (wszystko w jednej aplikacji). Wszystko działa, ponieważ kod aplikacji zostanie skompilowany do folderu bin, który zostanie automatycznie dołączony. Ponadto wszystkie widoki obszaru itp. znajdują się w samej aplikacji, więc są dostępne.

Teraz w app v2 (inny projekt z referencją proj-to-proj i niestandardowe zadanie budowania, które kopiuje widoki po prawej stronie lokalizacja w głównej aplikacji) wszystko nadal działa, ponieważ domyślnie referencje proj-to-proj oznaczają, że binarna Biblioteka klas zostanie skopiowana do folderu bin Twojej aplikacji. Tak więc, zgodnie z powyższymi zasadami, Numer Kierunkowy nadal jest ładowany poprawnie. Fakt, że ustawiłeś ścieżkę wyjściową biblioteki jako lokalizację w folderze obszary głównej aplikacji, nie robi różnicy - po prostu otrzymujesz dwie kopie binarne.

Teraz w app v3 (no proj-proj ref, area library assembly załadowane ręcznie) zespół biblioteki zostanie załadowany zbyt późno. Do czasu uruchomienia kodu zestaw odwołanych złożeń został już zablokowany i nie można go już zmienić.

Istnieje sposób na uruchamianie kodu i dodawanie elementów do listy zarejestrowanych zestawów: można to zrobić za pomocą AddReferencedAssembly metoda, która musi być wywołana z PreApplicationStartMethodAttribute metoda .

Oczywiście nadal musisz radzić sobie ze sposobem zarządzania plikami widoku. Sposób, w jaki aktualnie go masz ustawiony up jest prawie taki sam jak posiadanie widoków w głównej aplikacji (ponieważ są one skutecznie kopiowane we właściwe miejsce).

 20
Author: marcind,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-22 07:49:47

1-rozdzielenie obszarów Mvc na różne projekty Mvc, które mają być skompilowane w ich własne zespoły

2-dodaj to do AssemblyInfo.Klasa cs, do wywołania metody po załadowaniu aplikacji

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

3 - Oto jak wygląda metoda Init, gdy jest wywoływana podczas ładowania

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-Dodaj niestandardową maszynkę 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-Zarejestruj swoje obszary z różnych projektów Mvc (obszar)

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}
                );
        }
    }
}

Kod źródłowy i dodatkowe odniesienia można znaleźć here:http://blog.longle.io/2012/03/29/building-a-composite-mvc3-application-with-pluggable-areas

 6
Author: LeLong37,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-21 08:21:54