К сожалению, я не смог найти отличное решение для этого. Я, однако, нашел работоспособное решение.
Предупреждение. Если это возможно, попытайтесь изменить WSDL, чтобы избежать необходимости в этом решении. Это скорее взлом, чем предлагаемое решение, но оно будет работать в крайнем случае.
Решением было реализовать IClientMessageInspector и IEndpointBehavior. Эти интерфейсы позволяют получить доступ к необработанному текстовому запросу и ответу. Это позволило модифицировать сообщения до того, как они будут отправлены в службу или десериализованы WCF. Ниже моя Реализация и пользовательский класс, который позволил мне внести изменения в сообщение.
public class MyService : IClientMessageInspector
{
public void DoWork()
{
// Do some stuff
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
string message = reply.ToString();
// Load the reply message in DOM for easier modification
XmlDocument doc = new XmlDocument();
doc.Load(reply.GetReaderAtBodyContents());
// Perform the modification
MessageHelper.FixArrays(doc);
// Create New Message
XmlNodeReader reader = new XmlNodeReader(doc.DocumentElement);
Message newMsg = Message.CreateMessage(reply.Version, reply.Headers.Action, reader);
// Preserve the headers of the original message
if (reply.Headers.Any())
newMsg.Headers.CopyHeaderFrom(reply, 0);
foreach (string propertyKey in reply.Properties.Keys)
{
newMsg.Properties.Add(propertyKey, reply.Properties[propertyKey]);
}
// Close the original message and return new message
reply.Close();
reply = newMsg;
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
return null;
}
}
public static class MessageHelper
{
public static void FixArrays(XmlDocument doc)
{
// Arrearage
WrapElement(doc, "foo", "arrayItem", "http://url.com/namespace/foo");
}
private static void WrapElement(XmlDocument doc, string elementName, string wrapperName, string nameSpace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);
var Nodes = doc.SelectNodes("//a:" + elementName, names);
if (Nodes.Count > 0)
{
var newBorrower = doc.CreateElement(Nodes.Item(0).Prefix, wrapperName, Nodes.Item(0).NamespaceURI);
foreach (XmlElement node in Nodes)
{
newBorrower.AppendChild(node.Clone());
}
Nodes.Item(0).ParentNode.ReplaceChild(newBorrower, Nodes.Item(0));
for (int i = 1; i <= Nodes.Count - 1; i++)
{
Nodes.Item(i).ParentNode.RemoveChild(Nodes.Item(i));
}
}
}
private static void WrapRenameElement(XmlDocument doc, string newName, string elementName, string wrapperName, string nameSpace, string newNamespace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);
names.AddNamespace("b", newNamespace);
var Nodes = doc.SelectNodes("//a:" + elementName + "/..", names);
foreach (XmlElement parent in Nodes)
{
var newBorrower = doc.CreateElement(parent.Prefix, wrapperName, parent.NamespaceURI);
foreach (XmlElement child in parent.ChildNodes)
{
if (child.LocalName == elementName)
{
var newNode = RenameNode(child.Clone(), newNamespace, newName);
parent.RemoveChild(child);
newBorrower.AppendChild(newNode);
}
}
if (newBorrower.ChildNodes.Count > 0)
parent.AppendChild(newBorrower);
}
}
private static void WrapRenameElement(XmlDocument doc, string newName, string elementName, string wrapperName, string nameSpace)
{
var names = new XmlNamespaceManager(doc.NameTable);
names.AddNamespace("a", nameSpace);
var Nodes = doc.SelectNodes("//a:" + elementName + "/..", names);
foreach (XmlElement parent in Nodes)
{
var newBorrower = doc.CreateElement(parent.Prefix, wrapperName, parent.NamespaceURI);
foreach (XmlElement child in parent.ChildNodes)
{
if (child.LocalName == elementName)
{
var newNode = RenameNode(child.Clone(), nameSpace, newName);
parent.RemoveChild(child);
newBorrower.AppendChild(newNode);
}
}
if (newBorrower.ChildNodes.Count > 0)
parent.AppendChild(newBorrower);
}
}
public static XmlNode RenameNode(XmlNode node, string namespaceURI, string qualifiedName)
{
if (node.NodeType == XmlNodeType.Element)
{
XmlElement oldElement = (XmlElement)node;
XmlElement newElement =
node.OwnerDocument.CreateElement(qualifiedName, namespaceURI);
while (oldElement.HasAttributes)
{
newElement.SetAttributeNode(oldElement.RemoveAttributeNode(oldElement.Attributes[0]));
}
while (oldElement.HasChildNodes)
{
newElement.AppendChild(oldElement.FirstChild);
}
if (oldElement.ParentNode != null)
{
oldElement.ParentNode.ReplaceChild(newElement, oldElement);
}
return newElement;
}
else
{
return null;
}
}
}
Как я уже сказал, это не красиво и по сути взломано, но это решение подойдет для моей проблемы. Я надеюсь, что никто не должен иметь дело с этим, но если они это сделают, я надеюсь, что это поможет.