2010-11-22 4 views
13

मैं वर्तमान में एएसपी.नेट एमवीसी 3 आरसी के साथ गतिशील रूप से लोड किए गए क्षेत्रों के साथ प्रयोग कर रहा हूं। मैंने इसे कई स्थानों पर लिखा है कि यह नहीं है कि इस क्षेत्र के लिए क्या उद्देश्य है, और (कम से कम प्री-एमवीसी 2) संभव नहीं है, उदाहरण के लिए here कहें।एएसपी.नेट एमवीसी 3 आरसी क्षेत्र पंजीकरण। रजिस्ट्रारअलएरिया() और गतिशील रूप से लोड असेंबली

लेकिन फिर भी! इसे काम करने के लिए यह संभव होना चाहिए, है ना? मैंने एक समाधान बनाया है, एक एमवीसी 3 परियोजना जोड़ा, एक क्षेत्र और कुछ सामग्री जोड़ा। सब ठीक काम कर रहे हैं। अब मैंने एक नई कक्षा लाइब्रेरी प्रोजेक्ट (उसी समाधान में) बनाया है, एमवीसी-प्रोजेक्ट से इसका एक संदर्भ जोड़ा है, और क्षेत्र से संबंधित भागों को लाइब्रेरी में ले जाना शुरू कर दिया है। पुस्तकालय प्रोजेक्ट की आउटपुट-निर्देशिका को एमवीसी-प्रोजेक्ट के क्षेत्र-फ़ोल्डर में बदल दिया, और सुनिश्चित किया कि दृश्य और उनके web.config को आउटपुट-फ़ोल्डर में कॉपी किया गया है।

इस बारे में बहुत कुछ पढ़ने के बाद कि आप बाहरी क्षेत्रों में कैसे नहीं हो सकते थे, यह आश्चर्यजनक था कि यह काम करता था। वास्तव में कोई समस्या नहीं है! समस्या तब शुरू होती है जब मैं प्रोजेक्ट्स के बीच संदर्भ हटा देता हूं, और इसके बजाय लाइब्रेरी को कोड में लोड करता हूं। (AreaRegistration.RegisterAllAreas() पर कॉल करने से पहले।) अब यह काम नहीं करता है। बिलकुल।

मैं एमवीसी 3 के स्रोत में थोड़ा सा पोकिंग कर रहा हूं, और समस्या BuildManager.GetReferencedAssemblies() के साथ प्रतीत होती है जिसका उपयोग AreaRegistration के कार्यान्वयन को देखने के लिए असेंबली प्राप्त करने के लिए किया जाता है।

अब, मुझे इस बारे में 100% निश्चित नहीं है, लेकिन ऐसा लगता है कि यह विधि केवल उन असेंबली को देखती है जो संकलित समय पर मौजूद/संदर्भित थे, क्या कोई यह पुष्टि कर सकता है कि यह वास्तव में ऐसा है या नहीं?

मैंने इस के माध्यम से डीबग किया है, और उस विधि-कॉल को वास्तव में कॉल करने से पहले लोड की गई असेंबली नहीं मिलती है। यह किसी और चीज के कारण हो सकता है जिसे मैंने शायद याद किया है .. कोई विचार?

उत्तर

20

चीजें काम करने का तरीका थोड़ा जटिल है।

GetReferencedAssemblies में संदर्भित असेंबली शामिल हैं, असेंबली लोड नहीं हैं। इसमें शामिल हैं:

  • सभी विधानसभाओं आप आवेदन के web.config में संदर्भित (जैसे System.Web.Mvc के रूप में)
  • सब कुछ जड़ web.config, जो System, System.Web तरह बातें और दूसरों को आप जोड़ना नहीं है शामिल है से विरासत में मिली स्वयं। (आप यहां सूची को देख सकते हैं: C:\Windows\Microsoft.Net\Framework\v4.0.30319\web.config)।
  • आपकी साइट की bin फ़ोल्डर में सब कुछ शामिल है

तो अब अपने अनुप्रयोग v1 (एक ही ऐप्लिकेशन में सब कुछ) ले:
यह भी एक विशेष * आइटम, जो शामिल हैं। सबकुछ काम करता है क्योंकि एप्लिकेशन कोड बिन फ़ोल्डर में संकलित हो जाता है जो स्वचालित रूप से शामिल हो जाता है। इसके अलावा, क्षेत्र के सभी दृश्य आदि एप्लिकेशन में ही हैं, इसलिए वे पहुंच योग्य हैं।

अब एप्लिकेशन वी 2 में

सब कुछ अभी भी काम करता है, क्योंकि डिफ़ॉल्ट एक proj करने से (एक proj करने वाली proj संदर्भ और एक कस्टम निर्माण कार्य है कि अपने मुख्य अनुप्रयोग में प्रतियां सही स्थान पर विचारों के साथ अलग-अलग परियोजना) -प्रोजे संदर्भ का अर्थ है कि कक्षा पुस्तकालय बाइनरी आपके ऐप के बिन फ़ोल्डर में कॉपी हो जाती है। तो उपरोक्त नियमों से, क्षेत्र कोड अभी भी सही ढंग से लोड हो जाता है। तथ्य यह है कि आपने लाइब्रेरी के आउटपुट पथ को अपने मुख्य ऐप के एरिया फ़ोल्डर में कुछ स्थान होने के लिए सेट किया है, वास्तव में कोई फर्क नहीं पड़ता - आप बस बाइनरी की दो प्रतियों के साथ समाप्त होते हैं।

अब एप्लिकेशन v3 (कोई proj-proj रेफरी, क्षेत्र पुस्तकालय विधानसभा मैन्युअल लोड) अपने पुस्तकालय विधानसभा बहुत देर हो चुकी लोड हो जाता है में

। जब तक आपका कोड संदर्भित असेंबली के सेट को चलाता है तब तक पहले ही लॉक कर दिया गया है और अब बदला नहीं जा सकता है।

कोड चलाने के लिए और पंजीकृत विधानसभाओं की सूची में आइटम जोड़ने के लिए एक तरीका होता है: यदि आप AddReferencedAssembly तरीका है जिसके एक PreApplicationStartMethodAttribute method से लागू किया जाना चाहिए का उपयोग कर ऐसा कर सकते हैं।

बेशक

आप अभी भी कैसे आप अपने दृश्य फाइलों का प्रबंधन के साथ सौदा है। जिस तरह से आप वर्तमान में यह सेट अप है काफी मुख्य आवेदन में दृश्य (वे प्रभावी रूप से सही स्थान में कॉपी हो के बाद से) जैसा ही होता है।

+0

बिल्कुल सही जवाब है, धन्यवाद एक मील! हां, मुझे पता है कि फिलहाल यह मूल रूप से एक प्रोजेक्ट होने जैसा ही है, लेकिन मैं उन्हें धीरे-धीरे अलग करना चाहता था और देख रहा था कि मैं एक बार में सभी समस्याओं के बजाय समस्याओं को कहां मारता हूं :) मैं हूं असेंबली में संसाधनों के रूप में विचारों में संकलित होने पर विचार करना और अपना स्वयं का वर्चुअल पथ/फ़ाइल कार्यान्वयन करना, जब तक कि यह एक प्रदर्शन समस्या का अधिक न हो .. जैसा कि मैंने कहा, बस यह देखने के लिए कि क्या संभव है और क्या नहीं है ! फिर से धन्यवाद! – Robin

+0

आप एम्बेड किए गए संसाधन के रूप में अपने क्षेत्र विधानसभा में सभी दृश्यों अंकन को देखो और एक आभासी पथ प्रदाता को लागू करने को देखने के लिए पसंद कर सकते हैं। ड्रैगन ड्रॉप क्षेत्र असेंबली को प्राप्त करने के लिए मैंने यही किया है कि मैं मुख्य साइट की बिन निर्देशिका में बस रख सकता हूं। –

+0

@Joshua हेस - तुम मुझे अपना प्लगेबल क्षेत्रों समाधान भेज सकते हैं? –

6

1 - अलग आप Mvc differrent 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 (क्षेत्र) से अपने क्षेत्रों रजिस्टर परियोजनाएं

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

+0

हू, उस पर देखो, बहुत अच्छा! मुझे कुछ बिंदु पर कोशिश करने जा रहा है, धन्यवाद! – Robin

+0

रॉबिन अंक की सराहना करते हैं! – LeLong37

+0

दिन के लिए ऐसा कुछ ढूंढ रहे थे, धन्यवाद! – rossipedia

संबंधित मुद्दे