Saturday, March 31, 2012

Working with Windows 7 Event Tracing using .NET:- Part 4

 

Download sample code

Links : Part 1, Part 2, Part 3

 

Working with event trace sessions : Create and configuring trace sessions

Let see how to create trace sessions using a GUI based controller application. This GUI based controller application is non other than our perfmon.exe. Use the following steps to create new trace session for your custom provider.

  1. Open performance monitor by running the perfmon.exe in command prompt.

 

  1. Once performance monitor is opened, browse to Event Trace Sessions tree node. You will see Trace Sessions already configured to listen for event from system event providers. Our goal is to create a similar kind of trace session for our custom provider.

 

Machine generated alternative text: ‘a Pertorrnance Monitor<br />(j File Action View Window Help<br />•*hTU IL ___<br />Performance 1 Name Status<br />Monitoring Tools h  Circular Kernel Context Logger Running<br />Performance Monitor Audio Running<br />3 Data CollectorSets  Running<br />>  User Defined<br />> F. System EventLog-Application Running<br />J Event Trace Sessions  EventLog-DebugChannel Running<br />Startup Event Trace Sessions  EventLog-ForwardedEvents Running<br />> E Reports EventLog-Microsoft-Windows-... Running<br />AppFabric Event Collector Sessi... Running<br />EventLog-Microsoft-Windows-... Running<br />EventLog-Microsoft-Windows-... Running<br />EventLog-System Running<br />Microsoft Security Client Running<br />Microsoft Security Client WMI ... Running<br />NtfsLog Running<br />EventLog-Working With ETW P... Running<br />UBPM Running<br />WcesLog Running<br />WdiContextLog Running<br />WMZuneComm Running<br />MpWppTracing-03112012-1204... Running<br />WUDFTrace Running<br />Trace session for custom provi... Running<br />EMSMQ Running<br />SftFS Running<br />MSDTC_TRAC E_SESSION Running

 

 

  1. Right click on the right panel and  click on New-> Data Collector Set. This will open 'Create New Data Collector  Set' wizard.

 

Machine generated alternative text: MSMQ Running<br />SftFS Running<br />MSDTC_TRACE_SESSION Running<br />New Data CollectorSet<br />Refresh<br />Export List...<br />View<br />Arrange Icons<br />Line up Icons<br />Help

 

 

Wizard window.

 

Machine generated alternative text: —<br />k7j ® Create new Data Collector Set.<br />How would you like to Create this new data Collector set?<br />Name:<br />- Data CollectorI<br />‘ ‘ Create from a template (Recommended)<br />How cIa I ‘nork with templates?<br />G Create manually (Advanced)<br />How do I choose data collectors man n<br />[ Next 1 [ finish [ Cancel j

 

 

  1. Provide Trace session name as 'Trace session for custom provider'. Click on 'Next' to open provider selection wizard view.

 

Machine generated alternative text: —<br />® Create new Data Collector Set.<br />Which event trace providers would you like to enable?<br />Eroviders:<br />[ Afld... ]<br />[ Remove j<br />Properijes:<br />Property value [ edit...<br />Next ] [ Finish j [ Cancel j

 

 

  1. Click on 'Add' and select your custom provider from the list operating system has enumerated for all the registered providers. Our provider will also be listed here as we have already register it with the system. Click Ok to confirm the provider selection.

 

Machine generated alternative text: Event Trace Providers _______<br />Choose Event Trace Provider:<br />LIÎ1 With ETW Provider<br />WPC Trace<br />WPD API Trace<br />WPD APISQM Trace<br />WPD Bluetooth MTP Emumerator Driver Trace<br />WPD BusEnumService Trace<br />WPD ClassExtension Trace<br />WPD Classlnstaller Trace<br />WPD Composite Driver Trace<br />WPD FSDriver Trace<br />WPD ShellExtension Trace<br />WPD ShellServiceObject Trace<br />WPD Types Trace<br />WPD WCNCSvc Trace<br />WPD WCNWizard Trace<br />WPD WiaCompat Trace<br />WPD WMflMCnmnat Trare  <br />[ 0K N Cancel J

 

Machine generated alternative text: ® Creat<br />Which event trace providers would you like to enable?<br />Next ] [ Finish j [ Cancel j<br />Eroviders:<br />Working With ETW Provider<br />Properijes:<br />[ Agd... j<br />[ ßemove J<br />Property<br />value<br />Keywords(Any)<br />Keywords(All)<br />Level<br />Properties<br />4 <br />0x0<br />0x0<br />0x00<br />0x00000000<br />‚„

 

 

  1. Configure the trace session by customizing it to listen for specific keywords and verbosity levels.  Select the keywords row from Properties list and click on 'Edit' button to view the available keyword name. In our case we see only two keywords which we defined in instrumentation manifest file.

 

Machine generated alternative text: Property<br />G Authmabc<br />Value Des cription<br />ApplicabonsDevelopedForBankingDomain<br />Working With ET\1 Provider/Analytic<br />[ 0K ] [ Cancel ]<br />Applications Develc<br />Working With ETW<br />“,<br />Manual<br />0x800000000000000 1

 

Enable the check option for both the keywords values.

 

Similarly configure the required levels as well. After the configuration your wizard view show look as following.

 

Machine generated alternative text: ® Creat<br />Which event trace providers would you like to enable?<br />Eroviders:<br />Working with ETW Provider [ Afld... j<br />[ ßemove J<br />Properties:<br />Property value A [tZ]<br />Keywords(Any) 0x8000000000000001<br />Keywords(All) 0x0<br />Level 0x11<br />Properties 0x00000000<br />4 11E<br />Next ] [ Finish j [ Cancel j

 

 

Click on 'Next' button.

 

  1. Provide directory path where your want to save the collected events data. What value you give here is important in case you want to view your events using Windows Event Viewer. To view your events using Event Viewer you must provider following directory path to save the events data.

 

%SystemRoot%\System32\Winevt\Logs\

 

Wizard view after providing the directory path.

 

Machine generated alternative text: —<br />® Create new Data Collector Set.<br />Where would you like the data to be saved?<br />Root directo,y:<br />%SystemRoot%\System32Winevt\Logs\J [srowse.JJ<br />Next Finish 1 [ Cancel j

 

Click on 'Next' button.

 

  1. Change the option to 'Start this collector set now' as show in below image and click 'Finish' button.

 

Machine generated alternative text: Ø i9 Crete new Dite CollectorSt<br />Create the data oellector set?<br />Runas<br />cDetault><br />. Qpen propeitles for this data collector set<br />t Ra.t this data colector set nod<br />•:‘saxeanddose<br />j fiet [ÐnishllCancdl

 

 

We are done with creating trace session and it is up and running. Ready to listen for the event published by your custom provider. 

 

Machine generated alternative text: Name Status<br />Trace session for custom provider Running<br />CircuIar Kernel Context Logger Running<br />P.nn;nn

 

At this point if you run the console application we created, trace session will collect all the published events this application will fire.

Working with Consumer application

 

Once we have create a trace session  for a event provider, all the events from that provider are collected via trace sessions and are logged in log files. We will use Windows Event Viewer as Consumer application to view all the published events from our console application. Use the following steps to view the events.

 

  1. Open Windows Event Viewer by running  eventvwr.exe in command prompt.

 

  1. Expand 'Applications and Services Logs' node. You will see a new entry has been created for the channel you had defined in instrumentation manifest file. Expand 'Working with ETW provider' and select 'Analytic' node to view all the events published by our console application .

 

Machine generated alternative text: Eue Action view Help<br />k Event Viewer (Local)<br />Custom Views<br />E Windows Logs<br />4  Applications and Services Logs<br />BitLocker-Provisioning-Microsoft-IT<br />Hardware Events<br />Internet Explorer<br />fr] Key Management Service<br />frj Media Center<br />> ji Microsoft<br />fr] Microsoft Office Alerts<br />j Microsoft-lE<br />> ji Microsoft-IEDVTOOL<br />[,  Microsoft-IEFRAME<br />I MPJLoq<br />Windows PowerShell<br />¿ i Working With ETW Provider<br />IR Analytic<br />fl Saved Logs<br />; Subscriptions<br />Analytic Pagel<br />J<br />Next Page [ ßacktoTop j<br />J_i To make this Analytic, Debug or Classic event log easier to navigate and manipulate, first save it in .evtx format by using the<br />Level<br />Date and Time<br />Source<br />Useful<br />15-03-2012 01:42:07<br />Working With ETW Provider<br />Useful<br />L<br />15-03-2012 17:09:52<br />Working With ETW Provider<br />„<br />Event 1, Working With ETW Provider<br />E &a I D eta<br />Person Eat Event. Person First Name Arun, Person Last Name Malik<br />X<br />Log Name:<br />Source:<br />Event ID:<br />Level:<br />User<br />QpCode:<br />More Information:<br />L<br />Working With ETW Provider/Analytic<br />Working With ETW Provider Logge4: 15-03-2012 01:42:07<br />1 Task Category Component Person<br />Useful Keywords:<br />Computer<br />Operation Eat<br />Event Log Online Help

Wednesday, March 28, 2012

Issue with Moles : Not able to read unit test configuration file when test case method is set to run under Moles host type.

 

While writing unit test cases using moles to create fake objects, I came across an issue where, test methods were not able to the configuration file provided for unit test case assembly. This issue was occurring only when the test method were marketed with HostType("Moles") attribute.  I verified the location of configuration file being used by checking the properties of AppDomain in which the test case method was running. Following is a screen shot of what I show.

 

clip_image001 

 

It is clear from screen shot that the AppDomain was setup to use "Microsoft.Moles.VsHost.x86.exe.config" configuration file instead of using configuration file generated for the unit test case assembly.

 

After performing some debugging , I could find out that the problem was with the moles executable which I had installed using standalone moles installer. When you install moles using in standalone installer, moles instrumentation runtime (Microsoft.Moles.VsHost.x86.exe)does not set the AppDomain to use right config file (test assembly config), Instead AppDomain is set to use the configuration file of moles runtime executable.

 

To resolve this issue , I installed moles using Pex installer (download). when you install moles using Pex installer, moles runtime executable does set AppDomain to use right configuration file (config file of unit test assembly). See the below screen shot , ConfigurationFile  property is now referring to unit test assembly's config file path.

 

clip_image002

 

 

Hence , using moles installed through Pex installer allows  the test cases to happily read the config information provided in test case assembly's config file.

Thursday, March 15, 2012

Working with Windows 7 Event Tracing using .NET:- Part 3

 

Download sample code

Links : Part 1, Part 2, Part 4

 

Creating Event Provider Assembly and using it in your application.

 

 

 

In this article I will show you how to generate .NET c# provider code using MC.exe and compile the generated code into an assembly so that you can easily use that assembly in any of your application to write the events which you have defined in the manifest file.

Follow these steps to generate the provider code in .NET and to compile the code into a .NET assembly.

1. Generate .NET c# code with the help of the manifest xml file we have already created. Generated c# code is completely type safe and you do not need to worry about all the constants their values and where to use all those in the code. All this is handled by MC.exe. Use the following command in visual studio 2010 to generate the provider code in c# language.

MC.exe -h <target location> <namespace name for generated class> <manifest xml file path>

MC.exe -h c:\ProviderFiles CustomProvider c:\ProviderFiles\EventProviderManifest.xml

You will see the generated c# class file in your target location. Something similar to the following.

clip_image002

2. Generate an assembly by compiling the generated C# class file. Use the following in visual studio 2010 command prompt.

Csc.exe /out:c:\ProviderFiles\CustomProvider.dll /unsafe /t:library c:\ProviderFiles\EventProviderManifest.cs

You will see the generated assembly file in your target location. Something similar to the following.

clip_image003

Congratulation!

You have just created a custom windows event provider assembly which can be loaded in any of your .NET application to publish all your events defined in the instrumentation manifest file.

Let’s use the provider assembly we have just created in a .NET application to publish the events. I am creating a simple console based application which will publish person eat event. Code of console application is present in MyApplicationUsingMyProvider.cs file. Following is the code snippet for console application.

using System;

namespace MyApplicationUsingMyProvider

{

class Program

{

static void Main(string[] args)

{

CustomProvider.PROVIDER_GUID provider = new CustomProvider.PROVIDER_GUID();

provider.EventWritePERSON_EAT_EVENT("Arun", "Malik");

Console.WriteLine("Event published successfully.");

Console.WriteLine("Press any to exit...");        

Console.ReadLine();

}

}

}

Note that how the MC.exe has used the symbol value from <Provider/> element from manifest xml to generate the class name. Refer Part 2

Let’s compile the MyApplicationUsingMyProvider.cs into a console application and run it. Use following commands in visual studio 2010 command prompt.

Csc.exe /out:<target exe path> /r:<path of custom provider dll> /t:exe <console app cs file path>

csc.exe /out:c:\ProviderFiles\MyApplicationUsingMyProvider.exe /r:c:\ProviderFiles\CustomProvider.dll /t:exe c:\ProviderFiles\MyApplicationUsingMyProvider.cs

You will see the generated console application in your target location. Something similar to following.

clip_image004

So, we have successfully created a custom provider and used it in a simple console based application. If you run that application and try to see the published events in either windows event viewer or any of the consumer application, you will be disappointed. Reason is that there is no link has been established yet between the consumer applications and your provider. This link is Trace session and we need to create one which will listen for the published events from our custom provider. In the Part 4 of this series I will show you how to use one of the GUI based controller application to create and configure Trace session which will listen and collect the published events from your provider.

Links : Part 1, Part 2, Part 4

Working with Windows 7 Event Tracing using .NET:- Part 2

 

Download sample code

 

Links : Part 1, Part 3, Part 4

 

Working with Windows Instrumentation Manifest file

 

 

In this article, we will see how to create an instrumentation manifest file from scratch by defining a custom provider metadata and its supported events metadata in an xml file. We will use predefined xml elements and attributes for doing this.

Let’s create a blank xml file and add required elements one by one.

Add Element to Identify Provider: You can put more than one Provider information in single instrumentation manifest. To identify a particular provider, we use <Provider/> element and specify the values for following attributes.

Name: Name of your provider.

Guid: GUID to uniquely identity this provider in the system.

resourceFileName: Path of assembly in which the resource file generated after the compilation of

manifest file is embedded. We will see how the compile the manifest file.

messageFileName: Path of assembly in which the message file generated after the compilation of manifest file is embedded. We will see how the compile the manifest file.

Symbol: Used to refer the class of this provider in the code generated by MC.exe (manifest compiler).

Message: The localized display name for the provider. The message string references a localized string in the stringTable section of the manifest.

Sample xml snippet:

clip_image002

Add Element to define channels: Channels are used by Consumer applications like Windows Event Viewer to collect events for certain group of audiences. You use <channel />Element to define new channels. Values for the following attributes must be provided in each <channel/> element.

Chid: An id to uniquely identify the channel in the list of channels defined under a provider. This same attribute is used to attach the channel with specific event type defined using <Instrumentation\Events\Provider\Event/> element.

Name: Name of channel, must be unique among all the channels defined in same provider element.

Type: This value can be set to one the four types: Admin, Analytic, Debug and Operational. Component should write events under correct channel types, as each channel type is used by different set of audiences to analyses the application issues.

Enabled: To specify if the channel is enabled or not.

Isolation: Isolation level defines access permissions for the channel. There are three isolations are available: Application, System and Custom.

Message: The localized display name for the channel. The message string references a localized string in the stringTable section of the manifest.

Sample xml snippet:

clip_image004

Add Element to define Severity levels: Severity levels are used to group the published events. These are also used by consumer applications to query the events and trace session uses them to limit the events which are provided to consumer applications in real time or written in log files. You use <level />Element to define new levels. Values for following attributes must be provided in each new level element.

Name: Name of the Level. Must be unique among all the levels defined under same provider.

Value: Level value. It can be between 16 to 225.

Symbol: Used to refer the constant created for this Level in the code generated by MC.exe (manifest compiler).

Message: The localized display name for the channel. The message string references a localized string in the stringTable section of the manifest.

Sample xml snippet:

clip_image006

Add Element to define task and opcodes: Tasks and opcodes (operation codes) are used to logically group the published events. You define new tasks for each component of your application and a new opcode for each type of operation performed in that component. Because of this grouping consumer applications can easily query for events published for particular operations performed in particular component. You use <task />Element to define a new tasks and use <opcode /> element to define task specific operation codes. Values for the following attributes must be provided in each new <Task/> element. 

Name: Name of the Task. Must be unique among all the levels defined under same provider.

Symbol: Used to refer the constant created for this Task in the code generated by MC.exe (manifest compiler).

Value: Value assigned to the Task. It can be between 1 to 239.

Message: The localized display name for the channel. The message string references a localized string in the stringTable section of the manifest.

Sample xml snippet:

clip_image008

Add Element to define Keywords: Keywords are used to classify different types of events. You might create one keyword to classify all your database accesses in your application and another one to classify write accesses to the database. You associate keywords with events when you define new events using <event> element. Keywords are used by consumer applications to limit the number of events it listens for. You use <keyword /> element to define a new keywords. Values for the following attributes must be provided in each new <keyword /> element.

Name: Name of the Keyword. Must be unique among all the Keywords defined under same provider.

Mask: Bit value assigned to the Keyword. This value is checked by Trace Sessions to limit category of events they want to listen for. You can specify bit values in the range from 0x0000000000000001 through 0x0000800000000000 (bits 0 through 47).

Symbol: Used to refer the constant created for this Keyword in the code generated by MC.exe (manifest compiler).

Message: The localized display name for the channel. The message string references a localized string in the stringTable section of the manifest.

Sample xml snippet:

clip_image010

Add Element to define event data Template: Each published event carry some data with it. This data has specific meaning in the context of published event. You use <template /> element to define a new data template. Values for the following attributes must be provided in each new <template /> element and use <data /> element to define template specific data items.

Attributes of Template element

Tid: unique identifier of the template defined in the provider.

Attributes of Data element.

Name: Name assigned to the data item.

Type: Data type for the data item.

Sample xml snippet:

clip_image012

Add element to define Events: Each provider defines all the events it can publishes in manifest file. You use <event/> element to define each new event. Attributes you set in <event/> element are based on who is going to consume your published events. Following are attributes you set in <event/> element.

Value: The event identifier. The identifier must be unique within the list of events that you define for your provider.

Level: Level of verbosity. This value either comes for the Levels you have defined or from the level predefined in winmeta.xml. If your event is targeting Admin channel, you cannot use your custom level value. Only possible values for Admin channel events are win:Critical, win:Error,win:Warning and win:Information.

Symbol: Used to refer the event descriptor created for the event in the code generated by MC.exe (manifest compiler).

Message: The localized display name for the channel. The message string references a localized string in the stringTable section of the manifest. To add event specific data items in message use substitution parameters. For Example to use third data item in you message use %3.

Template: An identifier of the template that defines all the data items an event can carry along with it. Specify the identifier of a template that you defined in the manifest.

Task: The name of a task that identifies the component or subcomponent that generates this event. Specify the name of a task that you defined in the manifest.

Opcode: The name of an opcode that identifies an operation within the task. Specify the name of an opcode that you defined in the manifest or one of the opcodes defined in Winmeta.xml.

Channel: If your users are going to Windows Event Viewer to view your published events, this attribute should be set with one of the channel you have defined manifest.

Sample xml snippet:

clip_image014

Download complete manifest file from sample code.

At this stage, we have successfully completed an instrumentation manifest file. Next step is to register all the information defined in manifest file with Operating system. Once registered, operating system can fetch this information at the time you create new trace sessions or in inside Event Viewer to parse your message data elements and show them at proper places in the view.

Follow these steps to register the manifest with operating system.

1. Compile the manifest file and generate message file. Use following command in visual studio 2010 command prompt.

MC.exe -r <target location> <manifest file path>

MC.exe -r c:\ProviderFiles EventProviderManifest.xml

You will see the generated files in your target location. Something similar to the following

clip_image015

2. Generate native resource file from message file you just created in above step. Use following command in visual studio 2010 command prompt.

RC.exe <message file path>

RC.exe c:\ProviderFiles\EventProviderManifest.rc

You will see the generated native resource file in your target location. Something similar to the following.

clip_image017

3. Generate a .NET assembly and embed the native resource file you have just created in above step. Use the following command in visual studio 2010 command prompt.

csc.exe /out:<target assembly path> /win32Res:<resource file path> /t:library <some .cs file path>

csc.exe /out:c:\ProviderFiles\EventProviderManifest.dll /win32Res:c:\ProviderFiles\EventProviderManifest.res /t:library c:\ProviderFiles\temp.cs

You will see the generated assembly in your target location. Something similar to the following.

clip_image019

4. Next step is to update the instrumentation manifest file by updating the resourceFileName and messageFileName attributes of Provider element. Something similar to following.

clip_image021

5. Last step is to register manifest xml file with operating system by running the following command. Use visual studio 2010 command prompt to run this command.

Wevtutil im <instrumentation manifest file path>

Wevtutil im c:\ProviderFiles\EventProviderManifest.xml

If the above command runs successfully, you have registered the manifest with operating system successfully.

Till now we have seen how to work with instrumentation manifest and register it with the operating system. In part 3 of this series, I will show you how to create a provider assembly, which can be used in your applications to publish all the events you have defined in instrumentation manifest file.

 

Links : Part 1, Part 3, Part 4

Working with Windows 7 Event Tracing using .NET:- Part 1

 

Download sample code

 

Links : Part 2, Part 3, Part 4

 

 

Event Tracing Architectural components

 

Instrumentation Manifest: This is an XML file used to define the metadata about events you want to publish from your application using Windows ETW APIs. Same metadata is used by operating system, consumer applications and trace sessions to understand the meaning of published event and its content.

See how to create an instrumentation manifest file from scratch.

 

Event Provider: Event provider can be any application or component which is using ETW APIs and publishing windows tracing events. Generally you put all your code specific to ETW APIs in a separate assembly and use it in all your applications to publish the events. Each provider is associated with an instrumentation manifest file, which defines all the possible events your provider code can publish.

See how to create a provider assembly and use it in your application to publish events you had defined in instrumentation manifest file.

 

Trace Sessions: Trace Sessions listens for all the events published by your event provider. Event provider does not know what all Trace sessions are listening for the events it is publishing. Multiple trace sessions can be created to listen for the events created by single provider.  Trace sessions are created and configured using controller applications. See how to create and configure a Trace session.

 

Event Consumers: These are the applications which use Trace sessions as the source of the events. Same consumer application can listen for multiple trace sessions at same time. It can listen for the events in real time from the trace sessions which are configured to put the events in memory buffer or from log file generated by trace sessions configured to put events in log file. See how to use Windows Event Viewer, standard event consumer application provided by operating system.

 

Session Controllers: These are the applications you use to create new trace sessions and configure them to listen for the events published by your event providers.

See how to work with GUI based session controller application.

 

Below figure shows how all these components are logically associated with each other.

 

image

 

 

Now we know the high level component of windows event tracing infrastructure. A developer has to work with all these components to successfully enable their application to use windows event tracing.  

 

In the next articles of this series, I will show you how to define your custom events  using instrumentation manifest file, create your own event provider assembly which can be used in any of your application to publish custom events. I will also show you how to configure new Trace Sessions which will listen to your custom events and how to view all the collected events using Windows Event Viewer.

 

 

Links : Part 2, Part 3, Part 4

Thursday, February 23, 2012

WCF Extension Points, How to extend WCF framework to add custom features in WCF runtime.

 

In one of my SOA based software system, I had a requirement of intercepting the service method calls to automatically logging the method calls on entry and exit of the service method call without putting any logging statements inside the service method implementation and to have some default exception handling logic again without putting any try catch blocks inside service method implementation. The implementation of these features was giving us more cleaner implementation of business functionality inside service methods by abstracting away the implementation of crosscutting concerns like exception handling or logging in my case. 

To implement the above feature I was looking for the way to get execution control even before it goes to my service methods. Good news is that WCF itself helped me and gave the control with the help of it's extension points. Lets see how?

 

Proxy and Dispatcher

 

WCF works on messages which are send between client and service. Every time client wants to call a service  method, it sends a message to service with help of Proxy running in the client process. Job of the Proxy is to take the client request and convert it into a message which is than further serialized and transferred to the service. At service end this message is received by Dispatcher. Dispatcher takes the message and desterilizes the content into appropriate CLR type, finds out which method has to be called on behalf of the client and calls that method.

 

Both Proxy and Dispatcher provides many extension points using different interfaces. When you implement these interfaces in your own class and register those class with WCF runtime (we will see how?), Both Proxy and Dispatcher calls the implementation in your class at the time of message processing. 

 

Lets see what all interfaces are provided via WCF framework to intercept the message processing.

 

  1. IParameterInspector : Called before and after invocation to inspect and modify parameter values.

 

  1. IDispatchMessageFormatter/IClientFormatter : Called to perform serialization and deserialization.

 

  1. IDispatchMessageInspector/IClientMessageInspector : Called before send or after receive to inspect and replace message contents.

 

  1. IDispatchOperationSelector/IClientOperationSelector : Called to select the operation to invoke for the given message.

 

  1. IOperationInvoker : Called to invoke the operation.

 

 

Registering your inspector class with WCF runtime

 

You use WCF behaviors to register your inspector classes with WCF runtime. When the ServiceHost initializes the service, it looks into app.config/web.config file  for the behaviour to apply and also reflects over all the attributes applied on service contract methods to check if any attribute has been applied which is implementing any behaviour interface. If it finds one, it creates an instance of that attribute type and calls appropriate methods of behaviour interface, implemented by attribute class, to you give you a change to register your interceptors during service initialization.  There are following types of behaviors provided via WCF

 

  1. IServiceBehavior: Allows you to register your inspectors at Service level.
  2. IEndpointBehavior: Allows you to register your inspectors at Endpoint level.
  3. IContractBehavior: Allows you to register your inspectors at Service Contract level.
  4. IOperarionBehavior: Allows you to register your inspectors at each Operation level.

 

All these behavior interfaces are having same methods but the method signatures are different so that your only get those runtime objects which comes under the scope you want to extend. Following are the methods available in each behavior interface.

 

  1. Validate: Called just before the runtime is built—allows you to perform custom validation on the service description.

 

  1. AddBindingParameters: Called in the first step of building the runtime, before the underlying channel is constructed—allows you to add parameters to influence the underlying channel stack.

 

  1. ApplyClientBehavior: Allows behavior to inject proxy (client) inspectors. this method is not present on IServiceBehavior.

 

  1. ApplyDispatchBehavior:Allows behavior to inject dispatcher inspectors.

 

 

 

Now you know what all classes and interfaces are available from WCF to extend its runtime, lets extend the runtime to intercept the service method calls and log the entry and exit of method call automatically (without writing logging code in service method implementation).

 

Following are the classes involved in my solution. To make the sample as simple as possible I have create all these classes and interfaces in single WCF project.

 

image

 

Code for LoggingAttribute.

 

Note how this class is inherited from Attribute class and implementing IOperationBehavior. Methods of IOperationBehavior will be called by ServiceHost at the time of service initialization process to give you a chance to register your inspectors. In this example I am registring LoggingInspector instance.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.ServiceModel.Description;

 

namespace SampleService

{

public class LoggingAttribute : Attribute, IOperationBehavior

{

        public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            //for this example no implementation is required in this method.

        }

 

        public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)

        {

            //for this example no implementation is required in this method.

        }

 

        public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)

        {

            //Register your inspector class

            dispatchOperation.ParameterInspectors.Add(new LoggingInspector());

        }

 

        public void Validate(OperationDescription operationDescription)

        {

            //for this example no implementation is required in this method.

        }

    }

}

 

Code for LoggingInspector.

 

See how LoggingInspector is implementing IParameterInspector interface and providing the logging functionality.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.ServiceModel.Dispatcher;

 

namespace SampleService

{

    public class LoggingInspector : IParameterInspector

    {

        public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)

        {

            //Your can put any logging code here. here is the dummy one.

            Console.WriteLine(string.Format("Method exit : {0}",operationName));

        }

 

        public object BeforeCall(string operationName, object[] inputs)

        {

            //Your can put any logging code here. here is the dummy one.

            Console.WriteLine(string.Format("Method entry : {0}", operationName));

 

            return null;

        }

    }

}

 

 

Code for ISampleService service contract interface.

 

Here I am applying my own custom attribute to enable automatic logging on IncrementNumber method.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Web;

using System.Text;

 

namespace SampleService

{   

    [ServiceContract]

    public interface ISampleService

    {

        [OperationContract]       

        [Logging]

        int IncrementNumber(int number);       

    }   

}

 

 

Code for SampleService implementation.

 

Note that there is no logging related implementation inside IncrementNumber method implementation.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Web;

using System.Text;

 

namespace SampleService

{   

    public class SampleService : ISampleService

    {     

        public int IncrementNumber(int number)

        {

            return number++;

        }     

    }     

}

Why WCF when there are other technologies to implement distributed software systems?

 

Need for distributed software systems.

How do you create distributed application?

 

At architectural level you design your software systems by breaking the business functionality into multiple components and than deploy these components on separate process and machine boundaries.  All these components running on separate process and machine boundaries has to have some communication between them using some protocol so that they can collaborate to achieve the overall business functionality.

 

There have been many technologies available to develop the components and deploy them in distributed manner. Following are some the examples

 

  1. .Net Remoting
  1. COM and DCOM
  2. CORBA  and RMI
  3. Microsoft Enterprise Services

 

So what's wrong in using the above technologies to create distributed apps?

 

There is nothing wrong creating a distributed application using these technologies until your application is going to be used outside the organization or department and not going to interact with other applications in future. When the need to interact with other application comes in, it becomes really hard to achieve the desired interaction among applications because of the mismatch in data structures and protocol stack between your and other applications. Interoperability becomes  an issue because of proprietary standards and protocol stacks used to develop the applications. Other than interoperability issues, all these technologies has a limitation where firewalls can block the communication between components. 

 

How do you tackle with interoperability among distributed components?

 

We use web service technology in which components are exposed to other components using xml based open web standards (SOAP , WSDL, HTTP). These standards are acceptable throughout the software industry. As these standards are based on XML and HTTP which are supported on all platforms, components exposed using these standards are easily accessible between different platforms, ex a components running on windows platform can be accessed via components running on Unix platform. Following are some of the web service elements which makes interoperability possible.

 

Standard protocol: Functionality is exposed via interfaces using one of the few standard Internet protocols such as HTTP, SMTP, FTP, and so on. Mostly used protocol is HTTP.

 

Service description: Web services need to describe their interfaces in detail so that a client knows how to “consume” the functionality provided by the service. This description is usually provided via an XML document called a WSDL document. (WSDL stands for Web Services Description Language.)

 

Finding services: Users need to know what web services exist and where to find them so the clients can bind to them and use the functionality. One way for users to know what services exist is to connect to the listing of services. These listings are implemented via Universal Discovery, Description, and Integration (UDDI) repositories.

 

From above text it should be clear that there are many technologies available to implement distributed components with there own specific advantages and disadvantages and you should web services to expose your components outside your organization or department boundaries because of its open standards support all around in software community.

 

Now imagine that your organization or department needs to develop an application which has to be used internal to your organization and will also be accessed from outside your organization or department.  You might go and use .NET Remoting to expose your serviced components for internal users and will have to used web services to expose same components  to the users outside your organization. But if you do this your code base for the components will have the knowledge for both the technologies being used to expose the functionality as a service. Your developers will be investing more time in dealing with the technology implementation rather than the business functionality implementation.

 

What if you can abstract away the fact from your code base that your component is going to be exposed using multiple protocols and technologies? What if you can enable or disable any protocol in your already running component without stopping it or doing any code changes?  All these features were kind of dream before WCF came in market.

 

WCF introduction

(Develop once and use anywhere)

 

WCF is new Microsoft technology, actually a framework build upon .NET framework, which makes it really easy to develop serviced components and deploy them using multiple communication protocols. It supports net.tcp, net.pipe, HTML, HTTPS and MSMQ communication protocols. Biggest advantage of using WCF is that the knowledge of what all protocols are being used to expose your component is completely abstracted from the component code.  WCF framework is highly extendible as well. It provides so many extension points using them your can implement your own protocols and control almost all the expects of exposing your component as service. 

 

Following are main goals of WCF

 

  1. Unification of existing technologies: WCF subsumes the best of all the distributed technologies. WCF brings together the efficiency of ASMX, the gift of merely adopting transactions with Enterprise Services just through using attributes, the extensibility and flexibility of .NET Remoting, the supremacy of MSMQ for building queued applications, and WSE’s interoperability through WS-*. Microsoft took all these capabilities and built a single, steady infrastructure in the form of WCF.

 

image

 

 

  1. WCF As a Service-Oriented Development Tool: WCF offers that foundation for service-oriented applications by supporting all the four tents of SOA mentioned in my post.

 

image

 

  1. Coexisting with Existing Technology: WCF takes all the capabilities of the existing technology stacks while not relying upon any of them. All your existing investments will run side by side with WCF. Applications built with these earlier technologies will continue to work unchanged on systems with WCF installed. It also provides you with an opportunity to communicate with, or even replace, existing Windows communications APIs and technologies, including ASMX, ASP.NET web services, Web Services Enhancements (WSE), Enterprise

Services, System.Messaging, and .NET Remoting.