con 413 justin smith technical evangelist

47

Upload: robert-reynolds

Post on 25-Dec-2015

220 views

Category:

Documents


1 download

TRANSCRIPT

WCF Architecture and Extensibility Points

CON 413

Justin SmithTechnical Evangelisthttp://blogs.msdn.com/justinjsmith

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

Receiver

Channels

WCF Architecture: Layers of Layers

Sender

Proxy

Sender Application

Dispatcher

Receiver Application

Channel Layer

ServiceModel Layer

Channels

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

What is a Binding?

Abstraction of messaging functionalityTransport, security, transaction options, protocols

Creates a collection of BindingElement objects

Arrangement in collection is importantNetTcpBinding b = new NetTcpBinding();foreach (BindingElement el in b.CreateBindingElements()) { Console.WriteLine(el.GetType().Name);}

// outputsTransactionFlowBindingElement // protocolBinaryMessageEncodingBindingElement // encodingWindowsStreamSecurityBindingElement // securityTcpTransportBindingElement // transport

What is a BindingElement?

Create Channel Listeners & Channel Factories

listeners on receiver / factories on sendercollectively known as Channel Managers

Collection creates a stack (listeners/factories)

via BindingContext and CustomBinding typesBindingContext keeps a mutable list of BindingElement objects in CollectionCustomBinding is isomorphic

Channel Factory Stack

BindingContext

CustomBinding

Walkthrough : Channel Factory

NetTcpBinding

TransactionFlowBindingElementBinaryMessageEncodingBindingElem

entWindowsStreamSecurityBindingElem

entTcpTransportBindingElement

BuildChannelFactory<T>

Bu

ildIn

nerC

han

nelF

act

ory

<T

>

TcpChannelFactory<T>

TransactionFlowChannelFactory<T>

Encoding and StreamSecurity absorbed by TcpChannelFactory via

BindingContext

Walkthrough : Channel Factory public abstract class Binding : IDefaultCommunicationTimeouts { public virtual IChannelFactory<T> BuildChannelFactory<T> ( BindingParameterCollection parameters) { BindingContext context1 = new BindingContext(new CustomBinding(this), parameters); IChannelFactory<T> factory1 = context1.BuildInnerChannelFactory<T>(); return factory1; } // creates BindingContext, then calls BuildInnerChannelFactory}

public class BindingContext { public IChannelFactory<T> BuildInnerChannelFactory<T>() { return this.RemoveNextElement().BuildChannelFactory<T>(this); } // removes B.E. from list, then calls BuildChannelFactory on it}

public class MyBindingElement : BindingElement { public virtual IChannelFactory<T> BuildChannelFactory<T>(BindingContext c) { return new MyChannelFactory<T>(c); // ctor calls context’s } // returns the Channel Factory // BuildInnerChannelFactory}

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

What is a Channel Factory?

Create sending ChannelsStack of Channel Factories creates Channel stack

Channel Factory stack is opaqueGetProperty<T> allows some query capabilities

Each Channel Factory in stack:Refers to the next Channel FactoryDelegates GetProperty<T> calls when unknown

EndpointAddress needed in channel stackUri for Via can be used as well

What is a Channel Listener?

Listens for incoming messages & Creates receiving channel stacksBottom-most Channel Listener listens on transport

Embrace “Accept” semantics similar to sockets“Accept” returns a

Channel Listener stacks are opaqueSymmetry with Channel Factory design

Channel Stack

CreateChannel

Channel Factory Stack

Walkthrough : Channel Stack

TcpChannelFactory<T>

TransactionChannelFactory<T>

CreateChannel

TcpChannel<T>

TransactionChannel<T>

From a Channel Factory:

From a Channel Listener:

Channel Listener Stack

TcpChannelListener

TransactionChannelListener

AcceptChannel

Channel Stack

TcpChannel<T>

TransactionChannel<T>AcceptChannel

message passing to channel stack not precise

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

What is a Channel?

Sends and/or receives Message objectsFor specific transport or protocol functionalityCommonly stacked w / other Channel objectsHave shape described by interfaces

MEP (datagram, request/reply, duplex)Composition of channel stack dictates messaging functionality

Consider WS-RM

Sender Receiver

CreateSequence

CreateSequenceResponse (ID)

XSequence (ID, Msg #2)

Sequence (ID, Msg #1)

Sequence (ID, Msg #3, LastMessage)

SequenceAck (ID, Msg #1, Msg #3)

Sequence (ID, Msg #2, AckRequested)

SequenceAck (ID, Msg #1 - Msg #3)

TerminateSequence (ID)

Sending Application

Channel Stack

Receiving Application

Sequence (#2, LastMessage)

CreateSequence / CreateSequenceRespons

eSequence (#1)Ack (Msg #1-2)

Client

Walkthrough: WS-RM

HttpRequestChannel<T>

ReliableOutputSessionChannelTerminateSequence

MEPs and The Channel Layer

Channel Managers and Channels have shapeShape represents the supported MEP(s)

Datagram, Request/Reply, DuplexWCF represents shape via interfaces

Datagram: IInputChannel, IOutputChannelRequest / Reply: IRequestChannel, IReplyChannelDuplex: IDuplexChannelSessionful variants also exist

Interfaces have common type hierarchy

Shapes and Interfacespublic interface IInputChannel : IChannel, ICommunicationObject { Message Receive(); // standard Begin / End methods also exist (and timeouts)...}

public interface IOutputChannel : IChannel, ICommunicationObject { void Send(Message msg); // standard Begin / End methods also exist (and timeouts)...}

public interface IDuplexChannel : IInputChannel, IOutputChannel, IChannel, ICommunicationObject { }

public interface IRequestChannel : IChannel, ICommunicationObject { Message Request(Message msg); // standard Begin / End methods also exist (and timeouts)...}

// IReplyChannel omitted for clarity

ICommunicationObject

Channels and Channel Managers have a common state machine (also Faulted state)

Predictable state transitions

Created Opening Opened Closing Closed

Abort()

Abort()

Open() Close()

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcherBehaviors

The Message Type

Fundamental unit of communicationChannel layer interacts with Message objectsSeldom surfaces to the contract

CLR abstraction of a SOAP messageBody can be streamed, headers buffered

Can do non-SOAP formats (POX, JSON)public abstract class Message : IDisposable { public static Message CreateMessage(MessageVersion v, String a) {…} // lots of factory methods public void WriteMessage(XmlDictionaryWriter writer) {} // lots of write and read methods public abstract MessageHeaders Headers { get; }}

Envelope / Addressing Versions

EnvelopeVersion identifies SOAP specs1.1, 1.2, none

AddressingVersion identifies WS-Addressing

Aug 2004, 1.0, noneMessageVersion wraps bothNone == no SOAP please

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

XmlDictionaryWriter

An abstract type derived from XmlWriter

Wraps a System.IO.StreamCreated via factory methods

Specialized for binary, MTOM, text, JSON

MemoryStream stream = new MemoryStream();XmlDictionaryWriter dictionaryWriter = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8, false);dictionaryWriter.WriteElementString("localname", “http://namespace", "someValue");dictionaryWriter.Flush();

XmlDictionaryReader

An abstract type derived from XmlReader

Wraps a System.IO.Stream or bufferCreated via factory methods

Specialized for binary, MTOM, text, JSON

// Continued from previous slidestream.Position = 0;

XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(stream);reader.Read();Console.WriteLine(reader.ReadOuterXml());

Encoding Sample - Text

MemoryStream stream = new MemoryStream();using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8, false)) { writer.WriteStartDocument(); writer.WriteElementString(“SongName”, “urn:ContosoRockabilia”, “Aqualung”); writer.Flush();}// then read from Stream 

XmlDictionaryWriter (Text-UTF8) wrote 97 bytes3C-3F-78-6D-6C-20-76-65-72-73-69-6F-6E-3D-22-31-2E-30-22-20-65-6E-63-6F-64-69-6E-67-3D-22-75-74-66-2D-38-22-3F-3E-3C-53-6F-6E-67-4E-61-6D-65-20-78-6D-6C-6E-73-3D-22-75-72-6E-3A-43-6F-6E-74-6F-73-6F-52-6F-63-6B-61-62-69-6C-69-61-22-3E-41-71-75-61-6C-75-6E-67-3C-2F-53-6F-6E-67-4E-61-6D-65-3E

data read from stream:<?xml version="1.0" encoding="utf-8"?><SongName xmlns="urn:ContosoRockabilia"> Aqualung</SongName>  

Encoding Sample - Binary

MemoryStream stream = new MemoryStream();using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream, null, null)) { writer.WriteStartDocument(); writer.WriteElementString(“SongName”, “urn:ContosoRockabilia”, “Aqualung”); writer.Flush();}// then read from Stream 

XmlDictionaryWriter (Binary) wrote 43 bytes3F-08-53-6F-6E-67-4E-61-6D-65-04-15-75-72-6E-3A-43-6F-6E-74-6F-73-6F-52-6F-63-6B-61-62-69-6C-69-61-A1-08-41-71-75-61-6C-75-6E-67

data read from stream:N/A 

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

From Message to the Wire

Known as EncodingVia MessageEncoder and XmlWriter

MessageEncoder use Message.WriteMessageMessage.WriteMessage uses XmlWriter

public class MyEncoder : MessageEncoder { public override void WriteMessage(Message msg, Stream stream){ XmlWriter writer = XmlWriter.CreateWriter(stream); msg.WriteMessage(writer); writer.Flush(); } // other members omitted}

From the Wire to Message

Known as DecodingDone via ReadMessage

uses one of the Message.CreateMessage overloadsCreateMessage overload accepts an XmlReader

public class MyEncoder : MessageEncoder { public override Message ReadMessage(Stream st, Int32 s, String ct){ XmlReader reader= XmlReader.Create(st); MessageVersion version = MessageVersion.Soap12WSAddressing10; return Message.CreateMessage(reader, s, version); } // other members omitted}

Channel

Message Encoder

Channel

Message Encoder

Wri

teM

ess

ag

e

Walkthrough: Message-Wire-Message

Sender Receiver

Message

XmlWriter

Message

ReadM

ess

ag

e XmlReaderBytes

Bytes

Message

Channel Layer Service

demo

Agenda

BindingsChannel ManagersChannelsMessagesXmlWriters and XmlReadersMessage EncodersDispatcher and Behaviors

About the Dispatcher

In the abstract, the Dispatcher hides from the receiver the fact that the receiving application is receiving messagesThe Dispatcher is the realm of the contractMessages go in, Parameters come out, and a method is invoked

Receiver

Dispatcher

Receiving Application

Protocol / Shaping / Transport Channels

Parameters

Extending the Dispatcher Overview

Message Inspection

Service BehaviorsOperation Selector

Message Formatting

Operation Invoker

Channel

Method1(…)

DispatchOperation

Method2(…)

DispatchOperation

DispatchRuntime

Parameter Inspection

Operation Behaviors

Important Types for Extending the Dispatcher

To extend the Dispatcher, define a type that implements one of the followingIOperationInvoker

Invokes method on target objectIDispatchMessageFormatter

to control format of the MessageIDispatchOperationSelector

to select operation on target objectIDispatchMessageInspector

to inspect the MessageIParameterInspector

Steps to Extend the Dispatcher1. Define a type that implements one of the

previous interfaces2. Define a type that implements one of the

Behavior interfaces and instantiates the type in Step # 1

3. Add the Behavior from Step #2 to the description via the appropriate place in the ServiceDescription

4. OPTIONAL – add configuration support5. OPTIONAL – add support for attribute

annotation

IOperationInvoker

Enables control over the invocation of a method on the receiving object

public interface IOperationInvoker { bool IsSynchronous { get; } object[] AllocateInputs(); object Invoke(object instance, object[] inpts, out object[] outputs); IAsyncResult InvokeBegin(object instance, object[] inpts, AsyncCallback cbck, object state); object InvokeEnd(object instance, out object[] outputs, IAsyncResult result);}

IDispatchMessageFormatter

Enables control over received Message deserialization and outbound Message serializationSerializeReply returns a serialized Message objectDeserializeRequest returns an Object deserialized from the MessageMessageVersion fed from the BindingSerializeReply is not invoked if operation is OneWay

public interface IDispatchMessageFormatter { void DeserializeRequest(Message msg, object[] parameters); Message SerializeReply(MessageVersion version, object[] parameters, object result);}

IDispatchOperationSelector

Enables the selection of a particular DispatchOperationSelectOperation returns the name of the method associated with the DispatchOperation

Normally loaded from the ContractDescription

public interface IDispatchOperationSelector { String SelectOperation(ref Message message); }

IDispatchMessageInspector

Enables a last view of the Message before it is sent into the Channel stack and at the point when the reply surfacesNotice that the Message is passed by reference

Be careful of Message state transitionsRequest and Reply messages can be correlated manuallyIf the operation is OneWay, BeforeReceiveReply not invoked

public interface IDispatchMessageInspector { Object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext);

void BeforeSendReply(ref Message reply, object correlationState);}

IParameterInspector

Enables the inspection of parameters before the request is deserialized or the reply is serializedBeforeCall invoked before the Message is deserialized into parametersAfterCall invoked after the reply is sent

If the operation is a OneWay operation, then AfterCall is not invoked

BeforeCall and AfterCall can be correlated via an Object

public interface IParameterInspector { void AfterCall(String operationName, Object[] outputs, Object returnValue, Object correlationState);

Object BeforeCall(String operationName, Object[] inputs);}

What Order Are Interceptors Invoked?

IDispatchOperationSelector

IDispatchMessageInspector

IOperationInvoker

IDispatchMessageFormatter

IDispatchMessageInspector

IDispatchMessageFormatter

IParameterInspector

Sender

IParameterInspector

IOperationInvoker

Behaviors

demo

Evaluation Forms

Questions?