Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Azure

Service-Orientation with .NET : Service Contracts and Interoperability - Canonical Schema

5/7/2011 10:31:07 AM
- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
The XML Schema Definition Language is a highly successful industry standard that has received broad cross-platform support within, and well beyond, the SOA industry. With this language you can use industry standard markup syntax to not only express the structure and validation rules of business documents, but you can also use a series of built-in data types to represent the actual data. This allows you to define complete data models in a manner that is independent of any proprietary database or data representation technology.

Canonical Schema  establishes standardized XML Schema definitions (Figure 1), which makes this a pattern that can be applied in direct support of Standardized Service Contract .

Figure 1. By sharing a canonical schema definition, different services increase their respective compatibility and interoperability.


Schema Centralization , a related pattern that mandates that schema definitions be shared among service contracts, can be applied together with Canonical Schema  to help create a flexible and streamlined data architecture that acts as a foundation layer for a set of federated service contracts (Figure 2). The abstraction achieved by such a data architecture allows you to build underlying services using .NET, Java, or any other back-end implementation platform that supports XML Schema processing.

Figure 2. When canonical schemas are centralized, they are essentially reused by different service contracts, resulting in increased normalization across the service data and endpoint architecture.


Creating Schemas with Visual Studio

To build canonical XML schemas that we will eventually want to centralize, we need to master the XML Schema Definition Language and customize these schemas using an editor, such as the one provided by Visual Studio.


Let’s now put together some simple schemas. Figure 3 shows a preview of the person schema displayed in the Visual Studio 2010 Schema View. We can also refer to the person schema as the person type, because it essentially establishes a complex type for the person entity.

Figure 3. XML Schema types defined.


We’ll begin with putting together the gender type first:

Example 1.
<xs:schema xmlns:xs=http://www.w3.org/2001/XMLSchema
targetNamespace="http://schemas.example.org/
enterprise/models/v1"
xmlns="http://schemas.example.org/
enterprise/models/v1"
xmlns:mstns="http://schemas.example.org/
enterprise/models/v1"
version="1.0.1"
elementFormDefault="qualified">
<xs:simpleType name="gender">
<xs:restriction base="xs:string">
<xs:enumeration value="male" />
</xs:enumeration value="female" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

The validation logic in this schema only accepts string values that are “male” and “female.” The gender type is saved as a separate XML schema file called gender.xsd.

Next, let’s create the address type:

Example 2.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://schemas.example.org/
enterprise/models/v1"
xmlns="http://schemas.example.org/
enterprise/models/v1"
xmlns:mstns="http://schemas.example.org/
enterprise/models/v1"
version="1.0.1"
elementFormDefault="qualified">
<xs:complexType name="address">
<xs:sequence>
<xs:element name="address" type="xs:string" />
<xs:element name="city" type="xs:string" />
<xs:element name="state" type="xs:string" />
<xs:element name="zip" type="xs:string" />
<xs:element name="phone" type="xs:string" />
<xs:element name="country" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>

The address type accepts strings for all of its child elements. This type is also saved in a separate schema file (called address.xsd).

Finally, here’s the content for the person type, which is stored in the person.xsd file:

Example 3.
<xs:schema xmlns:xs=
"http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://schemas.example.org/
enterprise/models/v1"
targetNamespace="http://schemas.example.org/
enterprise/models/v1"
xmlns:mstns="http://schemas.example.org/
enterprise/models/v1"
version="1.1.20"
elementFormDefault="qualified">
<xs:include schemaLocation="Gender.xsd"/>
<xs:include schemaLocation="Address.xsd"/>
<xs:complexType name="person">
<xs:sequence>
<xs:element name="ID" type="xs:positiveInteger" />
<xs:element name="foreName"
type="xs:string" minOccurs="1"/>
<xs:element name="middleName" type="xs:string" />
<xs:element name="surName"
type="xs:string" minOccurs="1"/>
<xs:element name="socSecNr" type="xs:unsignedLong"
minOccurs="1" maxOccurs="1"/>
<xs:element name="jobTitle"
type="xs:string" minOccurs="0" maxOccurs="1" />
<xs:element name="address" type="tns:address" />
<xs:element name="gender" type="tns:gender" />
</xs:sequence>
</xs:complexType>
<xs:element name="person" type="tns:person" />
</xs:schema>


Note how the types of elements address and gender refer to the types created in the address.xsd and gender.xsd respectively. Two statements are necessary in order to make the address element refer to the type defined in the address.xsd file. The first refers to the previously created schema:

<xs:include schemaLocation="address.xsd"/>

The second specifies that the element address should be of this type:

<xs:element name="address" type="tns:address"/>

Also note that there is an element in the person XML schema that has the type of person. This makes it possible to send the person type as a message. The gender and address types do not have such an element because we are not planning to use them on their own to define individual messages.

At this point our catalog of XML schemas looks like this:

Figure 4. The catalog of XML schemas.


Generating .NET Types

The types we have created can be used “as is” for message definitions in BizTalk, but to use them for WCF (or ASMX) services, we need to generate .NET types using a utility program called svcutil that is shipped with Visual Studio. To generate these types, use the following statement at the Visual Studio command prompt:

svcutil  /dcOnly  /l:cs  person.xsd  address.xsd  gender.xsd

Apart from referring to the previously created XML schema files, we are also using these two switches:

  • /dcOnly – instructs svcutil to create data contracts for us

  • /l:cs – instructs svcutil that the language (l) of the generated code should be C# (cs)

The code that scvutil generates based upon our types looks like this:

Example 4.
{
using System.Runtime.Serialization;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute
(Name = "person", Namespace =
"http://schemas.example.org/enterprise/models/v1")]
public partial class person : object,
System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.
ExtensionDataObject extensionDataField;
private long idField;
private string foreNameField;
private string middleNameField;
private string surNameField;
private ulong socSecNrField;
private string jobTitleField;
private schemas.example.org.enterprise.models.v1.
address addressField;
private schemas.example.org.enterprise.models.v1.
gender genderField;
public System.Runtime.Serialization.
ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.
DataMemberAttribute(IsRequired = true)]
public long id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
[System.Runtime.Serialization.
DataMemberAttribute(IsRequired = true,
EmitDefaultValue = false, Order = 1)]
public string foreName
{
get
{
return this.foreNameField;
}
set
{
this.foreNameField = value;
}
}
[System.Runtime.Serialization.
DataMemberAttribute(IsRequired = true,
EmitDefaultValue = false, Order = 2)]
public string middleName
{
get
{
return this.middleNameField;
}
set
{
this.middleNameField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false, Order = 3)]
public string surName
{
get
{
return this.surNameField;
}
set
{
this.surNameField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, Order = 4)]
public ulong socSecNr
{
get
{
return this.socSecNrField;
}
set
{
this.socSecNrField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(EmitDefaultValue = false, Order = 5)]
public string jobTitle
{
get
{
return this.jobTitleField;
}
set
{
this.jobTitleField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false, Order = 6)]
public schemas.example.org.enterprise.models.v1.address address
{
get
{
return this.addressField;
}
set
{
this.addressField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, Order = 7)]
public schemas.example.org.enterprise.models.v1.gender gender
{
get
{
return this.genderField;
}
set
{
this.genderField = value;
}
}
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute
(Name = "address", Namespace = "http://schemas.example.org/
enterprise/models/v1")]
public partial class address : object,
System.Runtime.Serialization.IExtensibleDataObject
{
private System.Runtime.Serialization.
ExtensionDataObject extensionDataField;
private string addressMemberField;
private string cityField;
private string stateField;
private string zipField;
private string phoneField;
private string countryField;
public System.Runtime.Serialization.
ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(Name = "address", IsRequired = true,
EmitDefaultValue = false)]
public string addressMember
{
get
{
return this.addressMemberField;
}
set
{
this.addressMemberField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false)]
public string city
{
get
{
return this.cityField;
}
set
{
this.cityField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false)]
public string state
{
get
{
return this.stateField;
}
set
{
this.stateField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false)]
public string zip
{
get
{
return this.zipField;
}
set
{
this.zipField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false, Order = 4)]
public string phone
{
get
{
return this.phoneField;
}
set
{
this.phoneField = value;
}
}
[System.Runtime.Serialization.DataMemberAttribute
(IsRequired = true, EmitDefaultValue = false, Order = 5)]
public string country
{
get
{
return this.countryField;
}
set
{
this.countryField = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCodeAttribute
("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute
(Name = "gender", Namespace = "http://schemas.
example.org/enterprise/models/v1")]
public enum gender : int
{
[System.Runtime.Serialization.
EnumMemberAttribute()]
male = 0,
[System.Runtime.Serialization.
EnumMemberAttribute()]
female = 1,
}
}


Note

As an alternative to the svcutil utility, you can also use the xsd.exe utility, which will create .NET types that are serialized using the XMLSerializer rather than the DataContractSerializer.


Using the DataContract Library

You can also create these types by using code directly with .NET, instead of working with XML schema markup code. This next example shows how to create the three types in .NET using the DataContract and DataMember attributes.

Example 5.
 [DataContract(Name = "person", Namespace =
"http://schemas.example.org/enterprise/models/v1")]
public class Person : object,
System.Runtime.Serialization.IExtensibleDataObject
{
[DataMember(IsRequired = true)]
public int Id
{
get;
set;
}
[DataMember(IsRequired=true,
EmitDefaultValue=false, Order = 1)]
public string ForeName
{
get;
set;
}
[DataMember(IsRequired = true,
EmitDefaultValue=false, Order = 2)]
public string MiddleName
{
get;
set;
}
[DataMember(IsRequired = true,
EmitDefaultValue=false, Order = 3)]
public string SurName
{
get;
set;
}
[DataMember(IsRequired = true,
EmitDefaultValue=false, Order = 4)]
public ulong SocSecNr
{
get;
set;
}
[DataMember(Order = 5)]
public string JobTitle
{
get;
set;
}
[DataMember(Order = 6)]
public Address Address
{
get;
set;
}
[DataMember(Order = 7)]
public Gender Gender
{
get;
set;
}
private System.Runtime.Serialization.
ExtensionDataObject extensionDataField;
public System.Runtime.Serialization.
ExtensionDataObject ExtensionData
{
get
{
return this.extensionDataField;
}
set
{
this.extensionDataField = value;
}
}


The address and gender types are created as separate classes that use DataContract and DataMember attributes. The DataContract attribute is used to let .NET know that this is a data contract and that it should be serialized using DataContractSerializer. This serializer will only serialize fields that are annotated with the DataMember attribute.

Apart from signaling to the DataContractSerializer that a particular element should be serialized, the DataMember attribute accepts named arguments.

Specifically, the named arguments used in Example 5 are:

  • Order – affects the order in which the fields of the type are serialized

  • IsRequired – instructs consumers and services whether or not a field is required

  • EmitDefailtValue – when set to false, the default value (for example, 0 for an int) will not be serialized

The DataMember attribute has several other arguments that can come in handy. For example, should you require a different name in the .NET code and the serialized message, the Name attribute lets you change the name of the serialized value.

Figure 5 shows the resulting library created so far.

Figure 5. The Service Library defined so far, including Address, Gender, and Person class definitions.

Other -----------------
- Service-Orientation with .NET : Standardized Service Contract
- Cloud Services with Windows Azure : Windows Azure Storage
- A REST Service in Windows Azure
- Cloud Services with Windows Azure : A Web Service in Windows Azure
- Cloud Services with Windows Azure : Hello World in Windows Azure
- Cloud Services with Windows Azure : Windows Azure Roles
- Cloud Services with Windows Azure : Windows Azure Platform Overview
- Cloud Services with Windows Azure : Cloud Computing 101
- SOA with .NET and Windows Azure : Orchestration Patterns with WF - Compensating Service Transaction
- SOA with .NET and Windows Azure : Orchestration Patterns with WF - State Repository
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server