2012-08-07 21 views
112

में धारावाहिक होने से संपत्ति को रोकें। मैं एक एमवीसी 4 वेब एपीआई और एएसपीनेट वेबफॉर्म 4.0 का उपयोग कर रहा हूं ताकि बाकी एपीआई बन सकें। यह बहुत अच्छा काम कर रहा है:वेब एपीआई

[HttpGet] 
public HttpResponseMessage Me(string hash) 
{ 
    HttpResponseMessage httpResponseMessage; 
    List<Something> somethings = ... 

    httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK, 
           new { result = true, somethings = somethings }); 

    return httpResponseMessage; 
} 

अब मुझे कुछ गुणों को क्रमबद्ध करने की आवश्यकता है। मुझे पता है कि मैं सूची में कुछ linq का उपयोग कर सकता हूं और केवल उन्हीं गुणों को प्राप्त कर सकता हूं, और सामान्य रूप से यह एक अच्छा दृष्टिकोण है, लेकिन वर्तमान परिदृश्य में something ऑब्जेक्ट बहुत जटिल है, और मुझे विभिन्न तरीकों से गुणों का एक अलग सेट चाहिए, इसलिए रन टाइम पर, प्रत्येक संपत्ति को अनदेखा करना आसान है।

क्या ऐसा करने का कोई तरीका है?

+0

आप संपत्ति में ScriptIgnore जोड़ सकते हैं। इस सवाल को देखें http://stackoverflow.com/questions/10169648/how-to-exclude-property-from-json-serialization – atbebtg

उत्तर

3

आप AutoMapper का उपयोग करें और .Ignore() मैपिंग का उपयोग और फिर मैप की वस्तु

CreateMap<Foo, Foo>().ForMember(x => x.Bar, opt => opt.Ignore()); 
138

ASP.NET वेब एपीआई भेजने के लिए सक्षम हो सकता है डिफ़ॉल्ट फ़ॉर्मेटर रूप Json.Net का उपयोग करता है, इसलिए यदि आपके आवेदन सिर्फ केवल डेटा के रूप में JSON का उपयोग करता है प्रारूप, आप क्रमबद्धता के लिए प्रॉपर्टी को नकारने के [JsonIgnore] उपयोग कर सकते हैं:

public class Foo 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [JsonIgnore] 
    public List<Something> Somethings { get; set; } 
} 

लेकिन, इस तरह से XML स्वरूप का समर्थन नहीं करता। तो, इस मामले में अपने आवेदन समर्थन XML स्वरूप और अधिक (या केवल XML का समर्थन), Json.Net उपयोग करने के बजाय, आप [DataContract] जो दोनों JSON और एक्सएमएल का समर्थन करता है का उपयोग करना चाहिए करने के लिए है:

[DataContract] 
public class Foo 
{ 
    [DataMember] 
    public int Id { get; set; } 
    [DataMember] 
    public string Name { get; set; } 

    //Ignore by default 
    public List<Something> Somethings { get; set; } 
} 

अधिक समझने के लिए, आप कर सकते हैं official article पढ़ें।

+0

मुझे लगता है कि मुझे jsonignore का उपयोग करके रन टाइम पर विशेषताओं को जोड़ने और निकालने का तरीका ढूंढना होगा। – user1330271

+0

एक चार्म की तरह काम किया! धन्यवाद :) –

+0

यह दुखद क्यों है कि जेसन इग्नोर विशेषता XML प्रतिक्रिया के साथ समर्थित नहीं है? – Mukus

95

वेब एपीआई प्रलेखन पेज JSON and XML Serialization in ASP.NET Web API के अनुसार स्पष्ट रूप से एक संपत्ति आप Json serializer या [IgnoreDataMember] डिफ़ॉल्ट एक्सएमएल serializer के लिए के लिए [JsonIgnore] उपयोग कर सकते हैं पर क्रमबद्धता को रोकने के लिए।

हालांकि परीक्षण में मैंने देखा है कि [IgnoreDataMember] दोनों एक्सएमएल और जेसन अनुरोधों के लिए क्रमबद्धता को रोकता है, इसलिए मैं एकाधिक गुणों के साथ एक संपत्ति को सजाने के बजाय इसका उपयोग करने की सलाह दूंगा।

+2

के साथ काम करता है यह बेहतर जवाब है। इसमें एक विशेषता के साथ एक्सएमएल और जेएसओएन शामिल हैं। – Oliver

+15

अफसोस की बात है '[IgnoreDataMember]' आलसी लोड ईएफ 6 प्रॉक्सी ऑब्जेक्ट्स (आभासी गुण) के साथ काम करने के लिए प्रतीत नहीं होता है। '[DataContract]' और '[डेटामेम्बर] 'हालांकि, करते हैं। – Nick

21

देने के बजाय डिफ़ॉल्ट रूप से क्रमबद्ध हो, आप "ऑप्ट-इन" दृष्टिकोण ले सकते हैं। इस परिदृश्य में, केवल आपके द्वारा निर्दिष्ट गुणों को क्रमबद्ध करने की अनुमति है। System.Runtime.Serialization नामस्थान में पाए गए DataContractAttribute और DataMemberAttribute के साथ ऐसा करते हैं।

DataContactAttribute वर्ग के लिए लागू किया जाता है, और DataMemberAttribute प्रत्येक सदस्य आप धारावाहिक होना चाहते हैं पर लागू होता है:

[DataContract] 
public class MyClass { 

    [DataMember] 
    public int Id { get; set;} // Serialized 

    [DataMember] 
    public string Name { get; set; } // Serialized 

    public string DontExposeMe { get; set; } // Will not be serialized 
} 

हिम्मत मैं कहता हूँ कि यह एक बेहतर दृष्टिकोण है क्योंकि इसके बारे में स्पष्ट निर्णय लेने के लिए आप मजबूर करता है धारावाहिकरण के माध्यम से इसे क्या करेगा या नहीं करेगा। यह JSON.net पर निर्भरता के बिना, आपके मॉडल वर्गों को स्वयं एक प्रोजेक्ट में रहने की इजाजत देता है क्योंकि कहीं और आप उन्हें JSON.net के साथ क्रमबद्ध करने के लिए होते हैं।

+1

विरासत वाले सदस्यों को छिपाने के लिए नेट कोर के साथ बॉक्स से बाहर काम करने वाला एकमात्र दृष्टिकोण। एक्सएमएल और जेसन सीरियलाइजेशन दोनों के लिए काम करता है। Kudos – Piou

+0

मुझे एक ही funcionality की आवश्यकता है लेकिन गुणों को शामिल या बहिष्कृत किया जाता है इस पर निर्भर करता है कि कौन सी एपीआई विधि लागू की गई है यानी विभिन्न एपीआई कॉल के लिए अलग-अलग डेटा की आवश्यकता है। कोई सुझाव –

18

यह मेरे लिए काम करता है: एक कस्टम अनुबंध रिज़ॉल्वर बनाएं जिसमें एक सार्वजनिक संपत्ति है जिसे स्ट्रिंग सरणी प्रकार की AllowList कहा जाता है। अपनी कार्रवाई में, कार्रवाई को वापस करने की आवश्यकता के आधार पर उस संपत्ति को संशोधित करें।

1। एक कस्टम अनुबंध समाधानकर्ता बनाएँ: कार्रवाई में

public class PublicDomainJsonContractResolverOptIn : DefaultContractResolver 
{ 
    public string[] AllowList { get; set; } 

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization); 

     properties = properties.Where(p => AllowList.Contains(p.PropertyName)).ToList(); 
     return properties; 
    } 
} 

2. उपयोग कस्टम अनुबंध समाधानकर्ता

[HttpGet] 
public BinaryImage Single(int key) 
{ 
    //limit properties that are sent on wire for this request specifically 
    var contractResolver = Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver as PublicDomainJsonContractResolverOptIn; 
    if (contractResolver != null) 
     contractResolver.AllowList = new string[] { "Id", "Bytes", "MimeType", "Width", "Height" }; 

    BinaryImage image = new BinaryImage { Id = 1 }; 
    //etc. etc. 
    return image; 
} 

यह दृष्टिकोण मुझे अनुमति देते हैं/वर्ग परिभाषा को संशोधित करने के बजाय विशेष अनुरोध के लिए अनुमति नहीं देने की अनुमति दी। और यदि आपको एक्सएमएल क्रमिकरण की आवश्यकता नहीं है, तो इसे अपने App_Start\WebApiConfig.cs में बंद करना न भूलें या यदि आपका ग्राहक जेसन के बजाय xml अनुरोध करता है तो आपका एपीआई अवरुद्ध गुण वापस कर देगा।

//remove xml serialization 
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"); 
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType); 
+0

कुछ नए संस्करणों के साथ बदलना चाहिए लेकिन मैं इसे काम करने में असमर्थ था। मैं इसे हल करने वाले को संशोधित करते समय 'as' के बजाय 'नया' करके काम करने के लिए प्राप्त कर सकता हूं। JsonContractResolver प्रकार किसी कारण से संगत नहीं है। नया करने का मुद्दा यह है कि यह सिर्फ एक के बजाय इसे सभी के लिए ओवरराइट करता है। वर jsonMediaTypeFormatter = नए JsonMediaTypeFormatter { SerializerSettings = नए JsonSerializerSettings { ContractResolver = नए PublicDomainJsonContractResolverOptIn {AllowList = नया स्ट्रिंग [: –

+0

मैं Request.CreateResponse() विधि है कि एक MediaTypeFormatter प्राप्त करता है, इस तरह का उपयोग करके यह काम कर पाने में कामयाब रहे ] {"आईडी", "बाइट्स", "माइम टाइप", "चौड़ाई", "ऊंचाई"}} } }; वापसी अनुरोध। क्रेट रेस्पॉन्स (HttpStatusCode.OK, छवि, jsonMediaTypeFormatter); – Paul

+0

क्या होगा यदि हम चाहते हैं कि अवरुद्ध गुणों को XML प्रतिक्रिया में अनदेखा किया जाए? –

12

मैं खेल के लिए देर हो रही है, लेकिन एक गुमनाम वस्तुओं चाल करना होगा:

[HttpGet] 
public HttpResponseMessage Me(string hash) 
{ 
    HttpResponseMessage httpResponseMessage; 
    List<Something> somethings = ... 

    var returnObjects = somethings.Select(x => new { 
     Id = x.Id, 
     OtherField = x.OtherField 
    }); 

    httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK, 
           new { result = true, somethings = returnObjects }); 

    return httpResponseMessage; 
} 
6

मैं तुम्हें पूरा करने के लिए 2 तरीके दिखाएगा IgnoreDataMember संपत्ति

public class Foo 
    { 
     [IgnoreDataMember] 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 
10

उपयोग करने का प्रयास आप क्या चाहते हैं:

पहला तरीका: जेसनप्रो के साथ अपना क्षेत्र सजाने उस क्षेत्र के क्रमबद्धीकरण को छोड़ने के लिए perty विशेषता अगर यह शून्य है।

public class Foo 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] 
    public List<Something> Somethings { get; set; } 
} 

दूसरा तरीका: क्या आप कुछ जटिल परिस्थितियां के साथ बातचीत कर रहे हैं तो आप क्रम में वेब एपीआई सम्मेलन ("ShouldSerialize") इस्तेमाल कर सकते हैं कि क्षेत्र में कुछ विशिष्ट तर्क के आधार पर की क्रमबद्धता को छोड़ने के लिए।

public class Foo 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 

    public List<Something> Somethings { get; set; } 

    public bool ShouldSerializeSomethings() { 
     var resultOfSomeLogic = false; 
     return resultOfSomeLogic; 
    } 
} 

WebAPI JSON.Net का उपयोग करता है और यह क्रमबद्धता को इसलिए जब यह पता चला है (उदाहरण के लिए) ShouldSerializeFieldX() विधि नाम FieldX के साथ मैदान धारावाहिक नहीं की जाएगी प्रतिबिंब का उपयोग करें।

+0

यह वेब एपीआई द्वारा नहीं किया गया है, वेब एपीआई क्रमशः जेएसएन.नेट का उपयोग क्रमबद्ध करने के लिए करता है। यह प्रक्रिया जेसन.NET द्वारा वेब एपीआई द्वारा नहीं की जाती है – dotctor

0

किसी कारण से [IgnoreDataMember] हमेशा मेरे लिए काम नहीं करता है, और मुझे कभी-कभी StackOverflowException (या इसी तरह) मिलता है। तो बजाय (या अतिरिक्त) मैं एक पैटर्न कुछ इस तरह लग रही का उपयोग शुरू किया जब POST मेरी एपीआई के Objects में ing:

[Route("api/myroute")] 
[AcceptVerbs("POST")] 
public IHttpActionResult PostMyObject(JObject myObject) 
{ 
    MyObject myObjectConverted = myObject.ToObject<MyObject>(); 

    //Do some stuff with the object 

    return Ok(myObjectConverted); 
} 

तो बुनियादी तौर पर मैं एक JObject में गुजरती हैं और परिवर्तित करने के बाद यह करने के लिए प्राप्त किया गया है अंतर्निहित धारावाहिक के कारण होने वाली एविड समस्याएं जो कभी-कभी वस्तुओं को पार्स करते समय अनंत लूप का कारण बनती हैं।

अगर किसी को कोई कारण पता है कि यह किसी भी तरह से एक बुरा विचार है, तो कृपया मुझे बताएं।

यह ध्यान देने योग्य है कि यह एक EntityFramework कक्षा-संपत्ति है कि समस्या का कारण बनता है (दो वर्गों प्रत्येक-दूसरे को संदर्भित करते हैं) के लिए निम्न कोड है लायक हो सकता है:

[Serializable] 
public partial class MyObject 
{ 
    [IgnoreDataMember] 
    public MyOtherObject MyOtherObject => MyOtherObject.GetById(MyOtherObjectId); 
} 

[Serializable] 
public partial class MyOtherObject 
{ 
    [IgnoreDataMember] 
    public List<MyObject> MyObjects => MyObject.GetByMyOtherObjectId(Id); 
} 
4

लगभग greatbear302 के जवाब के रूप में ही है, लेकिन मैं प्रति अनुरोध अनुबंधResolver बनाते हैं।

1) एक कस्टम ContractResolver

public class MyJsonContractResolver : DefaultContractResolver 
{ 
    public List<Tuple<string, string>> ExcludeProperties { get; set; } 

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 

     if (ExcludeProperties?.FirstOrDefault(
      s => s.Item2 == member.Name && s.Item1 == member.DeclaringType.Name) != null) 
     { 
      property.ShouldSerialize = instance => { return false; }; 
     } 

     return property; 
    } 
} 

2 बनाएं) कार्रवाई में कस्टम अनुबंध समाधानकर्ता का उपयोग करें

public async Task<IActionResult> Sites() 
{ 
    var items = await db.Sites.GetManyAsync(); 

    return Json(items.ToList(), new JsonSerializerSettings 
    { 
     ContractResolver = new MyJsonContractResolver() 
     { 
      ExcludeProperties = new List<Tuple<string, string>> 
      { 
       Tuple.Create("Site", "Name"), 
       Tuple.Create("<TypeName>", "<MemberName>"), 
      } 
     } 
    }); 
} 

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

यह रूप में (समाधानकर्ता को अलग की उम्मीद काम नहीं किया अनुरोध के अनुसार)। मैं अज्ञात वस्तुओं का उपयोग करूंगा।

public async Task<IActionResult> Sites() 
{ 
    var items = await db.Sites.GetManyAsync(); 

    return Json(items.Select(s => new 
    { 
     s.ID, 
     s.DisplayName, 
     s.Url, 
     UrlAlias = s.Url, 
     NestedItems = s.NestedItems.Select(ni => new 
     { 
      ni.Name, 
      ni.OrdeIndex, 
      ni.Enabled, 
     }), 
    })); 
} 
संबंधित मुद्दे