Вы находитесь на странице: 1из 50

Windows Communication Foundation Top to Bottom (Part 02 of 15): Contracts

Michele Leroux Bustamante Chief Architect IDesign Inc.

About Michele Leroux Bustamante


IDesign Inc., www.idesign.net Microsoft regional director MVP Connected Systems BEA technical director IASA - board member Published MSDN, CoDe, TheServerSide International speaker, International .NET Association (INETA) Program advisor, UCSD Extension Track chair, SD Expo www.dasblonde.net, www.thatindigogirl.com

What We Will Cover


How to design service contracts for your Windows Communication Foundation (WCF) services Handling complex type serialization Working with service contracts, data contracts, and message contracts Code-first versus contract-first approaches

Session Prerequisites
Experience building Microsoft .NET Framework applications Basic understanding of WCF clients and services

Level 100

Agenda
Contracts and metadata Service contracts Complex type serialization
Serializable types, data contracts, known types, IXmlSerializable

Message contracts Summary of approaches

Clients and Services


ServiceHost

Endpoint

Service
Endpoint

Host Process

Clients and Services


Client App ServiceHost

Proxy
Endpoint

Endpoint

Service
Endpoint

Client Process

Host Process

Clients and Services


Client App ServiceHost

Proxy
Endpoint

Endpoint

Service
Endpoint

Client Process

Host Process

Demonstration One

Contracts and metadata

WCF Contracts
Service contracts Data contracts and other serializable types Message contracts

Agenda
Contracts and metadata Service contracts Complex type serialization
Serializable types, data contracts, known types, IXmlSerializable

Message contracts Summary of approaches

Service Contracts
ServiceContractAttribute
Define service operations

OperationContractAttribute
Methods exposed as part of the public service contract
[ServiceContract] public interface IContentManagerService { [OperationContract] void SaveLink(LinkItem item); }

ServiceContractAttribute
Applied to interfaces or classes Prefer interface
Remove coupling to service implementation Services may implement >1 contract

Always provide meaningful Namespace Can provide explicit Name


[ServiceContract(Name="ContentManagerContract", Namespace= "http://www.thatindigogirl.com /samples/2007/07")] public interface IContentManagerService {}

OperationContractAttribute
All methods in a service contract should have OperationContractAttribute Can provide explicit Name, Action, ReplyAction
[ServiceContract(Name="ContentManagerContract", Namespace = "http://www.thatindigogirl.com/samples/2007/07")] public interface IContentManagerService { [OperationContract(Name="SaveLink", Action= "http://www.thatindigogirl.com/samples/2007/07/ ContentManagerContract/SaveLink", ReplyAction="http://www.thatindigogirl.com/samples/ 2007/07/ContentManagerContract/SaveLink")] void SaveLink(LinkItem item); }

MessageParameterAttribute
Use MessageParameterAttribute to control parameter or return naming
[ServiceContract(Name="ContentManagerContract, Namespace= "http://www.thatindigogirl.com/samples/2007/07")] public interface IContentManagerService { [OperationContract] void SaveLink([MessageParameter(Name="LinkItem")] LinkItem item); [OperationContract] [return: MessageParameter(Name="LinkItem")] LinkItem GetLink(string id); }

Agenda
Contracts and metadata Service contracts Complex type serialization
Serializable types, data contracts, known types, IXmlSerializable

Message contracts Summary of approaches

Complex Type Serialization


Serializable types Data contracts Known types IXmlSerializable

DataContractSerializer
DataContractAttribute

IXmlSerializable

XML

DataContractSerializer
SerializableAttribute

XSD WSDL

SerializableAttribute
SerializableAttribute, Serializable

Many CLR types are serializable All fields are serialized


Regardless of accessibility

No control over naming conventions or data types


[Serializable] public class LinkItem { private long m_id; private string m_title; private string m_description; private DateTime m_dateStart; private DateTime m_dateEnd; private string m_url; // property accessors }

Data Contracts
DataContractAttribute
Translation between CLR types and schema

DataMemberAttribute
Opt-in members for serialization Applied to fields or properties

Preferred way for DataContractSerializer to work with complex types

Demonstration Two

Data contracts

DataContractAttribute
Always provide a Namespace
Web service conventions use schemas prefix to service target namespace

Can provide explicit Name


[ServiceContract(Name="ContentManagerContract, Namespace="http://www.thatindigogirl.com/samples/2007/07")] public interface IContentManagerService {}

[DataContract(Name="LinkItem, Namespace= "http://schemas.thatindigogirl.com/samples/2007/07")] public class LinkItem {}

DataMemberAttribute
Applied to fields or properties Always provide Order
Default order is alphabetical

Can provide explicit Name, IsRequired


[DataMember(Name = "Id", IsRequired = false, Order = 0)] private long m_id;
[DataMember(Name = "Id", IsRequired = false, Order = 0)] public long Id { get { return m_id; } set { m_id = value; } }

Data Contract Schema


Alphabetical Ordering (Default)
<xs:complexType name="LinkItem"> <xs:sequence> <xs:element minOccurs="0" name="m_dateEnd" type="xs:dateTime" /> <xs:element minOccurs="0" name="m_dateStart" type="xs:dateTime" /> <xs:element minOccurs="0" name="m_description" nillable="true" type="xs:string" /> <xs:element minOccurs="0" name="m_id" type="xs:long" /> <xs:element minOccurs="0" name="m_title" nillable="true" type="xs:string" /> <xs:element minOccurs="0" name="m_url" nillable="true" type="xs:string" /> </xs:sequence> </xs:complexType>

[DataContract(Name="LinkItem",Namespace= "http://schemas.thatindigogirl.com/samples/2007/07")] public class LinkItem { // fields [DataMember(Name="DateStart", IsRequired = true, Order = 3)] public DateTime DateStart { get { return m_dateStart; } set { m_dateStart = value; } } [DataMember(Name="Description", IsRequired = true, Order = 2)] public string Description {} [DataMember(Name="Id", IsRequired = false, Order = 0)] public long Id {} [DataMember(Name="Title", IsRequired = true, Order = 1)] public string Title {} // other properties }

Data Contract Schema


Explicit Ordering, Required Elements
<xs:complexType name="LinkItem"> <xs:sequence> <xs:element name="Id" minOccurs="0" 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 name="DateEnd" minOccurs="0" type="xs:dateTime" /> <xs:element name="Url" minOccurs="0" nillable="true" type="xs:string" /> </xs:sequence> </xs:complexType>

Known Types
Known types enable polymorphic behavior in service contracts Expose base types in service operations Associate known types
To the base types themselves To particular operations To the service contract as a whole

Use declarative attributes or configuration settings

KnownTypeAttribute
[DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2007/07")] [KnownType(typeof(GigInfo))] [KnownType(typeof(PhotoLink))] [KnownType(typeof(MP3Link))] public class LinkItem [DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2007/07")] public class GigInfo: LinkItem [DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2007/07")] public class PhotoLink: LinkItem [DataContract(Namespace = "http://schemas.thatindigogirl.com/samples/2007/07")] public class MP3Link: LinkItem

Demonstration Three

Known types

ServiceKnownTypeAttribute
[ServiceContract(Name = "GigManagerContract", Namespace = "http://www.thatindigogirl.com/samples/2007/07")] [ServiceKnownType(typeof(GigInfo))] [ServiceKnownType(typeof(PhotoLink))] [ServiceKnownType(typeof(MP3Link))] public interface IGigManagerService { [OperationContract] void SaveLink(LinkItem item); [OperationContract] LinkItem GetLink(string id); }

ServiceKnownTypeAttribute
[ServiceContract(Name = "GigManagerContract", Namespace = "http://www.thatindigogirl.com/samples/2007/07")] public interface IGigManagerService { [OperationContract] [ServiceKnownType(typeof(GigInfo))] void SaveGig(LinkItem item); [OperationContract] [ServiceKnownType(typeof(GigInfo))] LinkItem GetGig(string id); }

<declaredTypes>
<system.runtime.serialization> <dataContractSerializer> <declaredTypes> <add type="ContentTypes.LinkItem, ContentTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <knownType type="ContentTypes.GigInfo, ContentTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <knownType type="ContentTypes.MP3Link, ContentTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <knownType type="ContentTypes.PhotoLink, ContentTypes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </add> </declaredTypes> </dataContractSerializer> </system.runtime.serialization>

Code-First vs. Contract-First


In a perfect WCF world:
Create data contracts that also function as business objects Expose in service contracts

In reality:
May not own objects (cant make serializable) Business object serialization may not be appropriate May need to support pre-existing schemas

IXmlSerializable
IXmlSerializable types provide XSD schema to Web Services Description Language (WSDL) and metadata exchange (MEX)
Contract-first support

You handle mapping between XML and business objects


Requires knowledge of XML Provide appropriate validation

Less overhead than using interim data contracts

IXmlSerializable
IXmlSerializable
Valid in service contract (like data contract)

Hook serialization process:


IXmlSerializable.ReadXml() IXmlSerializable.WriteXml()

XmlSchemaProviderAttribute
Improvement on IXmlSerializable.GetSchema() Return schema for WSDL and MEX

Demonstration Four

IXmlSerializable

Agenda
Contracts and metadata Service contracts Complex type serialization
Serializable types, data contracts, known types, IXmlSerializable

Message contracts Summary of approaches

Message Contracts
MessageContractAttribute
Greater control over message headers and body elements

Supporting attributes:
MessageHeaderAttribute MessageBodyMemberAttribute

Useful for:
Add custom headers Control message wrapping Control signing and encryption

MessageContractAttribute
Converts a type to a SOAP message
Type can contain header and body elements

Can set IsWrapped, ProtectionLevel May set explicit Name, Namespace


[MessageContract(IsWrapped=true, ProtectionLevel=ProtectionLevel.Sign)] public class SaveLinkRequest {} [MessageContract] public class SaveLinkResponse {}

MessageHeaderAttribute
Apply to fields or properties of message contract
Simple technique for creating custom headers

Can provide Name, Namespace, ProtectionLevel May set SOAP protocol settings: Relay, Actor, MustUnderstand

MessageBodyMemberAttribute
Apply to fields or properties of message contract Can have several body elements
Equivalent to multiple parameters in operation Only way to return multiple complex types

Always supply Order Can set Name, Namespace, ProtectionLevel

[MessageContract(IsWrapped=true, ProtectionLevel=ProtectionLevel.Sign)] public class SaveEventRequest { private string m_licenseKey; private LinkItem m_linkItem; [MessageHeader(ProtectionLevel = ProtectionLevel.EncryptAndSign)] public string LicenseKey { get { return m_licenseKey; } set { m_licenseKey = value; } } [MessageBodyMember] public LinkItem LinkItem { get { return m_linkItem; } set { m_linkItem = value; } } } [MessageContract] public class SaveEventResponse { }

Applying Message Contracts


Message contracts are supplied as operation parameter or return value Must contain serializable members
Data contracts or serializable types
[ServiceContract(Name = "ContentManagerContract", Namespace="http://www.thatindigogirl.com/samples/2007/07")] public interface IContentManagerService { [OperationContract] SaveLinkResponse SaveLink(SaveLinkRequest message); [OperationContract] GetLinkResponse GetLink(GetLinkRequest message); }

Applying Message Contracts


In the generated client proxy, custom message headers are added as parameters to operations
Not optional
LinkItem item = new LinkItem(); // initialize item string licenseKey = "XXX"; m_proxy.SaveLink(licenseKey, item);

Applying Message Contracts


At the service, message headers are processed as member of the message contract Message body elements also available through message contract
public SaveLinkResponse SaveEvent( SaveLinkRequest message) { if (message.LicenseKey != "XXX") throw new FaultException<string>("Invalid license key."); m_linkItem = message.LinkItem; return new SaveLinkResponse(); }

Agenda
Contracts and metadata Service contracts Complex type serialization
Serializable types, data contracts, known types, IXmlSerializable

Message contracts Summary of approaches

WCF Contracts Summary


Service contracts define available operations and signatures Data contracts and other serializable types can be included in service contract Known types enable polymorphic contracts Message contracts are useful for custom headers and other advanced requirements

For More Information


My blog: www.dasblonde.net IDesign resources: www.idesign.net Learning WCF: A Hands-on Guide by Michele Bustamante (O'Reilly Media, Inc., 2007) Book blog: www.thatindigogirl.com

Questions and Answers


Submit text questions using the Ask button. Dont forget to fill out the survey. For upcoming and previously live webcasts:
www.microsoft.com/webcasts

Got webcast content ideas? Contact us at:


http://go.microsoft.com/fwlink/?LinkId=41781

Today's webcast was presented using Microsoft Office Live Meeting. Get a free 14-day trial by visiting: www.microsoft.com/presentlive

Вам также может понравиться