24

Asp.net MVC में यूआरएल संरचना की तरहएएसपी.नेट एमवीसी में गतिशील नियंत्रक और क्रिया विधि कैसे प्राप्त करें?

http://example.com/ {नियंत्रक}/{कार्रवाई}/{आईडी}

प्रत्येक "नियंत्रक" के लिए, मान http://example.com/blog चला जाता है, वहाँ एक BlogController है।

लेकिन यूआरएल का मेरा {नियंत्रक} भाग पूर्व-हाथ का फैसला नहीं किया गया है, लेकिन यह गतिशील रूप से रन टाइम पर निर्धारित किया जाता है, मैं एक "गतिशील नियंत्रक" कैसे बना सकता हूं जो कि उसी नियंत्रक को कुछ भी नक्शा बनाता है जो उसके बाद मूल्य और निर्धारित करता है कि क्या करना है?

{action} के साथ वही बात, यदि मेरे यूआरएल का {action} भाग भी गतिशील है, तो क्या इस परिदृश्य को प्रोग्राम करने का कोई तरीका है?

उत्तर

23

बिल्कुल! कस्टम नियंत्रक खोजने के लिए आपको DefaultControllerFactory को ओवरराइड करने की आवश्यकता होगी यदि कोई अस्तित्व में नहीं है। फिर आपको डायनामिक एक्शन नामों को संभालने के लिए IActionInvoker लिखना होगा।

आपका नियंत्रक कारखाने की तरह दिखेगा:

public class DynamicControllerFactory : DefaultControllerFactory 
{ 
    private readonly IServiceLocator _Locator; 

    public DynamicControllerFactory(IServiceLocator locator) 
    { 
     _Locator = locator; 
    } 

    protected override Type GetControllerType(string controllerName) 
    { 
     var controllerType = base.GetControllerType(controllerName); 
      // if a controller wasn't found with a matching name, return our dynamic controller 
     return controllerType ?? typeof (DynamicController); 
    } 

    protected override IController GetControllerInstance(Type controllerType) 
    { 
     var controller = base.GetControllerInstance(controllerType) as Controller; 

     var actionInvoker = _Locator.GetInstance<IActionInvoker>(); 
     if (actionInvoker != null) 
     { 
      controller.ActionInvoker = actionInvoker; 
     } 

     return controller; 
    } 
} 

फिर अपने कार्रवाई invoker होगा जैसे:

public class DynamicActionInvoker : ControllerActionInvoker 
{ 
    private readonly IServiceLocator _Locator; 

    public DynamicActionInvoker(IServiceLocator locator) 
    { 
     _Locator = locator; 
    } 

    protected override ActionDescriptor FindAction(ControllerContext controllerContext, 
                ControllerDescriptor controllerDescriptor, string actionName) 
    { 
      // try to match an existing action name first 
     var action = base.FindAction(controllerContext, controllerDescriptor, actionName); 
     if (action != null) 
     { 
      return action; 
     } 

// @ray247 The remainder of this you'd probably write on your own... 
     var actionFinders = _Locator.GetAllInstances<IFindAction>(); 
     if (actionFinders == null) 
     { 
      return null; 
     } 

     return actionFinders 
      .Select(f => f.FindAction(controllerContext, controllerDescriptor, actionName)) 
      .Where(d => d != null) 
      .FirstOrDefault(); 
    } 
} 

आप इस कोड here का एक बहुत अधिक देख सकते हैं। यह मेरे द्वारा और एक सहकर्मी द्वारा पूरी तरह से गतिशील एमवीसी पाइपलाइन लिखने का एक पुराना पहला मसौदा प्रयास है। आप इसे संदर्भ के रूप में उपयोग करने के लिए स्वतंत्र हैं और आप जो चाहते हैं उसकी प्रतिलिपि बनाएँ।

संपादित

मैं लगा कि मैं क्या है कि कोड करता है के बारे में कुछ पृष्ठभूमि शामिल होना चाहिए। हम एक डोमेन मॉडल के चारों ओर एमवीसी परत गतिशील रूप से बनाने की कोशिश कर रहे थे। इसलिए यदि आपके डोमेन में उत्पाद वर्ग शामिल है, तो आप सभी उत्पादों की सूची देखने के लिए products\alls पर नेविगेट कर सकते हैं। यदि आप कोई उत्पाद जोड़ना चाहते हैं, तो आप product\add पर नेविगेट करेंगे। उत्पाद को संपादित करने के लिए आप product\edit\1 पर जा सकते हैं। हमने चीजों को भी कोशिश की जैसे कि आप किसी इकाई पर गुणों को संपादित करने की अनुमति देते हैं। तो product\editprice\1?value=42 उत्पाद # 1 से 42 की कीमत संपत्ति निर्धारित करेगा। (मेरे पथ थोड़ा दूर हो सकते हैं, मैं अब सटीक वाक्यविन्यास को याद नहीं कर सकता।) उम्मीद है कि इससे मदद मिलती है!

+0

हैलो @Ryan होगा। मैंने https://github.com/ryanohs/DynamicServices से अपने डायनेमिक कंट्रोलर फैक्टरी और डायनामिकएक्शन इनवॉकर को कार्यान्वित करने का प्रयास किया है। रनटाइम के दौरान मुझे डायनामिक कंट्रोलर फैक्टरी 1 के डिफॉल्ट कन्स्ट्रक्टर के लिए पूछा गया था। फिर मैंने खाली कार्यान्वयन के साथ एक जोड़ा। लेकिन पैरामीटर कन्स्ट्रक्टर कभी नहीं बुलाया जाता है और _locater मान कभी सेट नहीं होता है। तो GetControllerInstance actionInvoker को आमंत्रित करने के दौरान शून्य _locator के कारण सेट नहीं है। मैंने गलत कहां किया है।मुझे _locator के लिए डिफ़ॉल्ट मान देना होगा, या इसे रनटाइम के दौरान कहीं और सेट किया गया है – mesimplybj

+1

कोई भी परिदृश्य विस्तृत कर सकता है जब गतिशील नियंत्रक और गतिशील कार्रवाई आवेदक की आवश्यकता होगी? – Thomas

1

आपको अपना खुद का IControllerFactory लिखना होगा (या शायद DefaultControllerFactory से प्राप्त करें) और उसके बाद इसे ControllerBuilder पर पंजीकृत करें।

7

थोड़ा और प्रतिबिंब के बाद, आपके अन्य उत्तर की तुलना में गतिशील क्रिया नामों को संभालने के लिए थोड़ा आसान तरीका हो सकता है। आपको अभी भी डिफ़ॉल्ट नियंत्रक फैक्ट्री को ओवरराइड करने की आवश्यकता होगी। मुझे लगता है कि आप की तरह अपने मार्ग निर्धारित कर सकते हैं:

routes.MapRoute("Dynamic", "{controller}/{command}/{id}", new { action = "ProcessCommand" }); 
फिर अपने डिफ़ॉल्ट/गतिशील नियंत्रक पर

आप

public ActionResult ProcessCommand(string command, int id) 
{ 
    switch(command) 
    { 
     // whatever. 
    } 
} 
+0

गतिशील नियंत्रक के बारे में कैसे? –

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