我们有一个WCF设置,包含以下合同:
[ServiceContract(
Namespace = Constants.Namespaces.HL7Namespace,
Name = Constants.Roles.ContentRequiredDocumentManagementSystem)]
// XmlSerializerFormat is needed to expose the HL7 schema fields without the "Field" suffix on each one, eg: idField
[XmlSerializerFormat]
public interface ICDARequest
{
[OperationContract(
// wsdl request action
Action = Constants.Namespaces.HL7Namespace + ":" + Constants.Interactions.RCMR_IN000029UV01 + "." + Constants.VersionType.NormativeCode + Constants.Version.InteractionVersion,
// wsdl operation name
Name = Constants.Interactions.RCMR_IN000029UV01,
// wsdl response action
ReplyAction = Constants.Namespaces.HL7Namespace + ":" + Constants.Interactions.RCMR_IN000030UV01 + "." + Constants.VersionType.NormativeCode + Constants.Version.InteractionVersion)]
SearchMessagesResponse SearchMessages(SearchMessagesRequest RCMR_IN000029UV01);
[MessageContract(
IsWrapped = false]
public class SearchMessagesResponse
{
[MessageBodyMember(
Name = State.Constants.Interactions.RCMR_IN000030UV01,
Namespace = State.Constants.Namespaces.HL7Namespace)]
public RCMR_IN000030UV01 data;
}
}
xsd.exe
基于HL7v3架构生成的类。 它补充道:
[System.Xml.Serialization.XmlTypeAttribute(TypeName = "BCCDX.DistributionStatus", Namespace = "urn:bccdx.ca")]
public partial class BCCDXDistributionStatus
{
[System.Xml.Serialization.XmlElementAttribute("receivedTime", Namespace = "urn:bccdx.ca", IsNullable = false)]
public TS receivedTime{...}
}
这就是所期望的。
然后在WCF服务中,我们可以使用新的类和成员:
var distStatus = new BCCDXDistributionStatus();
distStatus.receivedTime = CreateTS(locStat.MessageDownloadDate);
然后将其序列化并通过线路发送,如下所示:
<distributionStatus xmlns="urn:bccdx.ca">
<receivedTime value="201702150956-0800"/>
</distributionStatus>
这几乎是正确的。遗憾的是,XML文档没有引用"urn:bccdx.ca"
命名空间。我假设它会在序列化时自动添加到文档根元素,但我错了。这就是最终的结果:
<RCMR_IN000030UV01 ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3">
...
</RCMR_IN000030UV01>
当真正需要的是:
<RCMR_IN000030UV01 ITSVersion="XML_1.0" xmlns="urn:hl7-org:v3" xmlns:x="urn:bccdx.ca">
...
</RCMR_IN000030UV01>
请注意urn:bccdx.ca,前缀为
我想知道,如果我们可以添加多个命名空间,那么如何通过合同为生成的序列化消息XML添加前缀?我在网上看到了覆盖默认序列化程序的提示,但我不愿意。当然这已经被考虑过并处理过了吗?
答案 0 :(得分:1)
首先,我假设您在服务合同的某个地方使用[XmlSerializerFormat]
指定使用XmlSerializer
,例如:
[ServiceContract()]
[XmlSerializerFormat]
public interface IService1
{
[OperationContract(
// wsdl request action
Action = Constants.Namespaces.HL7Namespace + ":" + Constants.Interactions.RCMR_IN000029UV01 + "." + Constants.VersionType.NormativeCode + Constants.Version.InteractionVersion,
// wsdl operation name
Name = Constants.Interactions.RCMR_IN000029UV01,
// wsdl response action
ReplyAction = Constants.Namespaces.HL7Namespace + ":" + Constants.Interactions.RCMR_IN000030UV01 + "." + Constants.VersionType.NormativeCode + Constants.Version.InteractionVersion)]
SearchMessagesResponse SearchMessages(/* SearchMessagesRequest RCMR_IN000029UV01*/);
}
虽然您的问题中未提及此问题,但如果您没有这样做,那么您的类型中的[System.Xml.Serialization.XmlElementAttribute(...)]
属性声明将无效,因为DataContractSerializer
会忽略它们。
其次,我将假设您的RCMR_IN000030UV01
类型目前看起来像这样:
[XmlRoot(ElementName = "RCMR_IN000030UV01", Namespace = "urn:hl7-org:v3")]
public partial class RCMR_IN000030UV01
{
// The initially auto-generated code
[XmlAttribute(AttributeName = "ITSVersion")]
public string ITSVersion { get; set; }
}
public partial class RCMR_IN000030UV01
{
// The added property
[System.Xml.Serialization.XmlElementAttribute("distributionStatus", Namespace = "urn:bccdx.ca", IsNullable = false)]
public BCCDXDistributionStatus distStatus { get; set; }
}
[System.Xml.Serialization.XmlTypeAttribute(TypeName = "BCCDX.DistributionStatus", Namespace = "urn:bccdx.ca")]
public partial class BCCDXDistributionStatus
{
[System.Xml.Serialization.XmlElementAttribute("receivedTime", Namespace = "urn:bccdx.ca", IsNullable = false)]
public TS receivedTime { get; set; }
}
public class TS
{
[XmlAttribute("value")]
public DateTime Value { get; set; }
}
目前,您的服务正在返回如下所示的XML:
<RCMR_IN000030UV01 ITSVersion="1.0"
xmlns="urn:hl7-org:v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<distributionStatus
xmlns="urn:bccdx.ca">
<receivedTime value="2017-02-23T00:00:00-05:00"/>
</distributionStatus>
</RCMR_IN000030UV01>
但是,你想要这个:
<RCMR_IN000030UV01 ITSVersion="1.0"
xmlns="urn:hl7-org:v3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
<!---This should be added ---->
xmlns:x="urn:bccdx.ca">
<!---And distributionStatus should be prefixed with x: ---->
<x:distributionStatus>
<x:receivedTime value="2017-02-23T00:00:00-05:00"/>
</x:distributionStatus>
</RCMR_IN000030UV01>
首先我要注意这两个XML文件在语义上是相同的。在第一种情况下,名称空间"urn:bccdx.ca"
被声明为实际需要它的最低元素上的默认名称空间。在第二个中,它是在文件开头用前缀定义的。无论哪种方式,元素<distributionStatus>
及其子元素都以正确的命名空间结束。
因此,您可以简单地接受XML原样。
如果出于某种原因,必须将命名空间显示在带有x:
前缀的XML的开头,您可以向{[XmlNamespaceDeclarations]
属性添加docs属性{1}}强制命名空间在更高级别声明:
RCMR_IN000030UV01
指定target属性,参数,返回值或类成员包含与XML文档中使用的名称空间关联的前缀。
现在,您应该根据需要在根元素上返回带有命名空间的XML。