February 2010 - Posts
I decided to blog about common questions I receive regarding WCF Contrib.
You can find all questions in the WCF Contrib FAQ.
Communication Patterns
- What's the best practice for web applications that call services?
Research has shown that in concurrent environments such as web it is more scalable and has better performance to use a dedicated communication object per a sequence of invocations (sequential - one call after another in the same execution chain flow).
It's important to note that for few users, you may notice that using a single communication object to address them all may work faster, however, as soon as more requests come in you should see a noticeable decrease in your application performance, which is bad.
In essence, you should use the singleton instance for single calls or instantiate a new client channel with Sequential/SequentialAsyncOwnChannel to perform a sequence of calls at a given time and dispose it when you're done with it.
Client Channel
- When should I set the GlobalEndpointName?
ClientChannel<T>.GlobalEndpointName = "myEndpointName";
This needs to be set only once since it's the global name that will be used for all client channels created for the specific 'T' contract.
It is usually placed in the process main entry point.
Note that in WCF Contrib v2.1, if you have a single endpoint in the configuration for the given contract, you don't have to specify the endpoint name at all, it will pick it up automatically.
- When should I call LoadRuntime?
ClientChannel<T>.LoadRuntime();
This also needs to be called once, it too will usually be placed in the process main entry point.
It is a good practice that you call it whenever you can spare time to load the runtime behavior information, this isn't a necessity though. If you don't call it the infrastructure will automatically load the runtime information upon first access.
- Is disposing the singleton instance mandatory?
using (ClientChannel<T>. Instance) { }
The implementation of IDisposable in the client channel disposes the channel factory and communication object associated with the client channel.
The necessity of calling the dispose depends on the channel management mode.
The singleton instance is set with SingleCall, this means that behind the scenes upon every call a communication object is created and terminated right after.
That indicates it is not a necessity to call the dispose for such management mode. (The dispose of the factory isn't critical in this point since it just disposes the communication objects associated with it which were already disposed by the client channel infrastructure)
As a general approach, I'd say "If it's IDisposable and you're done with it, dispose it".
If you have control at your application/process exit point and you know which client channels you were using, I don't see a reason not disposing it.
Via Entity Designer Database Generation Power Pack
A power pack for Model-First design approach in Entity Framework for Visual Studio 2010.
It builds on the new EF4 extensibility points (WF & T4) and provides the following:
- Basic Table-per-Hierarchy support. This is represented by the “Generate T-SQL via T4 (TPH)” workflow.
- The SSDL and MSL generation pieces can now be tweaked through T4 templates, both in TPH and TPT strategies through the “Generate T-SQL via T4 (TPT)” and “Generate T-SQL via T4 (TPH)” workflows.
- Direct deployment and data/schema migration are available through the “Generate Migration T-SQL and Deploy” workflow. This workflow will use the Team System Data APIs to diff our default T-SQL script against the target database and create a new script which will perform non-invasive ALTERs and data migration where necessary.
- A new user interface will now display when “Generate Database from Model” is selected – this acts as a “workflow manager” which will present to you our default workflows and allow you to create your own, customizable workflows based on your own strategy, script generation, and deployment requirements.
Be sure to check the link above if you’re interested.
Via http://wcfcontrib.codeplex.com/wikipage?title=ClientChannelOutputCache
Output Cache Provider Factory
This is the factory class that is responsible for creating the actual output cache provider.
This is where you extensibility point kicks in, you can replace the built-in factory with your own, read about it here.
The factory needs to have a public parameter-less constructor and implement 'IOutputCacheProviderFactory'
public interface IOutputCacheProviderFactory
{
IOutputCacheProvider CreateProvider();
}
As you can see, this is a simple factory interface for providing the actual provider implementation.
Output Cache Provider
Output cache provider is where the magic really happens.
This is where you should implement your custom output caching solution if you like.
public interface IOutputCacheProvider
{
void AddItem(OutputCacheItemKey key, OutputCacheInterval interval, object value);
bool TryGetItem(OutputCacheItemKey key, out object value);
}
- AddItem - this method is supposed to add a new item to the output cache solution.
- TryGetItem - this method should look up the output cache solution for the item that was stored.
- OutputCacheInterval - you're getting the desired interval as a parameter.
- Consider setting the fields "LastVisitedAt" and "AddedAt" to the proper values at a given time so you can reference it later.
- You can use "IsActive()" method if you like to check whether the interval is active for the current time according to its policy and time properties.
Note: If the provider implements IDisposable, it will be disposed once the OutputCacheController is disposed.
The built-in provider is called "IntervalBasedCacheProvider", it is important to know this since this too is written in a reusable way where you can plug-in your custom store.
The provider gets two parameters in its constructor:
- purgeTimerIntervalInMilliseconds - The interval in milliseconds for the timer that is in charge of iterating the items and purging those which are inactive.
- store - An implementation for IOutputCacheStore
- AddItem - The provider basically saves the key and interval in its local state, sets the time properties of the interval to the current time and adds the item to the store.
- TryGetItem - When an item is requested from the cache, the provider checks if there's an active key in its local state, if so, sets the last visited time to the current time and gets the item from the store.
- Removing Items - In the timer callback, it iterates the keys in its local state and removes the inactive ones from the store
Output Cache Store
The store is responsible for storing the items.
public interface IOutputCacheStore
{
void SetItem(OutputCacheItemKey key, object value);
void RemoveItem(OutputCacheItemKey key);
bool TryGetItem(OutputCacheItemKey key, out object value);
}
The store that is provided with the built-in solution is using the SynchronizedDictionary that is a part of WCF Contrib as well.
Implementing your own custom output caching solution
You can go about it in two ways:
- Plug-in your own factory and provider and implement a different scenario - you can use this approach to write a provider that uses an interval-based caching solution such as HttpRuntime Caching, Enterprise Library, etc
- Plug-in your own factory and still use the built-in IntervalBasedCacheProvider only with your own custom store, such as a AppFabric caching, file-system, database, etc
Output Cache Item Key
It's important to recognize the description of the item keys if you like to implement you own solution since you will need a way a way to correlate between the item and key.
- The key contains the operation action and parameters and custom equality comparers if any were provided.
- It can be used as a dictionary key since it overrides Equals and GetHashCode by calculating it over the action and parameters using the appropriate comparer.
- ToString() is also overriden to return the aggregation of the action and parameters.
Via http://wcfcontrib.codeplex.com/wikipage?title=ClientChannelOutputCache.
A new feature that arrived at WcfContrib v2.1 Feb10 Beta.
You can use the output caching to cache the operation output with the setting of your desire.
This is extremely useful and may save you quite some time from building client caching stores.
The built-in mechanism implemented here is In-Proc in-memory cache using the synchronized dictionary that comes with WcfContrib as well.
You can fully customize it and change the underlying provider or store. (E.g. EntLib/ASP.NET Caching/AppFabric caching/Database/File system and whatnot)
If the result is present in the cache and is still active according to its policy and interval, this result is returned without going through the WCF pipeline whatsoever which enables very good performance.
Usage Guideline
If you're using the output caching feature, you should dispose the controller instance at your process exit point:
using (OutputCacheController.Current) { }
Features
- Output Cache on several elements - The behavior can be attached to a client channel for either a specific client channel instance or contract or specific operations.
- Different cache policies - Absolute / Sliding / Indefinite.
- Ignore Default Value - There may be services which return null when a certain entity isn't found for example, in this case you can use this mode to avoid caching it so next time it will still call the service to try and fetch the entity. (defaults to false)
- Compare Enumerable Items - When set to true (the default), A custom equality comparer will be used with IEnumerable parameters since in this case you usually don't want to check equality by reference.
- Equality Comparers - You can provide your own set of equality comparers to be used, this is index-based.
- Provider Factory Model - The model is fully customizable
What is NOT supported
The behavior doesn't support operations with out/ref parameter definitions.
This is due to the fact that the 'IClientOperationInvokerBehavior' (the core implementation for this behavior) wasn't designed while taking this into account in the first place.
This will be addressed in a future release.
Usage Scenarios
Contract-level Definition [ServiceContract]
//This will affect only 'Do' in this case since the other operations have the behavior set explicitly on them
[OutputCacheBehavior(OutputCachePolicy.Absolute, 3000)]
interface IService
{
[OperationContract]
void Do(Foo foo);
[OperationContract]
[OutputCacheBehavior(OutputCachePolicy.Sliding, 2000)]
Foo GetFoo1();
//
//Both the synchronous and asynchronous need to be tagged with the behavior,
//It will use the same underlying source for both of them, no worries.
[OperationContract(AsyncPattern = true)]
[OutputCacheBehavior(OutputCachePolicy.Sliding, 2000)]
IAsyncResult BeginGetFoo1(AsyncCallback callback, object asyncState);
Foo EndGetFoo1(IAsyncResult result);
}
Client-channel based definition:
ClientChannel<IService> myChannel = new ClientChannel<IService>(...);
//Add output cache to a specific operation
//You can add it to the entire description or contract behaviors which
//will affect all operations that were not set with the behavior explicitly on them
//You can also change the description of the global instance (ClientChannel<IService>.Instance)
myChannel.Description.Contract.Operations[0].Behaviors.Add(new OutputCacheBehaviorAttribute(...));
Derived ClientChannel definition:
You can attach the behaviors in the InitializeRuntime or through attributes on your own derived client channel.
For more information see ClientChannel documentation file on the Client Channel Extensions model.
Customizing the output cache provider
I will explain about it in a future post
Via http://wcfcontrib.codeplex.com/wikipage?title=WcfContribConfigurationSection.
Full-Blown Configuration
<configuration>
<configSections>
<section name="wcfContrib" type="WcfContrib.Configuration.WcfContribConfigurationSection, WcfContrib" />
</configSections>
<wcfContrib>
<client applyBoosting="true" />
<services applyBoosting="true" />
<extensions>
<logTrace logFolderPath="C:\MyLogsFolder\" />
<outputCache providerFactoryTypeName="MyOutputCacheProviderFactoryTypeName" />
</extensions>
</wcfContrib>
</configuration>
Client
Apply Boosting You can configure the default value of the "ApplyBoosting" of all Client Channels (defaults to 'false').
Boosting is a common need for internal communications, it sets all the following to the maximum value:
- MaxItemsInObjectGraph
- Buffer sizes, MaxReceivedMessageSize and Reader Quotas. Please note this is set upon known standard bindings. If you're using a different binding or a custom one you need to apply it yourself.
Services
Apply Boosting You can configure the default value of the "ApplyBoosting" of all the hosts using the Service Host that comes with WcfContrib (defaults to 'false').
- Increases throttling to a large number ONLY if it has the default throttling, meaning if the developer hasn't set it to something else.
- MaxItemsInObjectGraph
- Buffer sizes, MaxReceivedMessageSize and Reader Quotas. Please note this is set upon known standard bindings. If you're using a different binding or a custom one you need to apply it yourself.
Extensions
Log Trace You can configure settings related to logging and tracing extensions.
- logFolderPath - Change the folder path used for the tracing and logging files. (The default is writing it to the same location as the Entry assembly)
Output Cache You can configure settings related to the output caching extension.
- providerFactoryTypeName - You can set the type name for your custom output cache provider factory
I am happy to announce a new version of WcfContrib was published today.
It has been tested and it is stable. However, there were some core optimizations so this is considered to be a small test-run to make sure it is alright before tagging it as a stable release.
Please provide feedback, your input is important.
Changes from last version:
- New Output Caching module for Client Channel – Very useful feature!
- New behavior attributes and extension elements (ActivationContextInitializerAttribute, ActivationContextExtensionBehaviorElement, ErrorContextHandlerExtensionElement)
- A userful commonly-needed synchronized (thread-safe) dictionary was added: SynchronizedDictionary
- Internal Optimizations and Mode Fixes. (Sequential channel management option work with asynchronous operations now)
- ChannelInvokeContext was made an extensible object
- Client Channel supports default single endpoint - No need to specify an endpoint name of the client endpoint in the configuration if there is only one for the specific contract
- Configuration-less services hosting API improvements
- When deriving from ClientChannel, you can override OnChannelFactoryCreated (new method) to apply anything you need.
Updated Showcases from last time:
- Miscellaneous - Configuration Section - A sample of the new Configuration Section
- ClientChannel - Basic - Simple comment indicating the ApplyBoosting can be set globally through the new configuration section.
- Services - Hosting - Simple comment indicating the ApplyBoosting can be set globally through the new configuration section.
- Services - Service Extensions - Simple comment indicating about the new behavior attributes and extension elements you can use to apply the extensions declarative or in configuration.
- Services - Service Error Logging - An example for attaching the behavior in the configuration using the new extension element was added.
- Client Channel - Output Caching - A new sample was added demonstrating the basic usage of the output caching
I plan to write a series of posts demonstrating the features and implementations of WCF Contrib.
This isn’t a graphical control library but rather a communication library, thus I understand the need for proper documentation and guidance.
Feel free to contact me for any information you need.