c# क्या आप एएसपी.नेट एमवीसी में नियंत्रक विधियों को अधिभारित कर सकते हैं?




asp.net-mvc overloading (13)

मैं यह देखने के लिए उत्सुक हूं कि आप ASP.NET MVC में नियंत्रक विधियों को अधिभारित कर सकते हैं या नहीं। जब भी मैं कोशिश करता हूं, मुझे नीचे त्रुटि मिलती है। दो विधियां अलग-अलग तर्क स्वीकार करती हैं। क्या यह ऐसा कुछ नहीं किया जा सकता है?

नियंत्रक प्रकार 'MyController' पर कार्रवाई 'MyMethod' के लिए वर्तमान अनुरोध निम्न क्रिया विधियों के बीच संदिग्ध है:


मुझे यह जवाब किसी अन्य धागे में पोस्ट करना पसंद है

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

एएसपी.नेट एमवीसी - अलग-अलग पैरामीटर के साथ एक कार्रवाई ओवरराइड करना


जहां तक ​​मुझे पता है कि विभिन्न http विधियों का उपयोग करते समय आपके पास केवल एक ही विधि हो सकती है।

अर्थात

[AcceptVerbs("GET")]
public ActionResult MyAction()
{

}

[AcceptVerbs("POST")]
public ActionResult MyAction(FormResult fm)
{

}

यदि यह कई विचारों के लिए एक जीईटी कार्रवाई का उपयोग करने का प्रयास है जो विभिन्न मॉडलों के साथ कई कार्रवाइयों पर पोस्ट करता है, तो प्रत्येक POST कार्रवाई के लिए एक GET कार्रवाई जोड़ें जो रीफ्रेश पर 404 को रोकने के लिए पहले GET पर रीडायरेक्ट करता है।

लंबे शॉट लेकिन आम परिदृश्य।


प्रत्येक नियंत्रक विधि के लिए केवल एक सार्वजनिक हस्ताक्षर की अनुमति है। यदि आप इसे अधिभारित करने का प्रयास करते हैं, तो यह संकलित होगा, लेकिन आपको अनुभव की गई रन-टाइम त्रुटि मिल रही है।

यदि आप ओवरलोडेड विधियों (जो काम करेंगे) को अलग करने के लिए अलग-अलग क्रियाओं (जैसे [HttpGet] और [HttpGet] विशेषताओं) का उपयोग करने के इच्छुक नहीं हैं, या रूटिंग को बदलते हैं, तो क्या शेष है कि आप या तो एक और विधि प्रदान कर सकते हैं अलग नाम, या आप मौजूदा विधि के अंदर प्रेषण कर सकते हैं। यहां बताया गया है कि मैंने यह कैसे किया:

मैं एक बार ऐसी परिस्थिति में आया जहां मुझे पीछे की संगतता बनाए रखना पड़ा। मूल विधि को दो पैरामीटर की उम्मीद थी, लेकिन नए में केवल एक ही था। जिस तरह से मैंने उम्मीद की थी वह ओवरलोडिंग काम नहीं कर सका क्योंकि एमवीसी को एंट्री पॉइंट नहीं मिला था।

इसे हल करने के लिए, मैंने निम्नलिखित किया:

  1. सार्वजनिक रूप से निजी से 2 अधिभारित क्रिया विधियों को बदल दिया
  2. एक नई सार्वजनिक विधि बनाई गई जिसमें "बस" 2 स्ट्रिंग पैरामीटर शामिल थे। वह एक प्रेषक के रूप में कार्य करता है, यानी:

    public ActionResult DoSomething(string param1, string param2)
    {
        if (string.IsNullOrEmpty(param2))
        {
            return DoSomething(ProductName: param1);
        }
        else
        {
            int oldId = int.Parse(param1);
            return DoSomething(OldParam: param1, OldId: oldId);
        }
    }
    
    
    private ActionResult DoSomething(string OldParam, int OldId)
    {
        // some code here
        return Json(result);
    }
    
    
    private ActionResult DoSomething(string ProductName)
    {
        // some code here
        return Json(result);
    }
    

बेशक, यह एक हैक है और बाद में refactored किया जाना चाहिए। लेकिन समय के लिए, यह मेरे लिए काम किया।

आप एक प्रेषक भी बना सकते हैं जैसे:

public ActionResult DoSomething(string action, string param1, string param2)
{
    switch (action)
    {
        case "update":
            return UpdateAction(param1, param2);
        case "remove":
            return DeleteAction(param1);
    }
}

आप देख सकते हैं कि अपडेटएक्शन को 2 पैरामीटर की आवश्यकता है, जबकि DeleteAction को केवल एक की आवश्यकता है।


Post और Get दोनों से निपटने के लिए आप एक एकल ActionResult का उपयोग कर सकते हैं:

public ActionResult Example() {
   if (Request.HttpMethod.ToUpperInvariant() == "GET") {
    // GET
   }
   else if (Request.HttpMethod.ToUpperInvariant() == "POST") {
     // Post  
   }
}

उपयोगी अगर आपके Get और Post विधियों के मिलान हस्ताक्षर हैं।


यहां कुछ और है जो आप कर सकते हैं ... आप एक विधि चाहते हैं जो पैरामीटर प्राप्त करने में सक्षम है और नहीं।

कोशिश क्यों नहीं करें ...

public ActionResult Show( string username = null )
{
   ...
}

यह मेरे लिए काम किया है ... और इस विधि में, आप वास्तव में यह देखने के लिए परीक्षण कर सकते हैं कि आपके पास आने वाले पैरामीटर हैं या नहीं।

स्ट्रिंग पर अमान्य नालीबल वाक्यविन्यास को हटाने के लिए अद्यतन किया गया है और एक डिफ़ॉल्ट पैरामीटर मान का उपयोग करें।


मैंने इसे एमवीसी 5 में विशेषता रूटिंग की मदद से हासिल किया है। माना जाता है कि मैं वेबफॉर्म का उपयोग कर एक दशक के वेब विकास से एमवीसी के लिए नया हूं, लेकिन निम्नलिखित ने मेरे लिए काम किया है। स्वीकार्य उत्तर के विपरीत यह सभी ओवरलोड किए गए कार्यों को एक ही दृश्य फ़ाइल द्वारा प्रस्तुत किया जा सकता है।

पहले App_Start / RouteConfig.cs में विशेषता रूटिंग सक्षम करें।

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );            
    }
}

वैकल्पिक रूप से एक डिफ़ॉल्ट मार्ग उपसर्ग के साथ अपने नियंत्रक वर्ग को सजाने के लिए।

[RoutePrefix("Returns")]
public class ReturnsController : BaseController
{
    //.......

फिर अपने नियंत्रक कार्यों को सजाने के लिए जो एक दूसरे को एक सामान्य मार्ग और पैरामीटर के साथ ओवरलोड करते हैं। प्रकार बाध्य पैरामीटर का उपयोग करके आप विभिन्न प्रकार के आईडी के साथ एक ही यूआरआई प्रारूप का उपयोग कर सकते हैं।

[HttpGet]
// Returns
public ActionResult Index()
{
    //.....
}

[HttpGet]
[Route("View")]
// Returns/View
public ActionResult View()
{
    // I wouldn't really do this but it proves the concept.
    int id = 7026;
    return View(id);
}

[HttpGet]
[Route("View/{id:int}")]
// Returns/View/7003
public ActionResult View(int id)
{
    //.....
}

[HttpGet]
[Route("View/{id:Guid}")]
// Returns/View/99300046-0ba4-47db-81bf-ba6e3ac3cf01
public ActionResult View(Guid id)
{
    //.....
}

उम्मीद है कि यह मदद करता है और किसी को गलत रास्ते से नीचे नहीं ले जा रहा है। :-)


यदि आप अपना कोड ओवरलोडिंग करना चाहते हैं तो आप विशेषता का उपयोग कर सकते हैं।

[ActionName("MyOverloadedName")]

लेकिन, आपको उसी http विधि के लिए एक अलग कार्य नाम का उपयोग करना होगा (जैसा कि अन्य ने कहा है)। तो यह उस बिंदु पर सिर्फ अर्थशास्त्र है। क्या आपके पास आपके कोड या आपकी विशेषता का नाम होगा?

फिल के पास इस लेख से संबंधित एक लेख है: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx


इस समस्या को दूर करने के लिए आप एक ActionMethodSelectorAttribute लिख सकते हैं जो प्रत्येक क्रिया के लिए MethodInfo जांच करता है और इसे पोस्ट फॉर्म मानों से तुलना करता है और उसके बाद किसी भी विधि को अस्वीकार करता है जिसके लिए फ़ॉर्म मान मेल नहीं खाते हैं (बेशक बटन नाम को छोड़कर)।

यहां एक उदाहरण दिया गया है: - http://blog.abodit.com/2010/02/asp-net-mvc-ambiguous-match/

लेकिन, यह एक अच्छा विचार नहीं है।


आप एक अलग विधि के साथ एक ही विधि का उपयोग करने के लिए [एक्शननाम ("न्यूएक्शननाम")] का उपयोग कर सकते हैं:

public class HomeController : Controller
{
    public ActionResult GetEmpName()
    {
        return Content("This is the test Message");
    }

    [ActionName("GetEmpWithCode")]
    public ActionResult GetEmpName(string EmpCode)
    {
        return Content("This is the test Messagewith Overloaded");
    }
}

नहीं, नहीं और नहीं। जाओ और नीचे नियंत्रक कोड आज़माएं जहां हमारे पास "लोड ग्राहक" अधिभारित है।

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

यदि आप "लोड ग्राहक" कार्रवाई का आह्वान करने का प्रयास करते हैं तो आपको नीचे दिए गए आंकड़े में दिखाए गए त्रुटि मिल जाएगी।

पॉलीमोर्फिज्म सी # प्रोग्रामिंग का एक हिस्सा है जबकि HTTP एक प्रोटोकॉल है। HTTP polymorphism समझ में नहीं आता है। अवधारणा या यूआरएल और यूआरएल पर HTTP काम केवल अद्वितीय नाम हो सकता है। तो HTTP polymorphism लागू नहीं करता है।

इसे ठीक करने के लिए हमें "एक्शननाम" विशेषता का उपयोग करने की आवश्यकता है।

public class CustomerController : Controller
    {
        //
        // GET: /Customer/

        public ActionResult LoadCustomer()
        {
            return Content("LoadCustomer");
        }

        [ActionName("LoadCustomerbyName")]
        public ActionResult LoadCustomer(string str)
        {
            return Content("LoadCustomer with a string");
        }
    }

तो अब यदि आप "ग्राहक / लोड ग्राहक" यूआरएल पर कॉल करते हैं तो "लोडकैस्टर" कार्रवाई लागू की जाएगी और यूआरएल संरचना "ग्राहक / लोड ग्राहक" नाम के साथ "लोडकैस्टर (स्ट्रिंग स्ट्र)" लागू किया जाएगा।

उपरोक्त उत्तर मैंने इस कोडप्रोजेक्ट आलेख से लिया है -> एमवीसी एक्शन ओवरलोडिंग


हाँ। मैं प्रत्येक नियंत्रक विधि के लिए कुछ अलग, यानी, HttpGet या HttpGet लिए HttpGet / HttpGet (या समकक्ष AcceptVerbs विशेषता) सेट करके ऐसा करने में सक्षम हूं, लेकिन दोनों नहीं। इस तरह यह अनुरोध के प्रकार के आधार पर बता सकता है कि किस विधि का उपयोग करना है।

[HttpGet]
public ActionResult Show()
{
   ...
}

[HttpPost]
public ActionResult Show( string userName )
{
   ...
}

मेरे पास एक सुझाव यह है कि, इस तरह के मामले के लिए, एक निजी कार्यान्वयन होगा कि आपके दोनों सार्वजनिक कार्य विधियां डुप्लिकेटिंग कोड से बचने के लिए भरोसा करती हैं।


मैं अभी इस प्रश्न में आया हूं और, भले ही यह काफी पुराना है, फिर भी यह बहुत प्रासंगिक है। विडंबना यह है कि इस धागे में एक सही टिप्पणी एमवीसी में एक आत्म-कबूल किए गए शुरुआतकर्ता द्वारा पोस्ट की गई थी जब उसने पद लिखा था। यहां तक ​​कि एएसपी.NET दस्तावेज़ पूरी तरह से सही नहीं हैं। मेरे पास एक बड़ी परियोजना है और मैंने सफलतापूर्वक कार्रवाई विधियों को अधिभारित किया है।

यदि कोई सरल {नियंत्रक} / {action} / {id} डिफ़ॉल्ट मार्ग पैटर्न से परे रूटिंग को समझता है, तो यह स्पष्ट हो सकता है कि नियंत्रक क्रियाओं को किसी भी अद्वितीय पैटर्न का उपयोग करके मैप किया जा सकता है। यहां किसी ने बहुरूपता के बारे में बात की और कहा: "HTTP polymorphism समझ में नहीं आता है", लेकिन रूटिंग के HTTP के साथ कुछ भी नहीं है। स्ट्रिंग पैटर्न मिलान के लिए यह एक तंत्र है, बस, एक तंत्र है।

इस काम को करने का सबसे अच्छा तरीका रूटिंग विशेषताओं का उपयोग करना है, उदाहरण के लिए:

[RoutePrefix("cars/{country:length(3)}")]
public class CarHireController
{
    [Route("{location}/{page:int=1}", Name = "CarHireLocation")]
    public ActionResult Index(string country, string location, int page)
    {
        return Index(country, location, null, page);
    }

    [Route("{location}/{subLocation}/{page:int=1}", Name = "CarHireSubLocation")]
    public ActionResult Index(string country, string location, string subLocation, int page)
    {
        //The main work goes here
    }
}

ये क्रियाएं यूआरएल /cars/usa/new-york और /cars/usa/texas/dallas जैसे यूआरएल का ख्याल /cars/usa/texas/dallas , जो क्रमशः पहले और दूसरे इंडेक्स कार्यों को मैप करेगी।

इस उदाहरण नियंत्रक की जांच करना यह स्पष्ट है कि यह ऊपर वर्णित डिफ़ॉल्ट मार्ग पैटर्न से परे है। डिफ़ॉल्ट रूप से काम करता है यदि आपकी यूआरएल संरचना बिल्कुल आपके कोड नामकरण सम्मेलनों से मेल खाती है, लेकिन यह हमेशा मामला नहीं है। कोड डोमेन का वर्णनात्मक होना चाहिए, लेकिन यूआरएल को अक्सर आगे बढ़ने की आवश्यकता होती है क्योंकि उनकी सामग्री एसईओ आवश्यकताओं जैसे अन्य मानदंडों पर आधारित होनी चाहिए।

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

महत्वपूर्ण नोट एक दोष यह है कि ओवरलोड किए गए कार्यों के लिए यूआरएल उत्पन्न करने के लिए रूटिंग का उपयोग कार्य कार्रवाई के आधार पर काम नहीं करता है, उदाहरण के लिए, UrlHelper.Action का उपयोग करते समय। लेकिन यह काम करता है अगर कोई नामित मार्गों का उपयोग करता है, उदाहरण के लिए, UrlHelper.RouteUrl। और नामित मार्गों का उपयोग करना, सम्मानित स्रोतों के अनुसार, किसी भी तरह से जाने का तरीका ( http://haacked.com/archive/2010/11/21/named-routes-to-the-rescue.aspx/ ) है।

सौभाग्य!





overloading