2012-09-25 18 views
31

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

config.Formatters.XmlFormatter.UseXmlSerializer = true; 

विकल्प 2

[DataContract(Namespace="")] 

(और यदि आप ऐसा करते हैं, आप चाहते के साथ अपने मॉडल को सजाने के लिए है:

<ApiDivisionsResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/GrassrootsHoops.Models.Api.Response"> 
<Divisions xmlns:d2p1="http://schemas.datacontract.org/2004/07/GrassrootsHoops.Data.Entities"> 
<d2p1:Page>1</d2p1:Page> 
<d2p1:PageSize>10</d2p1:PageSize> 
<d2p1:Results xmlns:d3p1="http://schemas.datacontract.org/2004/07/GrassrootsHoops.Models.Api.Response.Divisions"/> 
<d2p1:Total>0</d2p1:Total> 
</Divisions> 
</ApiDivisionsResponse> 
+0

काम करता है आप कुछ इस तरह की कोशिश कर सकते: http: // stackoverflow।कॉम/प्रश्न/2 9 352015/कैसे-कर-आई-निर्माण-कस्टम-एक्सएमएल-नेमस्पेस-विशेषताएं-कब-उपभोग-ए-विरासत-साबुन-से –

उत्तर

37

विकल्प 1 का उपयोग कर GlobalConfiguration में XmlSerializer करने के लिए स्विच करने के लिए है [DataMember] विशेषताओं वाले सदस्यों को सजाने की आवश्यकता है)।

+2

मैंने UseXmlSerializer किया था और अब यह केवल JSON का उपयोग करता है। –

+4

'[DataContract()] 'विशेषता के लिए [' System.Runtime.Serialization'] (http://msdn.microsoft.com/en-us/library/kd1dc9w5.aspx) के संदर्भ की आवश्यकता है लाइब्रेरी – Andrew

+0

@MikeFlynn I ran एक ही मुद्दे में। यदि XmlSerializer ऑब्जेक्ट को क्रमबद्ध नहीं कर सकता है तो यह इसके बजाय जेसन को आजमाएगा। वास्तव में एक अपेक्षित डिफ़ॉल्ट व्यवहार आईएमओ नहीं है। विशेष रूप से जब NetDataContractSerializer त्रुटियों को फेंकता है। – CDeutsch

20

यदि आप XmlRoot के साथ अपने मॉडल को सजाने के इच्छुक हैं, तो यह करने का एक अच्छा तरीका है। मान लीजिए कि आपके पास दरवाजे के साथ एक कार है। डिफ़ॉल्ट WebAPI विन्यास की तरह कुछ वापस आ जाएगी:

<car> 
    <doors> 
     <door> 
      <color>black</color> 
     </door> 
    </doors> 
</car> 

यहाँ मॉडल है:

<car 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <doors> 
     <door> 
      <color>black</color> 
     </door> 
    </doors> 
</car> 

यह तुम क्या चाहते है

[XmlRoot("car")] 
public class Car 
{ 
    [XmlArray("doors"), XmlArrayItem("door")] 
    public Door[] Doors { get; set; } 
} 

आप क्या करना है एक कस्टम XmlFormatter बनाने है XmlRoot विशेषता में परिभाषित कोई नामस्थान नहीं होने पर उसमें एक खाली नामस्थान होगा। किसी कारण से, डिफ़ॉल्ट स्वरूपक हमेशा दो डिफ़ॉल्ट नामस्थान जोड़ता है।

public class CustomNamespaceXmlFormatter : XmlMediaTypeFormatter 
{ 
    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, 
              TransportContext transportContext) 
    { 
     try 
     { 
      var xns = new XmlSerializerNamespaces(); 
      foreach (var attribute in type.GetCustomAttributes(true)) 
      { 
       var xmlRootAttribute = attribute as XmlRootAttribute; 
       if (xmlRootAttribute != null) 
       { 
        xns.Add(string.Empty, xmlRootAttribute.Namespace); 
       } 
      } 

      if (xns.Count == 0) 
      { 
       xns.Add(string.Empty, string.Empty); 
      } 

      var task = Task.Factory.StartNew(() => 
       { 
        var serializer = new XmlSerializer(type); 
        serializer.Serialize(writeStream, value, xns); 
       }); 

      return task; 
     } 
     catch (Exception) 
     { 
      return base.WriteToStreamAsync(type, value, writeStream, content, transportContext); 
     } 
    } 
} 

करने के लिए आखिरी बात WebApiContext में नया फॉर्मेटर जोड़ना है। पुरानी XmlMediaTypeFormatter

public static class WebApiContext 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     ... 
     config.Formatters.Clear(); 
     config.Formatters.Add(new CustomNamespaceXmlFormatter{UseXmlSerializer=true}); 
     ... 
    } 
} 
+0

हाय, मुझे आपका समाधान पसंद है, हालांकि मुझे अपवाद होने पर बेस कार्यान्वयन को कॉल करने में बिंदु नहीं मिलता है। क्या आप समझा सकते हैं कि आपने ऐसा क्यों किया है? धन्यवाद। –

+0

दुर्भाग्य से, यह थोड़ी देर हो गया है क्योंकि मैंने इस पर हैक किया है। मुझे जो याद है, मुझे लगता है कि यह एक्सएमएल नेमस्पेस को हटाने और बस "सामान्य" फॉर्मेटर को कॉल करने के तरीके के रूप में था। – pobed2

+3

महान काम। लेकिन, सावधानी का एक शब्द: 'config.Formatters.Add (नया IgnoreNamespacesXmlMediaTypeFormatter {UseXmlSerializer = true}); 'POST' डेटा भेजते समय अन्यथा सेट किया जाना चाहिए,' FromBody 'इसे' serialize' करने में सक्षम नहीं होगा। –

5

मुझे pobed2 के उत्तर को पसंद करना सुनिश्चित करें (या साफ़) सुनिश्चित करें। लेकिन मुझे CustomNamespaceXmlFormatter की आवश्यकता होती है ताकि मुझे XmlRoot विशेषता और अनुपलब्ध होने पर भी अनुपलब्ध रूट नामस्थान निर्दिष्ट करने की अनुमति दे और Namespace संपत्ति में कोई मूल्य नहीं है (यानी, विशेषता का उपयोग करने के लिए विशेषता का उपयोग किया जाता है रूट तत्व नाम केवल)। तो मैं एक उन्नत संस्करण बनाया है, यहाँ यह है के मामले में यह उपयोगी किसी के लिए है:

public class CustomNamespaceXmlFormatter : XmlMediaTypeFormatter 
{ 
    private readonly string defaultRootNamespace; 

    public CustomNamespaceXmlFormatter() : this(string.Empty) 
    { 
    } 

    public CustomNamespaceXmlFormatter(string defaultRootNamespace) 
    { 
     this.defaultRootNamespace = defaultRootNamespace; 
    } 

    public override Task WriteToStreamAsync(
     Type type, 
     object value, 
     Stream writeStream, 
     HttpContent content, 
     TransportContext transportContext) 
    { 
     var xmlRootAttribute = type.GetCustomAttribute<XmlRootAttribute>(true); 
     if(xmlRootAttribute == null) 
      xmlRootAttribute = new XmlRootAttribute(type.Name) 
      { 
       Namespace = defaultRootNamespace 
      }; 
     else if(xmlRootAttribute.Namespace == null) 
      xmlRootAttribute = new XmlRootAttribute(xmlRootAttribute.ElementName) 
      { 
       Namespace = defaultRootNamespace 
      }; 

     var xns = new XmlSerializerNamespaces(); 
     xns.Add(string.Empty, xmlRootAttribute.Namespace); 

     return Task.Factory.StartNew(() => 
     { 
      var serializer = new XmlSerializer(type, xmlRootAttribute); 
      serializer.Serialize(writeStream, value, xns); 
     }); 
    } 
} 
+0

जैसा कि गंभीर स्मृति रिसाव से बचने के लिए [इस उत्तर] में सूचीबद्ध है [https://stackoverflow.com/a/23897411/3744182), एक गैर-डिफ़ॉल्ट कन्स्ट्रक्टर के साथ निर्मित 'XmlSerializer' को स्थिर रूप से कैश किया गया और पुन: उपयोग किया जाना चाहिए। यह भी देखें [डॉक्स] (https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer.aspx#Remarks) जो राज्य * यदि आप किसी भी अन्य रचनाकारों का उपयोग करते हैं, तो कई संस्करण एक ही असेंबली उत्पन्न होती है और कभी भी अनलोड नहीं होती है, जिसके परिणामस्वरूप स्मृति रिसाव और खराब प्रदर्शन होता है। ... अन्यथा, आपको हैशटेबल में असेंबली को कैश करना होगा, * – dbc

3

परियोजना है कि रहता प्रतिक्रिया मॉडल Properties/AssemblyInfo.cs

करने के लिए जाने जोड़े

using System.Runtime.Serialization;

और पर में नीचे

[assembly: ContractNamespace("", ClrNamespace = "Project.YourResponseModels")] 

वास्तविक नामस्थान के साथ Project.YourResponseModels बदलें जहां प्रतिक्रिया मॉडल स्थित हैं। आप नाम स्थान

+0

हैलो, कामकाज की तरह दिखता है और इसे खराब अभ्यास के रूप में माना जाना चाहिए। उदाहरण के लिए, मेरे 'YourResponseModels' को रीफैक्टर करने वाली प्रोजेक्ट संरचना के मामले में 'Project.YourResponseModels' नेमस्पेस से' Project.AnotherPlace.YourResponseModels' में स्थानांतरित किया जा सकता है। किसी भी रिफैक्टरिंग के मामले में सभी को इसे ध्यान में रखना चाहिए। –

+0

वेब एपीआई उद्देश्य के लिए एक्सएमएल निकायों को साफ करने के लिए यह पुराना दृष्टिकोण था, इसलिए जब आप रिफैक्टर करते हैं तो इससे कोई फर्क नहीं पड़ता, कोड और इकाइयां आपकी इच्छानुसार संरचित होती हैं, केवल सीरिएलाइज़र कुछ भी संभाल लेता है। पुनर्गठन के लिए मुझे नहीं लगता कि AssemblyInfo.cs में 10-20 से अधिक लाइनें होंगी, अभी भी बनाए रखना आसान है। वैसे भी एक्सएमएल का उपयोग किस दिन करेंगे? वेबएपीआई 2.0+ के साथ यह सब हल हो गया है, और जेएसओएन आधुनिक एपीएस के लिए एकमात्र प्रारूप होना चाहिए। यदि आप पुराने सिस्टम के साथ इंटरफेस करते हैं, तो आप एक्सएमएल नेमस्पेस को वैसे भी रख सकते हैं। –

-2

प्रति एक जोड़ने की जरूरत है यह पूरी तरह से

public ActionResult JsonAction(string xxx) 
{ 
    XmlDocument xmlDoc2 = new XmlDocument(); 
    xmlDoc2.Load(xmlStreamReader); 

    XDocument d = XDocument.Parse(optdoc2.InnerXml); 
    d.Root.Attributes().Where(x => x.IsNamespaceDeclaration).Remove(); 

    foreach (var elem in d.Descendants()) 
    elem.Name = elem.Name.LocalName; 

    var xmlDocument = new XmlDocument(); 
    xmlDocument.Load(d.CreateReader()); 

    var jsonText = JsonConvert.SerializeXmlNode(xmlDocument); 
    return Content(jsonText); 
} 
संबंधित मुद्दे