2012-09-10 20 views
5

मैं निम्न क्रियाओं के साथ एक नियंत्रक Groups है:ASP.NET वेब एपीआई में एकाधिक PUT तरीकों

public GroupModel Get(int ID) 

public GroupModel Post(CreateGroupModel model) 

public void Put(PublicUpdateGroupModel model) 

public void PutAddContacts(UpdateContactsModel model) 

public void PutRemoveContacts(UpdateContactsModel model) 

public void Delete(int ID) 

और मुझे क्या करना चाहते हैं मानक प्राप्त कॉल करने के लिए, पोस्ट मार्ग मानक बाकी का उपयोग है, डाल , mehods हटाओ। लेकिन PutAddContacts और PutRemoveContacts फोन कार्रवाई के नाम यूआरएल के साथ जोड़ दिया जाता है, उदाहरण के लिए:

प्राप्त समूहों/- कॉल विधि जाओ

पोस्ट समूहों/- कॉल पोस्ट विधि

PUT समूहों/- कॉल विधि रखो

समूह हटाएं/- कॉल्स हटवायचे विधि

PUT समूहों/addcontacts - कॉल PutAddContacts विधि

+०१२३५१६४१०६१

PUT समूहों/removecontacts - कॉल PutRemoveContacts विधि

क्या यह संभव है यह करने के लिए रूटिंग सेट या मैं मार्ग अगर मैं अपने यूआरएल में कार्रवाई नामों का उपयोग करना चाहते हैं के लिए आरपीसी मार्ग नीचे जाने की जरूरत करना है?

उत्तर

11

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

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

मार्ग जोड़ने के बाद, ठेठ MVC फैशन में चीजें जहां नियंत्रक नाम & क्रिया का उपयोग कहते हैं। अपने प्रश्न से, तथापि, मुझे लगता है कि आप वास्तव में के बजाय सिर्फ यह इतना काम करने के लिए पर पढ़ें होने का, RESTful होना चाहता हूँ ...

RESTful
बाकी doesn't require HTTP होने के नाते, हालांकि दोनों अक्सर साथ चर्चा कर रहे हैं। आरईएसटी वास्तव में हर संसाधन के बारे में है जो अर्थात् सटीक प्रतिनिधित्व करता है। HTTP का उपयोग करते समय इसका मतलब अद्वितीय यूआरआई है जो HTTP अर्थशास्त्र का सम्मान करता है। तो उदाहरण के लिए, HTTP GET का उपयोग करने वाले कॉल को डेटा को कभी भी संशोधित नहीं करना चाहिए क्योंकि यह HTTP की बुनियादी परिभाषा का उल्लंघन करता है और कैश जैसे HTTP बुनियादी ढांचे को भ्रमित करता है।

पोस्ट/PUT बनाम मर्ज/PATCH
हम सब प्राप्त से परिचित हैं, पोस्ट, डाल, प्रमुख, आदि .. HTTP तरीके के रूप में। आम तौर पर, जीईटी पुनर्प्राप्त करने के लिए है, पोस्ट जोड़ने के लिए है, और PUT संशोधित करने के लिए है (हालांकि बहस के अधीन)। फिर भी, आपके पास दो प्रकार के संशोधन हैं: आइटम जोड़ना और संग्रह से वस्तुओं को निकालना। तो क्या वे दोनों पुट या कुछ और हैं? यह कैसे करें इस पर समुदाय hasn't quite settled

  • विकल्प 1: कस्टम मीडिया प्रकार - HTTP कल्पना वास्तव में सभी प्रकार के तरीकों के लिए अनुमति देता है, यह ब्राउज़रों कि वास्तव में परिचित सबसेट करने के लिए हमें प्रतिबंधित है। तो आप MERGE (a Roy Fielding work around) or PATCH (an oData work around) विधियों को बना सकते हैं और इस नए मीडिया प्रकार के लिए व्यवहार को परिभाषित कर सकते हैं - शायद एक जोड़ने के लिए और एक हटाने के लिए।

  • विकल्प 2: POST/PUT का उपयोग करें - संपर्क जोड़ने और हटाने दोनों के लिए PUT का उपयोग करें। आईडी की सूची को टॉगल की तरह ही देखें (यदि मौजूद है, तो गायब होने पर मौजूद है, या वैकल्पिक रूप से पर्याप्त जानकारी शामिल है कि क्या करना है। फिर क्लाइंट को इंगित करने वाला एक HTTP 303 वापस करें, जिसमें एक पुरानी स्थिति है और ताज़ा करें।

  • विकल्प 3: पूर्ण सूची - यदि आपका सेट उचित आकार है, तो आप हर बार जब आप अपडेट करना चाहते हैं तो संपर्कों की पूरी सूची हमेशा पास कर सकते हैं। इस तरह तर्क एक सुपर सरल पोंछ और प्रतिस्थापित है।

क्या वास्तव में एक RESTful नजरिए से मायने रखती है कि आपके आवेदन सभी तरीकों में समान तरह से व्यवहार करती है। तो अगर मेर्ज का मतलब है, तो इसका मतलब हमेशा जोड़ना चाहिए। यदि आप उम्मीद करते हैं कि आईडी के पूर्ण सेट को PUT पर पास किया गया है तो हमेशा एक पूर्ण सेट पास करें।

नियंत्रक डिजाइन
तो यह मेरे थे, मैं एकाधिक नियंत्रकों में अपने नियंत्रक टूट जाएगा। एक नियंत्रक समूह के साथ अन्य सौदों के संपर्क (एक समूह के रूप में) और एक समूह के भीतर एक संपर्क के साथ एक तिहाई सौदों के साथ सौदा करता है। कुछ की तरह ...

//api/Group/ 
public List<GroupModel> Get() 
public GroupModel Get(int ID) 
public GroupModel Post(GroupModel model) //add a group 
public GroupModel Put(GroupModel model) //update a group (see comments above) 
public void Delete(int ID) 


//api/GroupContacts/ 
public ContactsModel Get()     //gets complete list 
public void PostContacts(ContactsModel model) //pushes a COMPLETE new state 
public void Delete()       //delete entire group of contacts 


//api/GroupContact/354/ 
public ContactModel Get(int id)    //get contact id #354 
public void PostContact(ContactModel model) //add contact (overwrite if exits) 
public void Delete(int id)     //delete contact if exists 

आप अपने यूआरएल नेस्ट प्रकट करने के लिए (जैसे: /api/Group/Contacts, /api/Group/Contact) चाहते हैं, आप this other post I wrote देख सकते हैं। आईएमएचओ, एएसपीनेट की रूटिंग को थोड़ा आसान बनाने के लिए एक ट्यून अप की आवश्यकता है ... लेकिन यह एक अलग मुद्दा है ;-)

+0

भयानक उत्तर के लिए Thx! मैं आपके दावे से सहमत हूं कि आरईएसटी अर्थशास्त्र के बारे में अधिक है, और यही कारण है कि मेरा मानना ​​है कि मेरा उदाहरण अभी भी बाकी है। और मज़ेदार रूप से पर्याप्त, मैं वास्तव में आपके अन्य पोस्ट में पहले आया था और सब-फ़ोल्डर्स का उपयोग करके कुछ ऐसा ही लागू किया था और प्रत्येक उप-फ़ोल्डर के लिए मार्ग बना रहा था, अगर मैं किसी ने मेरे समाधान को चिह्नित करने का जवाब नहीं दिया तो मुझे यह पोस्ट जवाब देने जा रहा था लेकिन मुझे लगता है मुझे अब परेशान करने की आवश्यकता नहीं है: डी – jcvandan

+0

सेवा की खुशी है। मैं बस एक बड़ी एपीआई परियोजना पर काम कर रहा हूं जो वेबपी बीटा के दौरान शुरू हुआ था। एमवीसी के बीच सूक्ष्म डिजाइन शिफ्ट के आसपास अपना सिर लेने में थोड़ी देर लग गई, जहां मेरे पास नियंत्रक और एपीआई शैली में विधियों का एक गुच्छा हो सकता है जहां मेरे पास नियंत्रक प्रसार होता है। – EBarr

+0

@EBarr मैं इस प्रश्न के उत्तर में मैंने पदानुक्रमित रूटिंग पर आपकी प्रतिक्रिया के लिए उत्सुक होगा। –

3

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

रूटिंग के लिए यह दृष्टिकोण आपको पथ के खंडों के पदानुक्रम के रूप में अपना यूआरआई नेमस्पेस बनाने की आवश्यकता है। नियंत्रकों के लिए पूर्ण यूआरआई पैटर्न से मेल खाने के बजाय, आप पथ खंडों के पेड़ में मनमानी बिंदुओं पर नियंत्रकों को संलग्न करते हैं।

बस आपको यह कैसा रहा यूआरआई के साथ एक छोटे आत्म मेजबान नमूना आपको बस इतना करना कोशिश कर रहे हैं के समान बनाया लगेगा की एक विचार देने के लिए:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
    var baseAddress = new Uri("http://oak:8700/"); 

    var configuration = new HttpSelfHostConfiguration(baseAddress); 
    var router = new ApiRouter("api", baseAddress); 

    // /api/Contacts 
    router.Add("Contacts", rcs => rcs.To<ContactsController>()); 

    // /api/Contact/{contactid} 
    router.Add("Contact", rc => 
          rc.Add("{contactid}", rci => rci.To<ContactController>())); 

    // /api/Group/{groupid} 
    // /api/Group/{groupid}/Contacts 
    router.Add("Group", rg => 
         rg.Add("{groupid}", rgi => rgi.To<GroupController>() 
                 .Add("Contacts", rgc => rgc.To<GroupContactsController>()))); 


    configuration.MessageHandlers.Add(router); 

    var host = new HttpSelfHostServer(configuration); 
    host.OpenAsync().Wait(); 

    Console.WriteLine("Host open. Hit enter to exit..."); 

    Console.Read(); 

    host.CloseAsync().Wait(); 
    } 
} 

public class GroupController : TestController { } 
public class ContactsController : TestController { } 
public class ContactController : TestController { } 
public class GroupContactsController : TestController { } 


public class TestController : ApiController 
{ 
    public HttpResponseMessage Get() 
    { 
     var pathRouteData = (PathRouteData) Request.GetRouteData(); 

     var paramvalues = new StringBuilder(); 

     foreach (KeyValuePair<string, object> keyValuePair in pathRouteData.Values) 
     { 
      paramvalues.Append(keyValuePair.Key); 
      paramvalues.Append(" = "); 
      paramvalues.Append(keyValuePair.Value); 
      paramvalues.Append(Environment.NewLine); 
     } 

     var url = pathRouteData.RootRouter.GetUrlForController(this.GetType()); 

     return new HttpResponseMessage() 
        { 
         Content = new StringContent("Response from " + this.GetType().Name + Environment.NewLine 
                + "Url: " + url.AbsoluteUri 
                + "Parameters: " + Environment.NewLine 
                + paramvalues.ToString()) 
        }; 
    } 
} 

आप सिर्फ इस पेस्ट करने के लिए सक्षम होना चाहिए एक कंसोल ऐप में कोड जोड़ें और माइक्रोसॉफ्ट.एस्पनेट.एबएपीआई। सेल्फहोस्ट और टेविस। वेबएपीआई राउटर न्यूजेट्स में एक संदर्भ जोड़ें और इसे आज़माएं। यदि आप उत्सुक हैं कि इस तरह के रूटिंग के साथ आप कितनी दूर जा सकते हैं, तो here पर एक जटिल नमूना है।

+0

दिलचस्प। मैं अभी एक तंग समय सीमा पर हूं, लेकिन मैं नियमित आधार पर लिखने वाले लंबे उत्तरों पर वापस आ जाता हूं।मैं अपना खुद का मार्ग हैंडलर लिखने की योजना बना रहा था। मैं वास्तव में वह चाहता हूं जो मेरे नामस्थानों का सम्मान करता है (इसलिए 'UI.Parent.Child.GrandChild' में कक्षाएं '/ api/parent/child/grandchild' पर मैप करेंगी। तो शायद आपने मुझे समय बचाया :-)। मैं वापस सर्कल और मूल्यांकन करूँगा, लेकिन मुझे कुछ हफ्तों लग सकते हैं। – EBarr

+0

@Ebarr यह कुछ कोड लिखने के लिए काफी सरल होना चाहिए जो नामस्थान के खिलाफ प्रतिबिंबित करता है और एपीकंट्रोलर के लिए शिकार करता है और स्वचालित रूप से पदानुक्रम बनाता है। सिर्फ पैरामीटर जिन्हें किसी प्रकार के सम्मेलन की आवश्यकता होगी। मेरे पास मेरे नामस्थान मेरे यूआरआई से मेल खाते हैं, इसलिए यह मेरे लिए उपयोगी होगा। –

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