Remove xml namespaces from WCF restful response

前端 未结 9 1656
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-05 11:13

I am using WCF to return a plain old XML (POX) document to the caller. I am using the XML Serializer formatter to turn the objects into XML.

In the returned docum

9条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-05 11:22

    I found a good solution to this issue which lets you inject your own XmlSerializer into WCF that is used when serializing and deserializing requests. This XmlSerializer can be set up to omit XML namespaces entirely (including xmlns:i="w3.org/2001/XMLSchema-instance") or any other way you desire.

    My solution utilizes WcfRestContrib. You could almost use the included POX formatter but in our case we wanted to support attributes so we wrote our own simple formatter.

    Instructions:

    1) Reference WcfRestContrib from your project.

    2) Create an IWebFormatter implementation:

    public class NamespacelessXmlFormatter : IWebFormatter {
        public object Deserialize(WebFormatterDeserializationContext context, Type type) {
            if (context.ContentFormat != WebFormatterDeserializationContext.DeserializationFormat.Xml) {
                throw new InvalidDataException("Data must be in xml format.");
            }
    
            return NamespacelessXmlSerializer.Deserialize(context.XmlReader, type);
        }
    
        public WebFormatterSerializationContext Serialize(object data, Type type) {
            using (var stream = NamespacelessXmlSerializer.Serialize(data, type)) {
                using (var binaryReader = new BinaryReader(stream)) {
                    byte[] bytes = binaryReader.ReadBytes((int)stream.Length);
                    return WebFormatterSerializationContext.CreateBinary(bytes);
                }
            }
        }
    }
    

    Which utilizes an XmlSerializer that fits your needs (here's ours which simply omits all namespaces):

    public static class NamespacelessXmlSerializer {
    
        private static readonly XmlSerializerNamespaces _customNamespace = new XmlSerializerNamespaces();
    
        private static readonly XmlWriterSettings _xmlSettings = new XmlWriterSettings {
            OmitXmlDeclaration = true
        };
    
        static NamespacelessXmlSerializer() {
            // to make sure .NET serializer doesn't add namespaces
            _customNamespace.Add(String.Empty, String.Empty);
        }
    
        /// 
        /// Deserializes object from its XML representation.
        /// 
        /// 
        /// 
        /// 
        public static T Deserialize(Stream stream) {
            return (T)Deserialize(stream, typeof(T));
        }
    
        /// 
        /// Deserializes object from its XML representation.
        /// 
        public static object Deserialize(Stream stream, Type type) {
            var ds = new XmlSerializer(type);
            var d = ds.Deserialize(stream);
            return d;
        }
    
        public static object Deserialize(XmlDictionaryReader xmlReader, Type type) {
            var ds = new XmlSerializer(type);
            var d = ds.Deserialize(xmlReader);
            return d;
        }
    
        /// 
        /// Serializes object to XML representation.
        /// 
        /// 
        /// Is thrown when there was an error generating XML document. This can happen 
        /// for example if the object has string with invalid XML characters:
        /// http://www.w3.org/TR/2004/REC-xml-20040204/#charsets.
        /// See this article for other potential issues:
        /// http://msdn.microsoft.com/en-us/library/aa302290.aspx
        /// 
        public static Stream Serialize(T objectToSerialize) {
            return Serialize(objectToSerialize, typeof(T));
        }
    
        /// 
        /// Serializes object to XML representation.
        /// 
        /// 
        /// Is thrown when there was an error generating XML document. This can happen 
        /// for example if the object has string with invalid XML characters:
        /// http://www.w3.org/TR/2004/REC-xml-20040204/#charsets.
        /// See this article for other potential issues:
        /// http://msdn.microsoft.com/en-us/library/aa302290.aspx
        /// 
        public static Stream Serialize(object objectToSerialize, Type type) {
            var stream = new MemoryStream();
    
            XmlWriter writer = XmlWriter.Create(stream, _xmlSettings);
            var x = new XmlSerializer(type);
            x.Serialize(writer, objectToSerialize, _customNamespace);
    
            stream.Position = 0;
    
            return stream;
        }
    }
    

    3) Apply the WebDispatchFormatter... attributes to your service using your custom implementation as the type (based on this documentation):

    [WebDispatchFormatterConfiguration("application/xml")]
    [WebDispatchFormatterMimeType(typeof(NamespacelessXmlFormatter), "application/xml")]
    

    4) Apply the WebDispatchFormatter attribute to all of your service methods (based on this documentation).

    5) That's it. Test your service and confirm it now behaves as expected.

提交回复
热议问题