У меня есть служба WCF, которая должна общаться с устаревшим клиентом WCF, который я не могу контролировать. Он вручную анализирует ответ службы, включая префиксы пространства имен в элементе root/elm1/elm2/ns1:elm3
. Ответ от службы не имеет ns1:elm3
, а просто elm3
, который клиент отклоняет как недействительный. Как я могу добавить его вручную перед отправкой ответа.
Я видел примеры того, как изменить ответ на сообщение SOAP с помощью метода IDispatchMessageInspector.BeforeSendReply()
. Вот мое SOAP сообщение в BeforeSendReply()
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<sendMessageResponse xmlns="http://mycompany.com/service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<sendMessageReturn>
<deliveredTimestamp>2/10/2020 10:25:27 PM</deliveredTimestamp>
<messageId>
<messageId>1581391525982</messageId>
<messageId>
<messageStatus>1</messageStatus>
<messageStatusDescription>Successfully received and acknowledged</messageStatusDescription>
<producedTimestamp>2/10/2020 10:25:10 PM</producedTimestamp>/>
</sendMessageReturn>
</sendMessageResponse>
</soapenv:Body>
</soapenv:Envelope>
Клиент ожидает SOAP сообщение, подобное этому:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<sendMessageResponse xmlns="http://mycompany.com/service">
<sendMessageReturn>
<ns1:deliveredTimestamp xmlns:ns1="http://mycompany.com/type">2020-02-11T06:07:48.088Z</ns1:deliveredTimestamp>
<ns2:messageId xmlns:ns2="http://mycompany.com/type">
<ns2:messageId>1581391525982</ns2:messageId>
</ns2:messageId>
<ns3:messageStatus xmlns:ns3="http://mycompany.com/type">1</ns3:messageStatus>
<ns4:messageStatusDescription xmlns:ns4="http://mycompany.com/type">Successfully received and acknowledged</ns4:messageStatusDescription>
<ns5:producedTimestamp xmlns:ns5="http://mycompany.com/type">2020-02-11T06:07:47.303Z</ns5:producedTimestamp>
</sendMessageReturn>
</sendMessageResponse>
</soapenv:Body>
</soapenv:Envelope>
У меня это в BeforeSendReply()
MessageBuffer msgbuf = reply.CreateBufferedCopy(int.MaxValue);
System.ServiceModel.Channels.Message tmpMessage = msgbuf.CreateMessage();
XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents();
XElement bodyEl = XElement.Load(xdr.ReadSubtree());
var deliveredTimestamp = bodyEl.Descendants().FirstOrDefault(b => b.Name.LocalName == "deliveredTimestamp");
Я могу получить атрибут namespace, например xmlns:ns1=http://company.com/type
, в deliveryTimestamp, но не могу получить префикс <ns1:deliveredTimestamp>...</ns1:deliveredTimestamp>
Спасибо за вашу помощь.
Обновление:
Мне удалось создать xml с правильными префиксами пространства имен, например так:
XElement root = new XElement(soapenv + "Envelop", new XAttribute(XNamespace.Xmlns + "soapenv", soapenv),
new XElement(soapenv + "Body",
new XElement("sendMessageResponse", new XAttribute(XNamespace.Xmlns + "i", svc),
new XElement("sendMessageReturn",
new XElement(type + "deliveredTimestamp", new XAttribute(XNamespace.Xmlns + "ns1", type)),
new XElement(type + "messagedId", new XAttribute(XNamespace.Xmlns + "ns2", type),
new XElement(type + "messageId")),
new XElement(type + "messageStatus", new XAttribute(XNamespace.Xmlns + "ns3", type)),
new XElement(type + "messageStatusDescription", new XAttribute(XNamespace.Xmlns + "ns4", type)),
new XElement(type + "producedTimestamp", new XAttribute(XNamespace.Xmlns + "ns5", type))
))));
Теперь у меня появилась другая проблема, когда createmessage () изменяет <soapenv:Envelope
на <s:Envelope
и клиенту это не нравится.
var newMessage = System.ServiceModel.Channels.Message.CreateMessage(reply.Version, null, xr);
newMessage.Headers.CopyHeadersFrom(reply);
newMessage.Properties.CopyProperties(reply.Properties);
reply = newMessage;
Кстати, код выше является копией другого SO сообщения кем-то.