wcf extensibility
DESCRIPTION
WCF Extensibility. Scott Reed Owner - Brain Hz Software [email protected] Instructor – DevelopMentor [email protected]. WCF Design Goal. To be the single best way of getting any two pieces of software to communicate under any circumstances (assuming at least one is .NET). - PowerPoint PPT PresentationTRANSCRIPT
WCF Design Goal
• To be the single best way of getting any two pieces of software to communicate under any circumstances (assuming at least one is .NET)
Extensibility in a nutshell
• WCF doesn’t support everything out of the box
• When a limitation is reached WCF can still be used by adding or replacing a specific piece of the framework
• (Almost) everything can be extended• Infinitely flexible = more difficult than it needs
to be
BC A
BC A
B CA
B CA
B CA
Client Service
Service
Client Runtime
Channel
Channel
TransportChannel
byte[]
DispatcherRuntime
Client Codeparameters
Encoder
Service Typeparameters
Channel
Channel
TransportChannel
byte[]
Encoder
Service Model Layer
Channel Layer
ServiceHost
ChannelDispatcher
EndpointDispatcher
DispatchRuntime
DispatchOperation
ChannelStack
IChannel (Protocol)
IChannel (Protocol)
IChannel (Transport)
Behavior extensibility steps
1) Implement the functionality– MessageInspector, ErrorHandler, InstanceProvider, etc.
2) Hook up the functionality through behavior– ServiceBehavior, EndpointBehavior, OperationBehavior
3) Let WCF know about the behavior from #2– Programmatically, configuratively, declaratively
When Behaviors Run
1. Reflect Over T
2. Load Config
.Description
.Open();
ServiceHost() or ChannelFactory()
3. Build Runtime
4. Open Resources
Behaviors
[MyBehavior]
<myBehavior />
.Description.Behaviors.Add(new MyBehavior());
Three Behaviors
• All three behavior types have the same methods:
public void AddBindingParameters(<description>, BindingParameterCollection);
public void ApplyClientBehavior(<description>, <client plumbing>);*
public void ApplyDispatchBehavior(<description>, <service plumbing>);
public void Validate(<description>);
* ApplyClientBehavior isn’t present in IServiceBahvior
ParameterInspectors
public interface IParameterInspector{ object BeforeCall(string operationName, object[] inputs); void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);}
Parameter InspectionUseful for consistent client and service side validation
Client Operation Client Runtime Channel
public interface IClientMessageFormatter{ Message SerializeRequest(MessageVersion messageVersion, object[] parameters); object DeserializeReply(Message message, object[] parameters);}
Message FormattingActually creates the message from parameters, and breaks apart the message into parameters and return value.
Formatter
Client Operation Client Runtime Channel
public interface IClientMessageInspector{ object BeforeSendRequest(ref Message request, IClientChannel channel); void AfterReceiveReply(ref Message reply, object state);}
Message InspectionThe most useful, allows last minute manipulation of the message before being sent into the channel layer.
MessageInspectors
Client Operation Client Runtime Channel
Other client side extension points
• Via (sends to intermediaries)• ChannelInitializers (manipulate channel stack)
• But the service has far more extensibility…
Demo
• Client side message inspector• Adding a behavior extension element
Error Handling
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IErrorHandler{ bool HandleError(Exception error); void ProvideFault(Exception error, MessageVersion version, ref Message fault);}
Error Handlers
Allows a central place to perform exception to fault message translation.
Address / Contract Filtering
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public abstract class MessageFilter{ IMessageFilterTable<FilterData> CreateFilterTable<FilterData>(); bool Match(Message message);}
AddressFilter
ContractFilter
Allows the messages to be matched to an appropriate dispatch runtime.
Providing InstanceContext
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IInstanceContextProvider{ InstanceContext GetExistingInstanceContext(Message message, IContextChannel channel); void InitializeInstanceContext(InstanceContext instanceContext, Message message, IContextChannel channel); bool IsIdle(InstanceContext instanceContext); void NotifyIdle(InstanceContextIdleCallback callback, InstanceContext instanceContext);}
InstanceContextProvider
Allows special case instancing modes
Providing Instance
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IInstanceProvider{ object GetInstance(InstanceContext instanceContext,Message message); void ReleaseInstance(InstanceContext instanceContext,object instance);}
InstanceProvider
Allows service object pooling
Message Inspection (again)
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IDispatchMessageInspector{ object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext); void BeforeSendReply(ref Message reply, object correlationState);}
MessageInspectors
The most useful, allows manipulation of the message right after being received from the channel layer.
Operation Selection
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IDispatchOperationSelector{ string SelectOperation(ref Message message);}public SynchronizedKeyedCollection<string, DispatchOperation> Operations { get { } }
OperationSelector
Allows operation selection by something other than Action
Message Formatting (again)
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IDispatchMessageFormatter{ void DeserializeRequest(Message message, object[] parameters); Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result);}
Formatter
Actually creates the message from parameters, and breaks apart the message into parameters and return value.
Operation Invocation
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IOperationInvoker{ object[] AllocateInputs(); object Invoke(object instance, object[] inputs, out object[] outs); IAsyncResult InvokeBegin(object instance, object[] inputs, ...); object InvokeEnd(object instance, out object[] outputs, ...);}
Invoker
Actually takes control of calling the service object.
Parameter Inspection (again)
DispatchOperationDispatchRuntimeEndpointDispatcherChannelDispatcher
public interface IParameterInspector{ object BeforeCall(string operationName, object[] inputs); void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);}
ParameterInspectors
Useful for consistent client and service side validation.
Other service extensibility points• Extensions• ChannelInitializers• ServiceThrottle• ExternalAuthorizationPolicies• RoleProvider• ServiceAuthorizationManager• InputSessionShutdownHandlers• InstanceContextInitializers• FaultContractInfos• CallContextInitializers• Etc...
Demo
• Service side error handler
Channel Layer extensibility
• Easy ways:– Binding configuration– Programmatic binding manipulation– Custom bindings
• Hard way– Writing a protocol channel
• Really hard way– Writing a transport channel
Writing a Channel (Overview)
• To write a channel, you must– Write the channel itself
• Support the proper “shapes”– Input, Output, Duplex, Request, Reply, RequestContext
• Possibly provide asynchronous versions of all method– Write a ChannelFactory– Write a ChannelListener– Write a BindingElement
Extensibility Summary
• If possible stick with Service Model layer– There are tons of extension points– It’s not that hard to do
• If you have to write a channel– Plan on spending a couple of weeks