Contract Generation from WSDL/XML Schema - DataContractSerializer vs. XmlSerializer
来源:互联网 发布:车载充电器 知乎 编辑:程序博客网 时间:2024/06/06 18:08
WCF LOB Adapter SDK metadata object model generates WSDL / XML Schema with constructs that are well-liked by DataContractSerializer. The Svcutil.Exe creates a proxy / service interface from this WSDL containing attributes such as ServiceContract, OperationContract, DataContract, DataMember, etc. If the adapter developer provides own XML Schema structure in OperationMetadata and/or TypeMetadata derived class and the XML Schema contains constructs that are ignored or forbidden by DataContractSerializer, the Svcutil.Exe and Add Adapter Service Reference Visual Studio Plug-In falls back to use XmlSerializer for serialization.
Following are some examples of forbidden XML Schema constructs:
· Xsd:choice
· Xsd:group
· Xsd:any
· Xsd:ref
· Xsd:attribute
The metadata object model in WCF LOB Adapter SDK avoids generating any XML Schema constructs that are ignored and forbidden by DataContractSerializer. But if the adapter developer wants to provide their own schema, then it is outside the Adapter SDK control and the WSDL will contain the XML Schema definitions as provided by the adapter developer. The generate CLR proxy will have the XmlSerializer attributes defined on operations and its members.
What does this mean to the end-user?
Adapter Consumers who want to use the adapter in BizTalk Server are not affected with XML/CLR (de) serialization, as they are working directly with XML Schema types. As long as the XML message conforms to the XML Schema, the adapter understands it.
But if the same adapter is also now being used within a .NET application that will convert the WSDL / XML Schema into relevant CLR objects, the end-users who are working with the generated CLR object may contain definitions that are “bizarre”.
Let me give you an example. Consider an XML Schema with optional elements defined (i.e. minOccurs=’0’). When using DataContractSerializer, the minOccurs should map to IsRequired attribute in the CLR object. The XmlSerializer on the other hand generates a proxy that contains the xxxSpecified properties for each optional element. The xxxSpecified was a pain for our customers in .NET 2.0 when used with xsd.exe or wsdl.exe. Now, let’s add another complex type in the WSDL that uses a forbidden construct such as “xsd:attribute”. The Svcutil.Exe will revert to use XmlSerializer and generate an output that contains xxxSpecified fields.
See the sample code that illustrates the above point.
Sample WSDL (without any forbidden construct)
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tns="hello://Microsoft.WCF.Samples.Adapters" xmlns:doc="http://schemas.microsoft.com/servicemodel/adapters/metadata/documentation" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:ns2="hello://Microsoft.WCF.Samples.Adapters" targetNamespace="hello://Microsoft.WCF.Samples.Adapters" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="hello://Microsoft.WCF.Samples.Adapters" version="1.0" xmlns="http://www.w3.org/2001/XMLSchema">
<complexType name="MyType">
<sequence>
<element minOccurs="0" maxOccurs="1" nillable="true" type="double" name="ONillableDoubleField" />
<element minOccurs="1" maxOccurs="1" nillable="true" type="double" name="MNillableDoubleField" />
<element minOccurs="1" maxOccurs="1" type="double" name="MandatoryDoubleField" />
<element minOccurs="0" maxOccurs="1" type="double" name="OptDoubleField" />
</sequence>
</complexType>
<element name="SayHelloWorld">
<annotation>
<documentation>
<doc:action>Hello/SayHelloWorld</doc:action>
</documentation>
</annotation>
<complexType>
<sequence>
<element minOccurs="1" maxOccurs="1" name="inName" nillable="true" type="string">
<annotation>
<documentation>Hello World is said by this name.</documentation>
</annotation>
</element>
<element minOccurs="0" maxOccurs="1" name="OptionalElement" type="dateTime" />
<element minOccurs="0" maxOccurs="1" name="Container" type="ns2:MyType"/>
</sequence>
</complexType>
</element>
<element name="SayHelloWorldResponse">
<annotation>
<documentation>
<doc:action>Hello/SayHelloWorld/response</doc:action>
</documentation>
</annotation>
<complexType>
<sequence>
<element minOccurs="1" maxOccurs="1" name="SayHelloWorldResult" nillable="true" type="string" />
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
<wsdl:message name="HelloWorld_SayHelloWorld_InputMessage">
<wsdl:part name="parameters" element="ns2:SayHelloWorld" />
</wsdl:message>
<wsdl:message name="HelloWorld_SayHelloWorld_OutputMessage">
<wsdl:part name="parameters" element="ns2:SayHelloWorldResponse" />
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="SayHelloWorld">
<wsdl:input wsaw:Action="Hello/SayHelloWorld" message="ns2:HelloWorld_SayHelloWorld_InputMessage" />
<wsdl:output wsaw:Action="Hello/SayHelloWorld/response" message="ns2:HelloWorld_SayHelloWorld_OutputMessage" />
</wsdl:operation>
</wsdl:portType>
</wsdl:definitions>
SVCUTIL generated service interface proxy
svcutil HelloWorld.wsdl /out:HelloWorld.DataContractSereializer.cs
[assembly: System.Runtime.Serialization.ContractNamespaceAttribute("hello://Microsoft.WCF.Samples.Adapters", ClrNamespace="microsoft.wcf.samples.adapters")]
namespace microsoft.wcf.samples.adapters
{
using System.Runtime.Serialization;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute()]
public partial class MyType : object, System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
private System.Nullable<double> ONillableDoubleFieldField;
private System.Nullable<double> MNillableDoubleFieldField;
private double MandatoryDoubleFieldField;
private double OptDoubleFieldField;
public System.Runtime.Serialization.ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute()]
public System.Nullable<double> ONillableDoubleField
{
get
{
return this.ONillableDoubleFieldField;
}
set
{
this.ONillableDoubleFieldField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, Order=1)]
public System.Nullable<double> MNillableDoubleField
{
get
{
return this.MNillableDoubleFieldField;
}
set
{
this.MNillableDoubleFieldField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, Order=2)]
public double MandatoryDoubleField
{
get
{
return this.MandatoryDoubleFieldField;
}
set
{
this.MandatoryDoubleFieldField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute(Order=3)]
public double OptDoubleField
{
get
{
return this.OptDoubleFieldField;
}
set
{
this.OptDoubleFieldField = value;
}
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", ConfigurationName="HelloWorld")]
public interface HelloWorld
{
[System.ServiceModel.OperationContractAttribute(Action="Hello/SayHelloWorld", ReplyAction="Hello/SayHelloWorld/response")]
string SayHelloWorld(string inName, System.DateTime OptionalElement, microsoft.wcf.samples.adapters.MyType Container);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface HelloWorldChannel : HelloWorld, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HelloWorldClient : System.ServiceModel.ClientBase<HelloWorld>, HelloWorld
{
public HelloWorldClient()
{
}
public HelloWorldClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public HelloWorldClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public string SayHelloWorld(string inName, System.DateTime OptionalElement, microsoft.wcf.samples.adapters.MyType Container)
{
return base.Channel.SayHelloWorld(inName, OptionalElement, Container);
}
}
Sample WSDL (with a forbidden construct)
Change the WSDL to include a DataContractSerializer forbidden construct within the complex type MyType. Keep everything else as is.
<complexType name="MyType">
<sequence>
<element minOccurs="0" maxOccurs="1" nillable="true" type="double" name="ONillableDoubleField" />
<element minOccurs="1" maxOccurs="1" nillable="true" type="double" name="MNillableDoubleField" />
<element minOccurs="1" maxOccurs="1" type="double" name="MandatoryDoubleField" />
<element minOccurs="0" maxOccurs="1" type="double" name="OptDoubleField" />
</sequence>
<attribute default="X" name="xAttribute" type="string" />
</complexType>
svcutil HelloWorld-xmltypes.wsdl /out:HelloWorld.XmlSerializer.cs
Check the impact of doing this on the generated proxy and notice other attributes such as –
· XmlSerializerFormatAttribute
· XmlTypeAttribute
· XmlElementAttribute
· XmlAttributeAttribute
· MessageContractAttribute
· MessageBodyMemberAttribute
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", ConfigurationName="HelloWorld")]
public interface HelloWorld
{
// CODEGEN: Parameter 'SayHelloWorldResult' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
[System.ServiceModel.OperationContractAttribute(Action="Hello/SayHelloWorld", ReplyAction="Hello/SayHelloWorld/response")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
SayHelloWorldResponse SayHelloWorld(SayHelloWorldRequest request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "3.0.4506.30")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters")]
public partial class MyType
{
private System.Nullable<double> oNillableDoubleFieldField;
private bool oNillableDoubleFieldFieldSpecified;
private System.Nullable<double> mNillableDoubleFieldField;
private double mandatoryDoubleFieldField;
private double optDoubleFieldField;
private bool optDoubleFieldFieldSpecified;
private string xAttributeField;
public MyType()
{
this.xAttributeField = "X";
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=0)]
public System.Nullable<double> ONillableDoubleField
{
get
{
return this.oNillableDoubleFieldField;
}
set
{
this.oNillableDoubleFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool ONillableDoubleFieldSpecified
{
get
{
return this.oNillableDoubleFieldFieldSpecified;
}
set
{
this.oNillableDoubleFieldFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=1)]
public System.Nullable<double> MNillableDoubleField
{
get
{
return this.mNillableDoubleFieldField;
}
set
{
this.mNillableDoubleFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=2)]
public double MandatoryDoubleField
{
get
{
return this.mandatoryDoubleFieldField;
}
set
{
this.mandatoryDoubleFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Order=3)]
public double OptDoubleField
{
get
{
return this.optDoubleFieldField;
}
set
{
this.optDoubleFieldField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlIgnoreAttribute()]
public bool OptDoubleFieldSpecified
{
get
{
return this.optDoubleFieldFieldSpecified;
}
set
{
this.optDoubleFieldFieldSpecified = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
[System.ComponentModel.DefaultValueAttribute("X")]
public string xAttribute
{
get
{
return this.xAttributeField;
}
set
{
this.xAttributeField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="SayHelloWorld", WrapperNamespace="hello://Microsoft.WCF.Samples.Adapters", IsWrapped=true)]
public partial class SayHelloWorldRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string inName;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", Order=1)]
public System.DateTime OptionalElement;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", Order=2)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public MyType Container;
public SayHelloWorldRequest()
{
}
public SayHelloWorldRequest(string inName, System.DateTime OptionalElement, MyType Container)
{
this.inName = inName;
this.OptionalElement = OptionalElement;
this.Container = Container;
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="SayHelloWorldResponse", WrapperNamespace="hello://Microsoft.WCF.Samples.Adapters", IsWrapped=true)]
public partial class SayHelloWorldResponse
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="hello://Microsoft.WCF.Samples.Adapters", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string SayHelloWorldResult;
public SayHelloWorldResponse()
{
}
public SayHelloWorldResponse(string SayHelloWorldResult)
{
this.SayHelloWorldResult = SayHelloWorldResult;
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface HelloWorldChannel : HelloWorld, System.ServiceModel.IClientChannel
{
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class HelloWorldClient : System.ServiceModel.ClientBase<HelloWorld>, HelloWorld
{
public HelloWorldClient()
{
}
public HelloWorldClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public HelloWorldClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public HelloWorldClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
SayHelloWorldResponse HelloWorld.SayHelloWorld(SayHelloWorldRequest request)
{
return base.Channel.SayHelloWorld(request);
}
public string SayHelloWorld(string inName, System.DateTime OptionalElement, MyType Container)
{
SayHelloWorldRequest inValue = new SayHelloWorldRequest();
inValue.inName = inName;
inValue.OptionalElement = OptionalElement;
inValue.Container = Container;
SayHelloWorldResponse retVal = ((HelloWorld)(this)).SayHelloWorld(inValue);
return retVal.SayHelloWorldResult;
}
}
Summary: Avoid, where possible, having constructs in the WSDL / XML Schema that can create a less optimum proxy for the end-user (applicable when using a top-down approach with creating a service interface from WSDL / XML Schema).
- Contract Generation from WSDL/XML Schema - DataContractSerializer vs. XmlSerializer
- XmlSerializer vs DataContractSerializer: Serialization in Wcf
- Message Contract, Data Contract, XmlSerializer Message XML Body
- xml/schema/wsdl
- xml/schema/wsdl
- XML Schema VS. Java Class
- 化零为整WCF(9) - 序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, BinaryFormatter)
- 化零为整WCF(9) - 序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, BinaryFormatter)
- 化零为整WCF(9) - 序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, BinaryFormatter)
- WCF(10):序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, Binary
- XmlSerializer, DataContractSerializer 和 BinaryFormatter区别与用法分析
- WCF - 序列化(DataContractSerializer, XmlSerializer, DataContractJsonSerializer, SoapFormatter, Binar
- XML Schema File VS. XML File
- 在 XML Schema和WSDL中使用名称空间
- 在 XML Schema和WSDL中使用名称空间
- 在 XML Schema和WSDL中使用名称空间
- 在 XML Schema和WSDL中使用名称空间
- 【转帖】XML Schema学习笔记详解WSDL types
- C# 读取Excel中指定的Sheet名称或索引
- [无情Dē温柔] 90后男孩的17-19岁三年生活
- 揭开CDP面纱
- ASP.NET页面刷新方法总结(转载)
- XP常用快捷键
- Contract Generation from WSDL/XML Schema - DataContractSerializer vs. XmlSerializer
- cypress usb controller firmware program
- Asp.net 中session存储的三种模式的具体运用
- EXT3.0实现的同步请求
- 用任务管理器揪出暗藏的木马
- 记我的10年18家工作经历 (转载.完整版)
- 十天复习,过不到计算机二级是你的运气PIE
- C#多线程UI界面处理
- 将一个Form窗体放到Panel(或者splitContainer的Panel)上去