在WCF输出中删除重复的xmlns声明
我有一个WCF服务,它可以以列表的形式接受和返回相当多的数据。我的问题是,典型行的输出如下所示:在WCF输出中删除重复的xmlns声明,wcf,namespaces,duplicates,xml-namespaces,Wcf,Namespaces,Duplicates,Xml Namespaces,我有一个WCF服务,它可以以列表的形式接受和返回相当多的数据。我的问题是,典型行的输出如下所示: <d:ArrayOfanyType> <d:anyType i:type="e:string" xmlns:e="http://www.w3.org/2001/XMLSchema">PJ123</d:anyType> <d:anyType i:type="e:double" xmlns:e="http://www.w3.org/2001
<d:ArrayOfanyType>
<d:anyType i:type="e:string" xmlns:e="http://www.w3.org/2001/XMLSchema">PJ123</d:anyType>
<d:anyType i:type="e:double" xmlns:e="http://www.w3.org/2001/XMLSchema">2</d:anyType>
<d:anyType i:type="e:string" xmlns:e="http://www.w3.org/2001/XMLSchema">216565</d:anyType>
<d:anyType i:type="e:dateTime" xmlns:e="http://www.w3.org/2001/XMLSchema">1993-09-10T00:00:00</d:anyType>
<d:anyType i:type="e:string" xmlns:e="http://www.w3.org/2001/XMLSchema">Timesheet W/E 11/9/93 Franklin</d:anyType>
<d:anyType i:type="e:string" xmlns:e="http://www.w3.org/2001/XMLSchema">CONSULT OF</d:anyType>
<d:anyType i:type="e:double" xmlns:e="http://www.w3.org/2001/XMLSchema">25</d:anyType>
<d:anyType i:type="e:double" xmlns:e="http://www.w3.org/2001/XMLSchema">0</d:anyType>
<d:anyType i:type="e:double" xmlns:e="http://www.w3.org/2001/XMLSchema">25</d:anyType>
</d:ArrayOfanyType>
PJ123
2.
216565
1993-09-10T00:00:00
时间表W/E 11/9/93富兰克林
咨询
25
0
25
因此,每行中的每个值都定义了“e”名称空间,这大大增加了消息的大小。我知道这背后的原因是,DataContractSerializer不必进行两次传递,但似乎很难以更大的消息大小为代价获得一点处理性能。我曾想过如何更改数据结构,但字段实际上可以是任何内容,我无法避免使用
元素
有人知道截取WCF管道并删除/重新组织这些名称空间声明的方法吗 您可以使用一个自定义编码器来实现这一点——在这一点上,您可以随心所欲地使用XML。正如约翰·桑德斯所指出的,这将导致(可能是重大的)性能损失,但它确实有效。下面的代码显示了如何处理它
public class StackOverflow_6681219
{
[ServiceContract]
public interface ITest
{
[OperationContract]
List<List<object>> GetData();
}
public class Service : ITest
{
public List<List<object>> GetData()
{
return new List<List<object>>
{
new List<object>
{
"PJ123",
2.0,
"216565",
new DateTime(1993, 9, 10),
"Timesheet W/E 11/9/93 Franklin",
"CONSULT OF",
25.0,
0.0,
25.0
}
};
}
}
class MyEncodingBindingElement : MessageEncodingBindingElement
{
MessageEncodingBindingElement inner;
public MyEncodingBindingElement(MessageEncodingBindingElement inner)
{
this.inner = inner;
}
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new MyEncoderFactory(this.inner.CreateMessageEncoderFactory());
}
public override MessageVersion MessageVersion
{
get { return this.inner.MessageVersion; }
set { this.inner.MessageVersion = value; }
}
public override BindingElement Clone()
{
return new MyEncodingBindingElement(this.inner);
}
public override bool CanBuildChannelListener<TChannel>(BindingContext context)
{
return context.CanBuildInnerChannelListener<TChannel>();
}
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
context.BindingParameters.Add(this);
return context.BuildInnerChannelListener<TChannel>();
}
class MyEncoderFactory : MessageEncoderFactory
{
MessageEncoderFactory inner;
public MyEncoderFactory(MessageEncoderFactory inner)
{
this.inner = inner;
}
public override MessageEncoder Encoder
{
get { return new MyEncoder(this.inner.Encoder); }
}
public override MessageVersion MessageVersion
{
get { return this.inner.MessageVersion; }
}
}
class MyEncoder : MessageEncoder
{
MessageEncoder inner;
public MyEncoder(MessageEncoder inner)
{
this.inner = inner;
}
public override string ContentType
{
get { return this.inner.ContentType; }
}
public override string MediaType
{
get { return this.inner.MediaType; }
}
public override bool IsContentTypeSupported(string contentType)
{
return this.inner.IsContentTypeSupported(contentType);
}
public override MessageVersion MessageVersion
{
get { return this.inner.MessageVersion; }
}
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
return this.inner.ReadMessage(buffer, bufferManager, contentType);
}
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
{
throw new NotImplementedException();
}
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
{
const string XmlnsNamespace = "http://www.w3.org/2000/xmlns/";
const string SchemaNamespace = "http://www.w3.org/2001/XMLSchema";
const string ArraysNamespace = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
const string SchemaInstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";
ArraySegment<byte> temp = this.inner.WriteMessage(message, maxMessageSize, bufferManager, messageOffset);
MemoryStream ms = new MemoryStream(temp.Array, temp.Offset, temp.Count);
XmlDocument doc = new XmlDocument();
doc.Load(ms);
bufferManager.ReturnBuffer(temp.Array);
XmlAttribute rootAttr = doc.CreateAttribute("xmlns", "sch", XmlnsNamespace);
rootAttr.Value = SchemaNamespace;
doc.DocumentElement.Attributes.Append(rootAttr);
XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
nsManager.AddNamespace("arrays", ArraysNamespace);
foreach (XmlNode arrayItem in doc.SelectNodes("//arrays:anyType", nsManager))
{
XmlAttribute toRemove = null;
XmlAttribute typeAttr = null;
foreach (XmlAttribute attr in arrayItem.Attributes)
{
if (attr.Prefix == "xmlns" && attr.Value == SchemaNamespace)
{
toRemove = attr;
}
else if (attr.LocalName == "type" && attr.NamespaceURI == SchemaInstanceNamespace)
{
typeAttr = attr;
}
}
if (toRemove != null)
{
arrayItem.Attributes.Remove(toRemove);
if (typeAttr != null)
{
string prefix = toRemove.LocalName;
typeAttr.Value = typeAttr.Value.Replace(prefix + ":", "sch:");
}
}
}
ms = new MemoryStream();
doc.Save(ms);
byte[] buffer = bufferManager.TakeBuffer((int)ms.Length + messageOffset);
Array.Copy(ms.GetBuffer(), 0, buffer, messageOffset, (int)ms.Length);
return new ArraySegment<byte>(buffer, messageOffset, (int)ms.Length);
}
public override void WriteMessage(Message message, Stream stream)
{
throw new NotImplementedException();
}
}
}
static Binding ReplaceEncoding(Binding original)
{
CustomBinding custom = new CustomBinding(original);
for (int i = 0; i < custom.Elements.Count; i++)
{
MessageEncodingBindingElement mebe = custom.Elements[i] as MessageEncodingBindingElement;
if (mebe != null)
{
custom.Elements[i] = new MyEncodingBindingElement(mebe);
break;
}
}
return custom;
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
Binding binding = ReplaceEncoding(new BasicHttpBinding());
host.AddServiceEndpoint(typeof(ITest), binding, "");
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine(proxy.GetData());
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
公共类StackOverflow_6681219
{
[服务合同]
公共接口测试
{
[经营合同]
List GetData();
}
公共类服务:ITest
{
公共列表GetData()
{
返回新列表
{
新名单
{
“PJ123”,
2.0,
"216565",
新日期时间(1993年9月10日),
“时间表W/E 11/9/93 Franklin”,
“咨询”,
25.0,
0.0,
25
}
};
}
}
类MyEncodingBindingElement:MessageEncodingBindingElement
{
MessageEncodingBindingElement内部;
公共MyEncodingBindingElement(MessageEncodingBindingElement内部)
{
this.inner=内部;
}
公共重写MessageEncoderFactory CreateMessageEncoderFactory()
{
返回新的MyEncoderFactory(this.inner.CreateMessageEncoderFactory());
}
公共覆盖消息版本消息版本
{
获取{返回this.inner.MessageVersion;}
设置{this.inner.MessageVersion=value;}
}
公共重写BindingElement克隆()
{
返回新的MyEncodingBindingElement(this.internal);
}
公共覆盖布尔CanBuildChannelListener(BindingContext上下文)
{
返回context.CanBuildInnerChannelListener();
}
公共覆盖IChannelListener BuildChannelListener(BindingContext上下文)
{
context.BindingParameters.Add(此);
返回context.BuildInnerChannelListener();
}
类MyEncoderFactory:MessageEncoderFactory
{
信息编码工厂内部;
公共MyEncoderFactory(MessageEncoderFactory内部)
{
this.inner=内部;
}
公共覆盖消息编码器
{
获取{返回新的MyEncoder(this.internal.Encoder);}
}
公共覆盖消息版本消息版本
{
获取{返回this.inner.MessageVersion;}
}
}
类MyEncoder:MessageEncoder
{
信息编码器内部;
公共MyEncoder(MessageEncoder内部)
{
this.inner=内部;
}
公共重写字符串ContentType
{
获取{返回this.inner.ContentType;}
}
公共重写字符串MediaType
{
获取{返回this.internal.MediaType;}
}
支持公共覆盖布尔IsContentTypeSupported(字符串contentType)
{
返回此.inner.IsContentTypeSupported(contentType);
}
公共覆盖消息版本消息版本
{
获取{返回this.inner.MessageVersion;}
}
公共重写消息ReadMessage(ArraySegment buffer、BufferManager、BufferManager、string contentType)
{
返回this.internal.ReadMessage(buffer、bufferManager、contentType);
}
公共重写消息ReadMessage(Stream、int-maxSizeOfHeaders、string-contentType)
{
抛出新的NotImplementedException();
}
公共重写ArraySegment WriteMessage(消息消息消息、int-maxMessageSize、BufferManager-BufferManager、int-messageOffset)
{
常量字符串XmlnsNamespace=”http://www.w3.org/2000/xmlns/";
常量字符串SchemaNamespace=”http://www.w3.org/2001/XMLSchema";
常量字符串ArraysNamespace=”http://schemas.microsoft.com/2003/10/Serialization/Arrays";
常量字符串SchemaInstanceNamespace=”http://www.w3.org/2001/XMLSchema-instance";
ArraySegment temp=this.internal.WriteMessage(message、maxMessageSize、bufferManager、messageOffset);
MemoryStream ms=新的MemoryStream(温度数组、温度偏移、温度计数);
XmlDocument doc=新的XmlDocument();
文件加载(毫秒);
bufferManager.ReturnBuffer(临时数组);
xmldattribute rootAttr=doc.CreateAttribute(“xmlns”,“sch”,xmlnsnespace);
rootAttr.Value=SchemaNamespace;
doc.DocumentElement.Attributes.Append(rootAttr);
XmlNamespaceManager nsManager=新的XmlNamespaceManager(doc.NameTable);
AddNamespace(“数组”,ArraysNamespace);
foreach(doc.SelectNode中的XmlNode数组项