2012-08-22 17 views
15

का समर्थन करने के लिए जेनेरिक वेब एपीआई नियंत्रक क्या एक सामान्य वेब एपीआई होना संभव है जो आपकी परियोजना में किसी भी मॉडल का समर्थन करेगा?किसी भी मॉडल

class BaseApiController<T> :ApiController 
{ 
    private IRepository<T> _repository; 

    // inject repository 

    public virtual IEnumerable<T> GetAll() 
    { 
     return _repository.GetAll(); 
    } 

    public virtual T Get(int id) 
    { 
     return _repositry.Get(id); 
    } 

    public virtual void Post(T item) 
    { 
     _repository.Save(item); 
    } 
    // etc... 
} 

class FooApiController : BaseApiController<Foo> 
{ 
    //.. 

} 

class BarApiController : BaseApiController<Bar> 
{ 
    //.. 
} 

क्या यह एक अच्छा दृष्टिकोण होगा?

आखिरकार, मैं केवल सीआरयूडी विधियों को दोहरा रहा हूं? क्या मैं इस आधार वर्ग का उपयोग मेरे लिए काम करने के लिए कर सकता हूं?

क्या यह ठीक है? क्या आप यह करेंगे कोई बेहतर विचार?

+0

हाय, मुझे पता है कि यह एक पुराना सवाल है, लेकिन क्या आप समझा सकते हैं कि आप अपनी जेनेरिक एक्शन विधियों को कैसे कॉल करते हैं? ऐसा लगता है कि आप इसे केवल रूटिंग नियमों के साथ पूरा कर सकते हैं। मुझे इसकी तारीफ़ करने में गर्व है। – Brett

उत्तर

22

मैंने कुछ हासिल करने और किसी ग्राहक को डेमो चलाने के लिए यह एक छोटी परियोजना के लिए किया था। एक बार जब मैं व्यवसाय नियमों, सत्यापन और अन्य विचारों के बारे में जानकारी प्राप्त करता हूं, तो मैंने अपनी बेस क्लास से सीआरयूडी विधियों को ओवरराइड करने के लिए समाप्त किया, इसलिए यह दीर्घकालिक कार्यान्वयन के रूप में नहीं निकला।

मैं, मार्ग के साथ समस्याओं में भाग नहीं है, क्योंकि सब कुछ एक आईडी एक ही प्रकार के (मैं एक मौजूदा प्रणाली के साथ काम कर रहा था) का इस्तेमाल किया। कुछ तालिकाओं में int प्राथमिक कुंजी थी, कुछ में strings था और अन्य guids थे।

मुझे इसके साथ-साथ समस्याएं भी समाप्त हुईं। अंत में, जब मैंने पहली बार ऐसा किया, तो यह वास्तव में एक वास्तविक दुनिया के कार्यान्वयन में इसका उपयोग करने के लिए एक अलग मामला साबित हुआ और मुझे किसी भी आगे आगे नहीं रखा।

+6

अच्छी तरह से आप अलग-अलग प्रकार के आईडी का प्रतिनिधित्व करने के लिए इंटरफ़ेस कॉल 'IIDentifier ' का उपयोग कर सकते हैं। – DarthVader

+0

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

+0

यदि आप ग्रीनफील्ड हैं, तो आपके पास एक ही प्रकार के सभी "आईडी" नहीं होने का कोई कारण नहीं है .. – LastTribunal

5

यह निश्चित रूप से संभव है। मेरे पास पहले ऐसा करने का कोई कारण नहीं था, लेकिन अगर यह आपकी स्थिति के लिए काम करता है, तो यह अच्छा होना चाहिए।

यदि आपके सभी मॉडल को उसी तरह से सहेजा और पुनर्प्राप्त किया जा सकता है, तो शायद वे सभी एक ही नियंत्रक में हों, हालांकि?

+0

अच्छी तरह से यह क्यों काम नहीं करेगा? अनिवार्य रूप से अधिकांश समय, हम सभी डोमेन मॉडलों के लिए एक ही ऑपरेशन का उपयोग करना और उन्हें कई बार दोहराना है। – DarthVader

+1

आपने पूछा कि क्या यह संभव था, इसलिए मैंने जवाब दिया :) :) मुझे लगता है कि मैं बाकी प्रश्न से कम गिर गया, मैं बस अपना जवाब हटा सकता हूं ... – eouw0o83hf

+0

मैं आपको अपना उत्तर हटाने के लिए +1 नहीं दूंगा :) – DarthVader

0

पिछले जवाब में कहा गया यह बिल्कुल संभव है। यह अच्छा दृष्टिकोण और निश्चित रूप से अच्छी वास्तुकला है। लेकिन मैं समझ नहीं पा रहा हूं कि आपके नियंत्रक सार्वजनिक क्यों नहीं हैं। हो सकता है कि यह आपकी समस्या हो और इसके कारण आपका कोड काम नहीं करेगा?

+0

ओह मैंने अभी यहां टाइप किया है। मॉडिफायर्स तक पहुंच पर ज्यादा ध्यान नहीं दिया। – DarthVader

+0

तो काम नहीं करने के लक्षण क्या हैं? –

+0

जिन्होंने काम नहीं किया? मैंने पूछा कि क्या यह व्यवहार्य या अच्छा डिजाइन/ – DarthVader

1

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

मैं वास्तव में एक बड़ी परियोजना के लिए कुछ ऐसा कर रहा हूं जहां उपयोगकर्ता अपनी संस्थाओं और एपीआई को परिभाषित कर सकते हैं - यानी: एक उपयोगकर्ता उपयोगकर्ता और खाते रखना चाहता है जबकि कोई अन्य कारों और अन्य चीज़ों को ट्रैक करना चाहता है। वे सभी एक ही आंतरिक नियंत्रक का उपयोग करते हैं, लेकिन उनमें से प्रत्येक का अपना अंत बिंदु होता है।

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

[POST("{primaryEntity}", RouteName = "PostPrimary")] 
public async Task<HttpResponseMessage> CreatePrimary(string primaryEntity, JObject entity) 
{ 
    // first find out which params are necessary to accept the request based on the entity's mapped metadata type 
    OperationalParams paramsForRequest = GetOperationalParams(primaryEntity, DatasetOperationalEntityIntentIntentType.POST); 

    // map the passed values to the expected params and the intent that is in use 
    IDictionary<string, object> objValues = MapAndValidateProperties(paramsForRequest.EntityModel, paramsForRequest.IntentModel, entity); 

    // get the results back from the service and return the data to the client. 
    QueryResults results = await paramsForRequest.ClientService.CreatePrimaryEntity(paramsForRequest.EntityModel, objValues, entity, paramsForRequest.IntentModel); 
     return HttpResponseMessageFromQueryResults(primaryEntity, results); 

} 
+0

शुभकामनाएं :) बहुत जटिल लगती है। मैं उन सभी से बचूंगा। :) – DarthVader

+1

आप जो कर रहे हैं उसके लिए, हाँ, मामूली ओवरकिल;)। हालांकि, उपर्युक्त कोड प्रत्येक ग्राहक में एकाधिक ऐप्स को एकाधिक जेनरेट नियंत्रक का उपयोग करके कई इकाइयों को प्रबंधित करने की अनुमति देता है (वास्तव में हमने इसे प्रति क्रिया प्रकार नियंत्रक में तोड़ दिया है) इसलिए जब आप समस्या को हल करना चाहते हैं तो इतना जटिल नहीं है । और यदि हम उपरोक्त कोड का उपयोग कर सकते हैं और 100 एमएमएस प्रतिक्रिया समय के साथ हजारों ग्राहकों का समर्थन कर सकते हैं, तो आप जाने के लिए अच्छे हैं;)। वैसे भी, विचार के लिए भोजन के रूप में इसे पूरा करने का एक और तरीका दिखाने की कोशिश कर रहा है। – AlexGad

+0

ठंडा :) शुभकामनाएं :) – DarthVader

1

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

मेरा समाधान (अभी तक सही ढंग से कार्यान्वित नहीं किया गया) कस्टम IHttpControllerSelector बनाना था जो सभी अनुरोधों के लिए मेरे जेनेरिक नियंत्रक का चयन करता है, वहां मैं अनुरोध पथ के आधार पर प्रतिबिंब सेटिंग जेनेरिक पैरामीटर के माध्यम से सामान्य से कंक्रीट के कंट्रोलर के डिस्क्रिप्टर प्रकार को सेट कर सकता हूं।

इसके अलावा एक अच्छा प्रारंभिक बिंदु http://entityrepository.codeplex.com/ है (मैं stackoverflow पर इस यहीं कहीं मिल गया है)

1

आप क्या कर के रूप में अन्य लोगों ने कहा निश्चित रूप से संभव है। लेकिन भंडार निर्भरताओं के लिए, आपको निर्भरता इंजेक्शन का उपयोग करना चाहिए। मेरा ठेठ नियंत्रक (एपीआई या एमवीसी) निम्नानुसार होगा।

public class PatientCategoryApiController : ApiController 
{ 

    private IEntityRepository<PatientCategory, short> m_Repository; 
    public PatientCategoryApiController(IEntityRepository<PatientCategory, short> repository) 
    { 
     if (repository == null) 
      throw new ArgumentNullException("entitiesContext is null"); 

     m_Repository = repository; 
    } 
} 

यह ठेठ कन्स्ट्रक्टर इंजेक्शन पैटर्न है। आपको डी इंजेक्शन या ऑटोफैक जैसे कंटेनरों की अच्छी समझ होनी चाहिए। यदि आप DI को नहीं जानते हैं, तो आपके पास एक लंबी सड़क है। लेकिन यह एक उत्कृष्ट दृष्टिकोण है। इस पुस्तक पर एक नज़र डालें। https://www.manning.com/books/dependency-injection-in-dot-net

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