Префикс пространства имен WCF ServiceHost не определен
Я принимаю SOAP ServiceHost, а клиент отправляет конкретное сообщение.
Служба отвечает на внутреннюю ошибку сервера 500, поскольку она не может декодировать сообщение SOAP. Причина вины:
Причина: "Ошибка десериализации тела сообщения запроса для операции GetStreamUri"
InnerException: "Префикс пространства имен " onv " не определен"
Чтобы проверить, что происходит, мы сравнили поступающие сообщения с теми, которые были проанализированы сервисным хостом.
Мы захватили сообщение с Wireshark:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:onv="http://www.onvif.org/ver10/schema"
xmlns:media="http://www.onvif.org/ver10/media/wsdl">
<SOAP-ENV:Header>
<!-- security stuff -->
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<media:GetStreamUri>
<media:StreamSetup xsi:type="onv:StreamSetup">
<onv:Stream>RTP-Unicast</onv:Stream>
<onv:Transport xsi:type="onv:Transport">
<onv:Protocol>UDP</onv:Protocol>
</onv:Transport>
</media:StreamSetup>
<media:ProfileToken>cs_videoProfileTK_000</media:ProfileToken>
</media:GetStreamUri>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
И мы захватили то, что сервисный хост получил с инспектором сообщений:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<!-- security stuff -->
</s:Header>
<s:Body>
<media:GetStreamUri xmlns:media="http://www.onvif.org/ver10/media/wsdl">
<media:StreamSetup xsi:type="onv:StreamSetup" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<onv:Stream xmlns:onv="http://www.onvif.org/ver10/schema">RTP-Unicast</onv:Stream>
<onv:Transport xsi:type="onv:Transport" xmlns:onv="http://www.onvif.org/ver10/schema">
<onv:Protocol>UDP</onv:Protocol>
</onv:Transport>
</media:StreamSetup>
<media:ProfileToken>cs_videoProfileTK_000</media:ProfileToken>
</media:GetStreamUri>
</s:Body>
</s:Envelope>
Как видите, анализатор пространства имен обнаруживает префикс onv и присваивает его
<onv:Stream xmlns:onv="http://www.onvif.org/ver10/schema">RTP-Unicast</onv:Stream>
но проблема в том, что пространство имен 'onv' определяется сразу после использования в атрибуте xsi: type
<media:StreamSetup xsi:type="onv:StreamSetup" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
Похоже, что XMLSerializer плохо справляется с использованием пространств имен, используемых в атрибутах. Есть ли какое-либо решение или обходной путь с использованием средств форматирования сообщений или инспекторов?
Редактировать сгенерированный код из WSDL.
// StreamSetup class
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.onvif.org/ver10/schema")]
public partial class StreamSetup : object, System.ComponentModel.INotifyPropertyChanged {
private StreamType streamField;
//ommited
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
public StreamType Stream {
get {
return this.streamField;
}
set {
this.streamField = value;
this.RaisePropertyChanged("Stream");
}
}
// ommited
}
// StreamType class
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.onvif.org/ver10/schema")]
public enum StreamType {
[System.Xml.Serialization.XmlEnumAttribute("RTP-Unicast")]
RTPUnicast,
// ommited
}
// Get Stream URI Method/Operation
[System.ServiceModel.OperationContractAttribute(Action="http://www.onvif.org/ver10/media/wsdl/GetStreamUri", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(ConfigurationEntity))]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(DeviceEntity))]
[return: System.ServiceModel.MessageParameterAttribute(Name="MediaUri")]
ONVIF.MediaUri GetStreamUri(ONVIF.StreamSetup StreamSetup, string ProfileToken);