Learning WCF Chapter2 Data Contracts
A data contract describes how CLR types map to XSD schema definitions.
Data contracts are the preferred way to enable serialization of complex types included in operation signatures as parameters or return values.
You create a data contract by applying the DataContractAttribute to a type.
To include members in serialization,you decorate them with the DataMemberAttribute;
this is an opt-in process that has nothing to do with visibility of members (public,protected,private).
By default,serialization is handled by the DataContractSerializer,a new serializer for WCF that succeeds the XmlSerializer used for earlier technologies such as ASMX.
In this section,you will become acquainted with the key features of data contracts and common serialization practices, including the following:
• How to apply data contract attributes to exercise control over type serialization
• Version tolerance and data contract versioning techniques
• Implementing IExtensibleDataObject to support version tolerance
• How to work with polymorphic types in the service contract
• How enumerations, arrays, and collections are serialized
First you’ll complete a lab that illustrates many of these scenarios,and then I’ll explain the related attributes and features in greater detail.
Lab: Working with Data Contracts
For this lab you will modify a preexisting type,turning it into a data contract so that it can be included in the service contract.
Using the DataContractAttribute and the DataMemberAttribute,you will control type serialization through the DataContractSerializer.
You’ll also test data contract version tolerance and implement the IExtensibleData interface in support of versioning.
Creating a data contract
In this part of the lab,you’ll turn a complex type into a data contract so that it can be included in a service contract,
and then take a look at the XSD schema produced for the type in the WSDL document.
1. Open the startup solution for this lab: <YourLearningWCFPath>\Labs\Chapter2\DataContracts\DataContracts.sln.
This solution includes the following projects:
ContentTypes
A class library that contains a LinkItem type used by the service.
LinkItem is a custom type that holds a title,description,URL and other details that can be associated with events,articles,photos,files,and so forth.
In this example, LinkItem is used to hold information about a gig (or event) for a band.
GigManager
A class library containing the service contract and service type.
The service contract exposes operations to save a LinkItem,and retrieve the saved LinkItem.
This example uses session to save the item.
See Chapter 5 for more on sessions.
Host
A console application for hosting the service.
GigEntry
A Windows client application that presents an interface for users to create and save a gig entry and retrieve the saved entry.
2. Try to run the solution at first.
From Visual Studio,press F5 to run the Host and the GigEntry client application.
An InvalidDataContractException will be thrown when the ServiceHost attempts to initialize. //这个地方是瞎扯,默认不会抛出异常的 ,虽然我用的是.net 3.0,也不会抛出异常
The error message indicates that the type ContentTypes.LinkItem cannot be serialized.
3. Review the service contract for the solution.
Go to the GigManager project and open GigManagerService.cs.
The service contract is shown in Example 2-13.
The ContentTypes.LinkItem type is included in both operation signatures.
Example 2-13. IGigManagerService service contract
[ServiceContract(Name = "GigManagerServiceContract", Namespace = "http://www.thatindigogirl.com/samples/2006/06", SessionMode = SessionMode.Required)]
public interface IGigManagerService
{
[OperationContract]
void SaveGig(LinkItem item); [OperationContract]
LinkItem GetGig();
}
4. You are going to modify the LinkItem type to make it a valid data contract that can be included in the service contract.
Go to the ContentTypes project and add a reference to the System.Runtime.Serialization assembly. //需要添加新的引用System.Runtime.Serialization
Next,open LinkItem.cs and apply the DataContractAttribute to the class definition,
and apply the DataMemberAttribute to each private field so that they are included in the serialized type definition.
Add a using statement for System.Runtime.Serialization as well.
The resulting type should appear as shown in Example 2-14.
给类添加DataContract 给是有字段添加DataMember
[DataContract]
public class LinkItem
{
[DataMember]
private long id;
public long ID
{
get { return id; }
set { id = value; }
} [DataMember]
private string title;
public string Title
{
get { return title; }
set { title = value; }
} [DataMember]
private string description;
public string Description
{
get { return description; }
set { description = value; }
} [DataMember]
private DateTime dateStart;
public DateTime DateStart
{
get { return dateStart; }
set { dateStart = value; }
} [DataMember]
private DateTime dateEnd;
public DateTime DateEnd
{
get { return dateEnd; }
set { dateEnd = value; }
} [DataMember]
private string url;
public string Url
{
get { return url; }
set { url = value; }
}
}
5. Compile the solution and attempt to run the host once again.
This time you won’t see an exception because LinkItem is now a data contract.
6. View the service description in the browser;
you want to see the XSD schema representation of the LinkItem data contract.
Browse to the following address:http://localhost:8000 and click the ?wsdl link to navigate to the service description.
This will generate the service description so that you can browse to the following address: http://localhost:8000/?xsd=xsd2.
You should see a schema like the one shown in Example 2-15.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.datacontract.org/2004/07/ContentTypes" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/ContentTypes">
<xs:complexType name="LinkItem">
<xs:sequence>
<xs:element minOccurs="0" name="DateEnd" type="xs:dateTime"/>
<xs:element minOccurs="0" name="DateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="Description" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="ID" type="xs:long"/>
<xs:element minOccurs="0" name="Title" nillable="true" type="xs:string"/>
<xs:element minOccurs="0" name="Url" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem"/>
</xs:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.datacontract.org/2004/07/ContentTypes" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/ContentTypes">
<xs:complexType name="LinkItem">
<xs:sequence>
<xs:element minOccurs="" name="dateEnd" type="xs:dateTime"/>
<xs:element minOccurs="" name="dateStart" type="xs:dateTime"/>
<xs:element minOccurs="" name="description" nillable="true" type="xs:string"/>
<xs:element minOccurs="" name="id" type="xs:long"/>
<xs:element minOccurs="" name="title" nillable="true" type="xs:string"/>
<xs:element minOccurs="" name="url" nillable="true" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem"/>
</xs:schema>
Notice that the naming convention for each data member matches the field name in the type definition.
In addition,the order of each element in the schema sequence is alphabetical, //每一个元素是按照字母顺序排列的
as opposed to the order of appearance in the type definition.
Another thing to note is that the namespace for the type does not match the service contract target namespace;
instead,it uses the domain shemas.datacontract.org.
Note:
Other .NET serialization techniques are dependent on the reflection order of types.
This can introduce problems when developers inadvertently reorder the class definition,not realizing it can cause incompatibilities.
Customizing data contract serialization 自定义数据契约的序列化
Now the LinkItem type is a valid data contract but you may want to provide a namespace consistent with the namespace in your service contract,indicating that this type belongs to your application.
Furthermore,you may want to provide more formal names for each of the data members.
Another thing you may want to control is the order in which members appear in the schema—recall that the default behavior is to present them in alphabetical order.
In this section,you’ll customize the data contract to address these issues.
1. Modify the LinkItem type definition to provide a proper namespace,friendly names for each data member,and appropriate order for data members in the
schema.
Start by supplying a Namespace value for the DataContractAttribute.
Also provide values for the following DataMemberAttribute properties: Name,IsRequired,and Order.
Example 2-16 provides you with the values to use for each attribute.
Pay attention to the IsRequired property for each.
It will be significant later in the lab.
Example 2-16. Customizing serialization with DataContractAttribute and DataMemberAttribute
[DataContract(Namespace="http://schemas.thatindigogirl.com/samples/2006/06")]
public class LinkItem
{
[DataMember(Name = "Id", IsRequired = false, Order = 0)]
private long m_id;
[DataMember(Name = "Title", IsRequired = true, Order = 1)]
private string m_title;
[DataMember(Name = "Description", IsRequired = true, Order = 2)]
private string m_description;
[DataMember(Name = "DateStart", IsRequired = true, Order = 3)]
private DateTime m_dateStart;
[DataMember(Name = "DateEnd", IsRequired = false, Order = 4)]
private DateTime m_dateEnd;
[DataMember(Name = "Url", IsRequired = false, Order = 5)]
private string m_url;
// Properties
}
2. Compile the host and run it without debugging. Return to the browser and review the new LinkItem schema by browsing to http://localhost:8000/?xsd=xsd2(be sure to refresh).
The schema should now look like the one shown in Example 2-17.
这一块也是无力吐槽了,我编译之后,访问http://localhost:8000/?xsd=xsd2和http://localhost:8000/出现的是同一个界面。没有下面所显示的内容
应该访问这个地址http://localhost:8000/?xsd=xsd0
Example 2-17. Schema generated for the modified LinkItem data contract
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema elementFormDefault="qualified"
targetNamespace="http://schemas.thatindigogirl.com/samples/2006/06"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://schemas.thatindigogirl.com/samples/2006/06">
<xs:complexType name="LinkItem">
<xs:sequence>
<xs:element minOccurs="0" name="Id" type="xs:long" />
<xs:element name="Title" nillable="true" type="xs:string" />
<xs:element name="Description" nillable="true" type="xs:string" />
<xs:element name="DateStart" type="xs:dateTime" />
<xs:element minOccurs="0" name="DateEnd" type="xs:dateTime" />
<xs:element minOccurs="0" name="Url" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem" />
</xs:schema>
Now the elements in the schema use the formal property name and are presented in the order specified by each DataMemberAttribute.
Required and optional members also have an affect on the minOccurs schema attribute;
required elements use the implicit value for minOccurs, which is 1.
Leave the host running as you move to the next step in the lab.
Consuming data contracts at the client
Now it’s time to add some code to the client application to save and retrieve gig information using the LinkItem type.
In this section of the lab,you’ll see how SvcUtil generates data contracts for complex types exposed at the service.
1. Start by generating a proxy for the client.
Go to the GigEntry project and add a service reference supplying the base address for the GigManagerService: http://localhost:8000.
Use the namespace localhost.
2. Open GigInfoForm.cs in the code window and add the following code beneath the GigInfoForm definition to construct the proxy:
public partial class GigInfoForm : Form
{
localhost.GigManagerServiceContractClient m_proxy = new
GigEntry.localhost.GigManagerServiceContractClient( );
// other code
}
Find the cmdSave_Click() event and add code to create a LinkItem instance that will hold gig information input by the user.
Example 2-18 shows the code to initialize the LinkItem.
You must also add the using statement for GigEntry.localhost.
Example 2-18. Code to save a LinkItem
using GigEntry.localhost;
private void cmdSave_Click(object sender, EventArgs e)
{
LinkItem item = new LinkItem( );
item.Id = int.Parse(this.txtId.Text);
item.Title = this.txtTitle.Text;
item.Description = this.txtDescription.Text;
item.DateStart= this.dtpStart.Value;
item.DateEnd= this.dtpEnd.Value;
item.Url= this.txtUrl.Text;
m_proxy.SaveGig(item);
}
3. Now add code to the cmdGet_Click( ) event handler to retrieve the saved LinkItem storing gig information.
This code is shown in Example 2-19.
Example 2-19. Code to retrieve a previously saved LinkItem
private void cmdGet_Click(object sender, EventArgs e)
{
LinkItem item = m_proxy.GetGig( );
if (item != null)
{
this.txtId.Text = item.Id.ToString( );
this.txtTitle.Text = item.Title;
this.txtDescription.Text = item.Description;
if (item.DateStart != DateTime.MinValue)
this.dtpStart.Value = item.DateStart;
if (item.DateEnd != DateTime.MinValue)
this.dtpEnd.Value = item.DateEnd;
this.txtUrl.Text = item.Url;
}
}
4. Now you are ready to test the solution.
Compile the solution and run both the Host and GigEntry client application.
The GigEntry client application is prepopulated with some default values in the user interface (see Figure 2-5).
Select Save to populate a LinkItem with gig information and pass it to the SaveGig( ) service operation.
Clear some text from the description and select Get to retrieve the LinkItem you previously saved.
Figure 2-5. GigEntry client user interface
At this point,you have turned the LinkItem complex type into a data contract,exposed this type as part of the service description,and generated a client proxy to consume operations that rely on the LinkItem type.
To developers,the client code works directly with the LinkItem.
In fact,the service model relies on a client-side version of the data contract to handle serialization.
If you open the proxy,you’ll see a copy of the LinkItem data contract.
I’ll discuss this further after you complete the lab.
Exploring version tolerance
In this section,of the lab you’ll play with some data contract versioning scenarios.
You’ll add and remove items from the contract,and you’ll see what the limitations are on adding new parameters.
1. To begin with,remove one of the data members from the LinkItem data contract.
Open LinkItem.cs and comment the DataMemberAttribute for m_url:
//[DataMember(Name = "Url", Order = 5, IsRequired = false)]
private string url;
Compile and run the solution again and test the impact of this change.
In the GigEntry interface select Save,then select Get.
The URL textbox will be cleared because the value was lost at the service.
2. Change the LinkItem type so that it preserves unknown data elements provided by the client.
Modify the LinkItem class definition to inherit IExtensibleDataObject.
Implement the interface by adding the new ExtensionData member and property accessor shown in Example 2-20.
[DataContract(Namespace = "http://www.thatindigogirl.com/samples/2006/06")]
public class LinkItem : IExtensibleDataObject
{
private ExtensionDataObject extensionData;
public ExtensionDataObject ExtensionData
{
get
{
return extensionData;
}
set
{
extensionData = value;
}
}
//Other Code
}
Test the result of this change by compiling and running the solution once again.
From the GigEntry interface select Save. Clear the URL textbox and select Get.
This time, the URL you originally saved is returned.
3. Now add a new enum field to the data contract.
Open LinkItem.cs and add the enumeration defined in Example 2-21 to the ContentTypes namespace.
Example 2-21. Definition for LinkItemCategories
[DataContract(Namespace="http://schemas.thatindigogirl.com/samples/2006/06")]
public enum LinkItemCategories
{
[EnumMember]
Gig,
[EnumMember]
MP3,
[EnumMember]
Photo
}
Add the following required data member named LinkItemCategories to the LinkItem definition:
[DataMember(Name = "Category", IsRequired = true, Order = 6)]
public LinkItemCategories m_category;
Compile and run the solution again.
From the GigEntry interface,select Save;
this time a FaultException is thrown indicating an error while deserializing the message.
The error indicates that a different element was expected,which essentially means an expected field is missing or out of order.
格式化程序尝试对消息反序列化时引发异常: 尝试对参数 http://www.thatindigogirl.com/samples/2006/06 进行反序列化时出错: item。
InnerException 消息是““EndElement”命名空间“http://www.thatindigogirl.com/samples/2006/06”中的“item”并非所需元素。
所需元素应为“Category”。”。有关详细信息,请参阅 InnerException。
4. Change the definition so that the LinkItemCategories data member is no longer required:
[DataMember(Name = "Category", IsRequired = false, Order = 6)]
public LinkItemCategories m_category;
Compile and run the solution,executing the same test.
This time there won’t be an exception because the new data member,unknown to the client proxy,is no longer required.
Let’s take a closer look at the attributes and features used in this lab.
Mapping Data Contracts to XSD Schema
Data contracts included in service contracts become part of the service description and thus the WSDL document.
For each data contract included a schema is generated,and this schema is referenced by the operation messages that rely on the type.
In an operation signature that has multiple parameters and a return value,each may be a distinct data contract represented as individual schema.
Example 2-22 illustrates a schema generated for the LinkItem type (repeated from the lab). This schema describes the following:
• The target namespace of the serialized type.
Messages that include a serialized LinkItem will use this namespace to disambiguate from other LinkItem types if they exist.
• The definition of the type.
In the case of the LinkItem,the outer element name is <LinkItem> and it contains a sequence of child elements.
• The expected name for each child element.
• The data type of each child element.
Examples of schema types used in this schema are string, long, and dateTime.
• If the element is required or not as indicated by the minOccurs attribute.
If minOccurs is omitted,the implied value is 1.
If minOccurs is 0,the element may be omitted and the serialized type will still be valid against the schema.
• If the element can be empty or not as indicated by the nillable attribute.
If nillable is set to false, the element cannot be passed without contents.
• The layout order of each child element.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.thatindigogirl.com/samples/2006/06" elementFormDefault="qualified" targetNamespace="http://www.thatindigogirl.com/samples/2006/06">
<xs:import schemaLocation="http://localhost:8000/?xsd=xsd2" namespace="http://schemas.thatindigogirl.com/samples/2006/06"/>
<xs:element name="SaveGig">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="item" nillable="true" type="tns:LinkItem"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="LinkItem">
<xs:sequence>
<xs:element minOccurs="0" name="ID" type="xs:long"/>
<xs:element name="Title" nillable="true" type="xs:string"/>
<xs:element name="Description" nillable="true" type="xs:string"/>
<xs:element name="DateStart" type="xs:dateTime"/>
<xs:element minOccurs="0" name="DateEnd" type="xs:dateTime"/>
<xs:element xmlns:q1="http://schemas.thatindigogirl.com/samples/2006/06" minOccurs="0" name="Category" type="q1:LinkItemCategories"/>
</xs:sequence>
</xs:complexType>
<xs:element name="LinkItem" nillable="true" type="tns:LinkItem"/>
<xs:element name="SaveGigResponse">
<xs:complexType>
<xs:sequence/>
</xs:complexType>
</xs:element>
<xs:element name="GetGig">
<xs:complexType>
<xs:sequence/>
</xs:complexType>
</xs:element>
<xs:element name="GetGigResponse">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="GetGigResult" nillable="true" type="tns:LinkItem"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Schema can also represent hierarchical relationships in the event a data contract inherits other base data contracts.
Each data contract would still have its own schema,but the inheritance hierarchy is preserved. Collections,dictionaries,and arrays are all represented in schema as arrays.
The WSDL document thus carries not only all the information about endpoints,protocols,and operations,it also includes schema for each complex type used by each operation.
That’s how SvcUtil is able to reconstruct data contracts during proxy generation.
Although the resulting types may not look exactly like those at the service,the reverse-engineered types will successfully be serialized into a format that the service can deserialize to reconstruct appropriate CLR types.
In some cases,you may be presented with a preexisting schema that should be used in your service contracts.
You can use SvcUtil to generate data contracts for this schema in the same way you use SvcUtil to generate a proxy for the client.
Designing Data Contracts
As the lab illustrates,to create a data contract you apply DataContractAttribute to your custom types and apply the DataMemberAttribute to each field or property you want to include in serialization.
This opt-in approach forces developers to consider what information should be transferred between clients and services.
The service model uses the DataContractSerializer to convert between data contracts and schema.
Any data contracts included in service operations are included in the service description.
Thus, proxy generation can generate copies of those types for client use.
DataContractAttribute and DataMemberAttribute each have properties that help you control the schema generated for a complex type.
There are also other attributes that support enumerations and collections,specifically.
They are the EnumMemberAttribute and the CollectionDataContractAttribute,respectively.
In this section I’ll talk about each of these attributes and their relevance to serialization.
DataContractAttribute
The DataContractAttribute is part of the System.Runtime.Serialization namespace.
As discussed earlier,it is used to turn complex types into data contracts to support service model serialization.
This attribute has only two properties:
Name
Controls the complex type name generated for the schema. By default the CLR type name is used.
Namespace
Sets the target namespace for the schema.
This defaults to http://schemas.datacontract.org/2004/07/[CLR namespace].
The CLR namespace is the namespace in which the complex type is defined.
Setting each of these properties can be important since the desired schema conventions may not align with CLR naming conventions developers use.
At a minimum,you should provide a value for Namespace.
By default,the namespace used for data contracts uses the prefix http://schemas.datacontract.org/2004/07.
Like with the target namespace for the service,complex types described in schema should have a namespace that relates the type to your specific company or application.
This can also help to resolve ambiguities if other types are used with the same name.
A common convention in web service specifications is to take the target namespace for the service and replace “www” (for example) with “schemas.” The lab illustrates this pattern:
[DataContract(Namespace="http://schemas.thatindigogirl.com/samples/2006/06")]
DataMemberAttribute
The DataMemberAttribute is also part of the System.Runtime.Serialization namespace.
This attribute is used to opt-in the field or properties to be included in serialization.
This attribute provides several properties for controlling the resulting schema generated for a complex type:
Name
Controls the schema element name generated for the field or property.
The default behavior is to use the field or property name as defined in the CLR type.
IsRequired
Controls the minOccurs attribute for the schema element.
By default,all elements are optional (minOccurs=0).
Order
Controls the order of each element in the schema.
By default,nonordered data members appear alphabetically, followed by any ordered elements.
EmitDefaultValue
Controls if default values will be included in serialization.
By default,all data members are serialized.
If this property is set to false,any member that is set to the default value for its type (null reference types,for example) will not be serialized.
This can cause problems if IsRequired is set to true.
By default all data members are ordered alphabetically,they carry the name of the associated field or property,and they become nonrequired schema elements.
In this section, I’ll explain how to control these characteristics.
You can apply the DataMemberAttribute to a field or property definition regardless of visibility (public,protected,private).
Applying the DataMemberAttribute to properties enables you to serialize values that may not have field storage (they may be dynamically calculated at runtime).
In either case,this attribute explicitly includes the field or property in the data contract.
It can be confusing if you mix the application of this attribute among fields and properties,
so I recommend that you generate property accessors for all fields (public,protected,private)
so that you can apply the attribute to properties instead of fields.
If you name your properties in such a way that they also fit naming conventions for the schema,
you needn’t set the Name property of this attribute.
Note:
If you apply the DataMemberAttribute to both property and its associated field,
you’ll end up with duplicate members in the schema.
By default,data members are not required.
That means if the client fails to supply a value,the complex type will be initialized with defaults for those members.
If you require certain fields to operate,you should set the IsRequired property to true.
IsRequired affects the minOccurs attribute for the associated element in the schema.
If messages arrive with missing required elements the service model throws an exception,something this lab illustrates.
If you introduce new required fields to a complex type after version 1 of the contract has been published,existing clients will not be compatible.
To support backward compatibility,you should not make new data members required.
I’ll talk more about versioning practices shortly.
The nillable schema attribute cannot be controlled by a DataMemberAttribute property.
The default behavior is that reference types have nillable set to true,while value
types (structures) have nillable set to false.
This is illustrated in Example 2-17; string elements are nillable, dateTime elements are not.
You can modify this behavior by using the nullable type in .NET.
The following code shows you how to declare a nullable type using shorthand (“?” suffix) or the more formal notation with Nullable<T>:
[DataMember(Name = "DateEnd", IsRequired = false, Order = 4)]
private DateTime? m_dateEnd;
public Nullable<DateTime> DateEnd
{
get { return m_dateEnd; }
set { m_dateEnd = value; }
}
The resulting schema will now support empty values for the DateEnd element:
<xs:element minOccurs="0" name="DateEnd" nillable="true" type="xs:dateTime" />
Note:
A sample illustrating Nullable<T> can be found at <YourLearningWCFPath>\Samples\DataContracts\NullableTypes.
You can also control the order that elements appear in the schema.
By default,the DataContractSerializer generates a schema for each data contract with data member order based on the following rules:
• Starting from the topmost class in the hierarchy and working down through the inheritance tree.
• Within each individual data contract, data members are ordered alphabetically.
• Any data members with a specified order will be ordered alphabetically within the order grouping.
For example,ordered elements can be grouped within a type such that all members with Order=1 are alphabetical,followed all members with Order=2, and so on.
To simplify matters,developers should apply an explicit order to each data member,within a type.
After all,how does it look to business partners that consume your services if the Id field is in the middle of the elements in the schema instead of at the top?
What happens when there are 100 elements in a complex type and there is no sense to its organization?
Note:
If you need greater control over the resulting schema for a complex type or hierarchy of types,you should consider using the IXmlSerializable approach.
I’ll discuss this later in this chapter.
The important thing to consider is that naming conventions and element order for data contracts should be consistent and professional.
Note:
Here are several samples related to DataContractAttribute and DataMemberAttribute:
• <YourLearningWCFPath>\Samples\DataContracts\DataContracts_FieldMembers
• <YourLearningWCFPath>\Samples\DataContracts\DataContracts_PropertyMembers
EnumMemberAttribute
Enumerations are implicitly data contracts,which means you don’t have to decorate them with the DataContractAttribute in order to expose them in a service contract.
By default,all members are included in the schema for the enumeration,and the default namespace will use the prefix http://schemas.datacontract.org/2004/07.
To be consistent with your other data contracts,you should probably provide a namespace for your enumerations,as shown in Example 2-21 from this lab.
But,once you decorate enumerations with DataContractAttribute you are obligated to opt-in each member you want to include in the enumeration.
There is a catch to this: you must use the EnumMemberAttribute instead of the DataMemberAttribute.
Note:
Using the DataMemberAttribute will result in an empty schema definition for the enumeration.
The resulting schema definition for the LinkItemCategories enumeration in this lab is shown in Example 2-23.
Example 2-23. Schema generated for LinkItemCategories
<xs:simpleType name="LinkItemCategories">
<xs:restriction base="xs:string">
<xs:enumeration value="Gig" />
<xs:enumeration value="MP3" />
<xs:enumeration value="Photo" />
</xs:restriction>
</xs:simpleType>
The EnumMemberAttribute has a single property, Value.
You can use this property to control how enum members are named in the schema:
[EnumMember(Value="Event"]
Gig,
[EnumMember(Value="Music"]
MP3,
[EnumMember(Value="Pics"]
Photo
CollectionDataContractAttribute
You may need to create a custom collection at some point,and expose it as part of a service contract.
The CollectionDataContractAttribute is a special attribute specifically for this purpose.
This attribute has the following members:
Name
Controls the collection type name generated for the schema.
By default,the CLR type name is used.
Namespace
Sets the target namespace for the schema with default behavior like the DataContractAttribute.
ItemName
Controls the name for each element in the collection.
KeyName
Controls the key name for dictionary collections only. This is invalid if the collection type is not a dictionary.
ValueName
Controls the value name for dictionary collections only. This is invalid if the collection type is not a dictionary.
You apply the CollectionDataContractAttribute to the custom collection like this:
[CollectionDataContract(Namespace=
"http://schemas.thatindigogirl.com/samples/2006/06",ItemName="Item")]
public class LinkItemCollection: List<LinkItem>
{ }
A sample illustrating CollectionDataContractAttribute can be found at
<YourLearningWCFPath>\Samples\DataContracts\CollectionDataContract.
Learning WCF Chapter2 Data Contracts的更多相关文章
- Learning WCF Chapter2 Service Contracts
A service contract describes the operations supported by a service,the message exchange pattern they ...
- Learning WCF Chapter2 WCF Contracts and Serialization
So far I’ve talked about the standards behind it all,but in fact WCF hides most of this from the dev ...
- Learning WCF Chapter2 Service Description
While messaging protocols are responsible for message serialization formats,there must be a way to c ...
- Learning WCF Chapter2 Messaging Protocols
In Chapter 1,you were introduced to fundamental WCF concepts, 在章节1中,学习了wcf中的基础概念including how t ...
- Learning WCF Chapter1 Hosting a Service in IIS
How messages reach a service endpoint is a matter of protocols and hosting. IIS can host services ov ...
- Learning WCF Chapter1 Generating a Service and Client Proxy
In the previous lab,you created a service and client from scratch without leveraging the tools avail ...
- 理解WCF中的Contracts
WCF中的Contracts WCF通过Contract来说明服务和操作,一般包含五种类型的Contract:ServiceContract,OperationContract,FaultContra ...
- Learning WCF 书中的代码示例下载地址
Learning WCF Download Example Code 第一个压缩文件LearningWCF.zip是VS2005创建的项目,不要下载这个. 建议下载VS2008版的,以及Media
- In machine learning, is more data always better than better algorithms?
In machine learning, is more data always better than better algorithms? No. There are times when mor ...
随机推荐
- 项目由Windows2003 迁移到Windows 2008 过程,报 JS错误
这两天在做服务器迁移,遇到了一些小的问题,现在做个粗略的记录 原服务器环境:Windows 2003 现服务器环境:Windows 2008 其中SSB项目在迁移部署后发现,报 JS的错误. 我在想除 ...
- (六)Hibernate 映射类型
所有项目导入对应的hibernate的jar包.mysql的jar包和添加每次都需要用到的HibernateUtil.java 第一节:基本类型映射 例子: hibernate.cfg.xml < ...
- yum 安装 依赖报错
今天使用yum安装的时候 报错: Error: Multilib version problems found. This often means that the root cause 应该是yum ...
- Make Ubuntu 14.04 Fullscreen and virtualbox
sudo apt-get remove libcheese-gtk23 sudo apt-get install xserver-xorg-core sudo apt-get install virt ...
- IE6 png 透明 (三种解决方法)
FF和IE7已经直接支持透明的png图了,下面这个主要是解决IE6下透明PNG图片有灰底的 ====================================================== ...
- mvc3.0ModelFirst生成实体
前沿 这几天想用mvc写点东西,mvc现在自己工作也不用,所以有些生.于是弄点视频研究一下.可能一些经常接触mvc的对这个问题看来,就是小kiss,但是我感觉自己研究出来了还是比较兴奋.在3.0根据模 ...
- Sqlserver知识点1
1.字符串 字符数据类型是SQL Server 中最常用的数据类型之一,它可以用来存储各种字母.数字符号和特殊符号.在使用字符数据类型时,需要在其前后加上英文单引号或者双引号. (1)char ...
- 一个小程序[Socrates]中学到的Perl点滴
1. 抓取网页源文件,只要三行代码 use LWP::Simple; $url='http://music.baidu.com/top/dayhot'; $page=get($url) or die ...
- C语言-06复杂数据类型-01数组
01-数组 #include <stdio.h> int main() { // 使用注意 // 都是正确写法 //int ages[5] = {10 , 11, 12, 67, 56}; ...
- Navigation学习笔记
***************************** 使用storyboard导航********************************* storyboard方式相对简单. 在弹出来 ...