2012-07-10 17 views
109

मैं एमवीसी 4 वेब एपीआई प्रोजेक्ट का उपयोग शुरू कर रहा हूं, मेरे पास एकाधिक HttpPost विधियों के साथ नियंत्रक है। नियंत्रक निम्नलिखित की तरह दिखता है:वेब एपीआई नियंत्रक में एकाधिक एचटीपीपोस्ट विधि

नियंत्रक

public class VTRoutingController : ApiController 
{ 
    [HttpPost] 
    public MyResult Route(MyRequestTemplate routingRequestTemplate) 
    { 
     return null; 
    } 

    [HttpPost] 
    public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate) 
    { 
     return null; 
    } 
} 

यहाँ MyRequestTemplate टेम्पलेट वर्ग Json से निपटने अनुरोध के माध्यम से आ रहा है के लिए जिम्मेदार प्रतिनिधित्व करता है।

त्रुटि: अगर मैं उपरोक्त विधि यह ठीक काम करता है में से एक को दूर

Multiple actions were found that match the request

:

जब मैं http://localhost:52370/api/VTRouting/TSPRoute या http://localhost:52370/api/VTRouting/Route के लिए एक अनुरोध फ़िडलर का उपयोग कर मैं एक त्रुटि मिलती है।

Global.asax

मैं global.asax में डिफ़ॉल्ट रूटिंग तालिका को संशोधित करने की कोशिश की है, लेकिन मैं अभी भी त्रुटि हो रही है, मुझे लगता है कि मैं Global.asax में मार्गों को परिभाषित करने में समस्या है। ग्लोबल.एक्सएक्स में मैं यही कर रहा हूं।

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.MapHttpRoute(
      name: "MyTSPRoute", 
      routeTemplate: "api/VTRouting/TSPRoute", 
      defaults: new { } 
    ); 

    routes.MapHttpRoute(
     name: "MyRoute", 
     routeTemplate: "api/VTRouting/Route", 
     defaults: new {action="Route" } 
    ); 
} 

मैं पोस्ट का उपयोग कर फ़िडलर में अनुरोध कर रहा हूँ, MyRequestTemplate के लिए RequestBody में json गुजर।

उत्तर

126

आपके पास एक ही नियंत्रक में कई क्रियाएं हो सकती हैं।

इसके लिए आपको निम्नलिखित दो चीजें करना है।

  • पहले सजाने ActionName के साथ कार्रवाई का श्रेय तरह

    [ActionName("route")]` 
    public class VTRoutingController : ApiController 
    { 
        [ActionName("route")] 
        public MyResult PostRoute(MyRequestTemplate routingRequestTemplate) 
        { 
        return null; 
        } 
    
        [ActionName("tspRoute")] 
        public MyResult PostTSPRoute(MyRequestTemplate routingRequestTemplate) 
        { 
        return null; 
        } 
    } 
    
  • दूसरा WebApiConfig फ़ाइल में निम्न मार्गों परिभाषित करते हैं।

    // Controller Only 
    // To handle routes like `/api/VTRouting` 
    config.Routes.MapHttpRoute(
        name: "ControllerOnly", 
        routeTemplate: "api/{controller}"    
    ); 
    
    
    // Controller with ID 
    // To handle routes like `/api/VTRouting/1` 
    config.Routes.MapHttpRoute(
        name: "ControllerAndId", 
        routeTemplate: "api/{controller}/{id}", 
        defaults: null, 
        constraints: new { id = @"^\d+$" } // Only integers 
    ); 
    
    // Controllers with Actions 
    // To handle routes like `/api/VTRouting/route` 
    config.Routes.MapHttpRoute(
        name: "ControllerAndAction", 
        routeTemplate: "api/{controller}/{action}" 
    ); 
    
+0

ठीक काम करता है ..... – yogee

+0

यदि मैं आईडी के प्रकार पर कोई प्रतिबंध सेट नहीं करना चाहता हूं तो क्या होगा? मतलब: मैं स्ट्रिंग आईडी को भी कैसे स्वीकार कर सकता हूं? – frapontillo

+5

@ फ्रैपोंटिलो: आईडी एक अभिन्न अंग होना चाहिए, ताकि यह मार्ग के नाम से विचलित हो जाए अन्यथा रूटिंग एनघिन इसे एक क्रिया नाम के रूप में एक आईडी नाम के रूप में मान लेगा। यदि आपको आईडी को स्ट्रिंग के रूप में रखना है तो आप एक क्रिया बना सकते हैं। –

23

उपयोग:

routes.MapHttpRoute(
    name: "DefaultApi", 
    routeTemplate: "api/{controller}/{action}/{id}", 
    defaults: new { id = RouteParameter.Optional } 
); 

यह एक RESTful दृष्टिकोण नहीं रह गया है, लेकिन अब आप इस तरह नाम से अपने कार्यों कॉल कर सकते हैं (बजाय के लिए आप क्रिया के आधार पर जाल एपीआई स्वचालित रूप से एक निर्धारित करने देना):

[POST] /api/VTRouting/TSPRoute 

[POST] /api/VTRouting/Route 

लोकप्रिय धारणा के विपरीत, इस दृष्टिकोण के साथ कुछ भी गलत नहीं है, और यह वेब एपीआई का दुरुपयोग नहीं कर रहा है। आप अभी भी वेब एपीआई (हैंडलर, सामग्री वार्तालाप, mediatypeformatters और इतने पर प्रतिनिधि) की सभी भयानक सुविधाओं पर लाभ उठा सकते हैं - आप बस रीस्टफुल दृष्टिकोण को हटा दें।

+0

उत्तर के लिए धन्यवाद, लेकिन यह अभी भी मुझे एक ही त्रुटि दे रहा है। – Habib

+0

यह संभव नहीं है, तो आपके ऐप में कुछ और गलत कॉन्फ़िगर किया जाना चाहिए। क्या आप पूरे रूट सेटअप को दिखा सकते हैं? इसके अलावा * आप * नियंत्रक कार्यों को कैसे कॉल कर रहे हैं? –

+0

संपूर्ण रूट सेटअप global.asax में है, मैंने अपने प्रश्न में उस भाग को पोस्ट किया है, अनुरोध करने के लिए, मैं फिडलर-> लिखें-> का उपयोग कर रहा हूं और ऑपरेशन के रूप में पोस्ट का चयन कर रहा हूं – Habib

11

एक वेब एपीआई एंडपॉइंट (नियंत्रक) एक ऐसा संसाधन है जो क्रियाओं को प्राप्त/पोस्ट/रख/हटा देता है। यह एक सामान्य एमवीसी नियंत्रक नहीं है।

आवश्यक रूप से, /api/VTRouting पर केवल एक HttpPost विधि जो आपके द्वारा भेजे जा रहे पैरामीटर स्वीकार करता है। फ़ंक्शन का नाम से कोई फर्क नहीं पड़ता, जब तक आप [http] सामान से सजा रहे हों। मैंने कभी कोशिश नहीं की है, यद्यपि।

संपादित करें: यह काम नहीं करता है। हल करने में, ऐसा लगता है कि इस प्रकार के मॉडल-बाइंड करने की कोशिश नहीं कर रहे पैरामीटर की संख्या से जाना जाता है।

आप विभिन्न मानकों को स्वीकार करने के लिए कार्यों को अधिभारित कर सकते हैं। मुझे पूरा यकीन है कि अगर आप इसे अपने तरीके से घोषित करते हैं तो आप ठीक होंगे, लेकिन विधियों के लिए अलग-अलग (असंगत) पैरामीटर का उपयोग करते हैं। यदि परम समान हैं, तो आप भाग्य से बाहर हैं क्योंकि मॉडल बाध्यकारी आपको नहीं पता होगा कि आपका क्या मतलब है।

[HttpPost] 
public MyResult Route(MyRequestTemplate routingRequestTemplate) {...} 

[HttpPost] 
public MyResult TSPRoute(MyOtherTemplate routingRequestTemplate) {...} 

यह हिस्सा काम करता है

वे दे जब आप बनाते हैं एक नया एक यह बहुत स्पष्ट है, और मैं कहूंगा कि आप इस सम्मेलन के साथ छड़ी चाहिए डिफ़ॉल्ट टेम्पलेट:

public class ValuesController : ApiController 
{ 
    // GET is overloaded here. one method takes a param, the other not. 
    // GET api/values 
    public IEnumerable<string> Get() { .. return new string[] ... } 
    // GET api/values/5 
    public string Get(int id) { return "hi there"; } 

    // POST api/values (OVERLOADED) 
    public void Post(string value) { ... } 
    public void Post(string value, string anotherValue) { ... } 
    // PUT api/values/5 
    public void Put(int id, string value) {} 
    // DELETE api/values/5 
    public void Delete(int id) {} 
} 

यदि आप एक वर्ग बनाना चाहते हैं जो कई चीजें करता है, AJAX उपयोग के लिए, मानक नियंत्रक/क्रिया पैटर्न का उपयोग न करने का कोई बड़ा कारण नहीं है। एकमात्र वास्तविक अंतर यह है कि आपकी विधि हस्ताक्षर सुंदर नहीं हैं, और आपको उन्हें वापस करने से पहले Json(returnValue) में चीजों को लपेटना होगा।

संपादित करें:

ओवरलोडिंग ठीक जब साधारण प्रकार का उपयोग कर जब मानक टेम्पलेट (शामिल करने के लिए संपादित) का उपयोग कर काम करता है। मैं अलग-अलग हस्ताक्षरों के साथ 2 कस्टम ऑब्जेक्ट्स के साथ, दूसरी तरफ चला गया और परीक्षण किया। इसे काम करने के लिए कभी नहीं मिल सकता है।

  • जटिल वस्तुओं के साथ बाध्यकारी नहीं लगती है "गहरी", तो thats नो-जाना
  • आप उपलब्ध विकल्पों में
  • पर एक अतिरिक्त परम गुजर, क्वेरी स्ट्रिंग
  • A better writeup than I can give पर द्वारा इस के आसपास मिल सकता है

यह इस मामले में मेरे लिए काम करता है, देखें कि यह आपको कहां प्राप्त करता है। केवल परीक्षण के लिए अपवाद।

public class NerdyController : ApiController 
{ 
    public void Post(string type, Obj o) { 
     throw new Exception("Type=" + type + ", o.Name=" + o.Name); 
    } 
} 

public class Obj { 
    public string Name { get; set; } 
    public string Age { get; set; } 
} 

और इस रूप की तरह सांत्वना कहा जाता है:

$.post("/api/Nerdy?type=white", { 'Name':'Slim', 'Age':'21' }) 
+0

मैंने पैरामीटर प्रकारों को बदलने का प्रयास किया है, लेकिन ऐसा लगता है कि यह केवल नियंत्रक में एक एकल पोस्ट विधि की अनुमति देता है। आपके उत्तर – Habib

+0

के लिए धन्यवाद मैंने माना है कि यह मॉडल को बाध्य करने का प्रयास करेगा, क्योंकि आप इसे अधिभारित कर सकते हैं। यह अलग-अलग # पैरा के साथ काम करता है, हालांकि। हालांकि ऐसा करने के लिए इसे फिर से लिखना मुश्किल नहीं हो सकता है, लेकिन उन्होंने अभी तक स्रोत कोड जारी नहीं किया है, इसलिए मैं वास्तव में काम नहीं कर रहा कारण बताते हुए बदसूरत disassembly –

+2

+1 पर अटक गया है, और वेब एपीआई के पीछे दर्शन। – MEMark

0
public class Journal : ApiController 
{ 
    public MyResult Get(journal id) 
    { 
     return null; 
    } 
} 

public class Journal : ApiController 
{ 

    public MyResult Get(journal id, publication id) 
    { 
     return null; 
    } 
} 

मैं यकीन नहीं है कि अधिक भार प्राप्त/पोस्ट विधि restfull एपीआई की अवधारणा का उल्लंघन करता है नहीं कर रहा हूँ, लेकिन यह workds। अगर कोई इस मामले पर प्रबुद्ध हो सकता है। क्या होगा यदि मैं

uri:/api/journal/journalid 
uri:/api/journal/journalid/publicationid 

इतनी के रूप में आप aggregateroot की मेरी पत्रिका तरह देखा हो सकता है, हालांकि मैं पूरी तरह से प्रकाशन के लिए एक और नियंत्रक को परिभाषित करने और मेरा url में प्रकाशन के आईडी नंबर पारित कर सकते हैं के रूप में एक uri है लेकिन इस और अधिक जानकारी मिलती है। चूंकि मेरा प्रकाशन जर्नल के बिना अस्तित्व में नहीं होगा।

0

मैं सिर्फ यूआरएल और इस तरह से मार्ग इंजन जानता है कि मैं क्या कार्रवाई चाहते करने के लिए जोड़ा "कार्रवाई = ACTION_NAME"।मैंने कार्यों में एक्शननाम विशेषता भी जोड़ा लेकिन मुझे यकीन नहीं है कि इसकी आवश्यकता है।

0

मुझे लगता है कि प्रश्न का उत्तर पहले ही दिया जा चुका है। मैं कुछ वेब एपीआई नियंत्रक की भी तलाश कर रहा था जिसमें एक ही हस्ताक्षर किए गए मेहटोड हैं लेकिन अलग-अलग नाम हैं। मैं कैलकुलेटर को वेबएपी के रूप में लागू करने की कोशिश कर रहा था। कैलक्यूलेटर में एक ही हस्ताक्षर के साथ 4 विधियां हैं लेकिन अलग-अलग नाम हैं।

public class CalculatorController : ApiController 
{ 
    [HttpGet] 
    [ActionName("Add")] 
    public string Add(int num1 = 1, int num2 = 1, int timeDelay = 1) 
    { 
     Thread.Sleep(1000 * timeDelay); 
     return string.Format("Add = {0}", num1 + num2); 
    } 

    [HttpGet] 
    [ActionName("Sub")] 
    public string Sub(int num1 = 1, int num2 = 1, int timeDelay = 1) 
    { 
     Thread.Sleep(1000 * timeDelay); 
     return string.Format("Subtract result = {0}", num1 - num2); 
    } 

    [HttpGet] 
    [ActionName("Mul")] 
    public string Mul(int num1 = 1, int num2 = 1, int timeDelay = 1) 
    { 
     Thread.Sleep(1000 * timeDelay); 
     return string.Format("Multiplication result = {0}", num1 * num2); 
    } 

    [HttpGet] 
    [ActionName("Div")] 
    public string Div(int num1 = 1, int num2 = 1, int timeDelay = 1) 
    { 
     Thread.Sleep(1000 * timeDelay); 
     return string.Format("Division result = {0}", num1/num2); 
    } 
} 

और WebApiConfig में आप फाइल पहले से ही

config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{action}/{id}", 
      defaults: new { id = RouteParameter.Optional }); 

बस आईआईएस पर प्रमाणीकरण/प्राधिकरण की स्थापना की और आपका काम हो गया है!

आशा है कि इससे मदद मिलती है!

5

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

config.Routes.MapHttpRoute("API Default", 
           "api/{controller}/{action}/{id}", 
           new { id = RouteParameter.Optional }); 
13

एक आपकी समस्या का काफी बेहतर समाधान Route आप एनोटेशन द्वारा विधि पर मार्ग निर्दिष्ट कर सकते हैं जो उपयोग करने के लिए होगा:

[RoutePrefix("api/VTRouting")] 
public class VTRoutingController : ApiController 
{ 
    [HttpPost] 
    [Route("Route")] 
    public MyResult Route(MyRequestTemplate routingRequestTemplate) 
    { 
     return null; 
    } 

    [HttpPost] 
    [Route("TSPRoute")] 
    public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate) 
    { 
     return null; 
    } 
} 
+0

क्या नेमस्पेस रूट है? मैं एमवीसी 4 का उपयोग कर रहा हूं और रूट पहचाना नहीं गया है। – eaglei22

+0

2 निम्नलिखित स्रोतों को देखें http://www.asp.net/web-api/overview/web-api-routing-and-actions/create-a-rest-api-with-attribute-routing http: // www .asp.net/web-api/overview/web-api-routing-and-actions/विशेषता-रूटिंग-इन-वेब-एपीआई -2 – Wisienkas

+0

हां, यह वही तरीका है जिसे जाना चाहिए। धन्यवाद। – newman

1

नियंत्रक स्तर पर रूट उपसर्ग [रूटफ्रिक्स ("एपीआई/प्रोफाइल")] रखो और एक्शन विधि [रूट ("LikeProfile") पर एक मार्ग डालें]। Global.asax फ़ाइल में कुछ भी बदलने की आवश्यकता नहीं है

namespace KhandalVipra.Controllers 
{ 
    [RoutePrefix("api/Profiles")] 
    public class ProfilesController : ApiController 
    { 
     // POST: api/Profiles/LikeProfile 
     [Authorize] 
     [HttpPost] 
     [Route("LikeProfile")] 
     [ResponseType(typeof(List<Like>))] 
     public async Task<IHttpActionResult> LikeProfile() 
     { 
     } 
    } 
} 
संबंधित मुद्दे