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?
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).
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
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