Is it possible to track all outgoing WCF call? - c#

Our application calls external services like
//in client factory
FooServiceClient client = new FooServiceClient(binding, endpointAddress);
//in application code
client.BarMethod(); //or other methods
Is it possible to track all of these calls (e.g by events or something like that) so that the application can collect the statistics like number of call, response time, etc? Note that my application itself needs to access the values, not only to write to a log file.
What I can think is to create a subclass of VisualStudio-generated FooServiceClient and then add codes like this
override void BarMethod()
{
RaiseStart("BarMethod");
base.BarMethod();
RaiseEnd("BarMethod);
}
and the RaiseStart and RaiseEnd method will raise events that will be listened by my code.
But this seems tedious (because there are a lot of methods to override) and there is a lot of repeated codes, my code needs to change everytime the service contract changes, etc. Is there a simpler way to achieve this, for example by using reflection to create the subclass or by tapping into a built-in method in WCF, if any?

The first thing I would look at is to see if the counters available in your server's Performance Monitor can provide you with the kind of feedback you need. There's built in counters for a variety of metrics for ServiceModel Endpoints, Operations and Services. Here is some more info http://msdn.microsoft.com/en-us/library/ms735098.aspx

You could try building an implementation of IClientMessageInspector, which has a method to be called before the request is sent and when the reply is received. You can inspect the message, make logs etc in these methods.
You provide an implementation of IEndpointBehavior which applies your message inspector, and then add the endpoint behavior to your proxy client instance.
client.Endpoint.Behaviors.Add(new MyEndpointBehavior())
Check out the docs for MessageInspectors and EndpointBehaviors, there are many different ways of applying them (attributes, code, endpoint xml config), I can't remember of the top of my head which apply to which, as there also IServiceBehavior and IContractBehavior. I do know for sure that the endpoint behaviors can be added to the client proxy collection though.

I found a simple way to do it by using dynamic proxy, for example Castle's Dynamic Proxy.
Firstly, use a factory method to generate your client object
IFooClient GetClient()
{
FooClient client = new FooClient(); //or new FooClient(binding, endpointAddress); if you want
ProxyGenerator pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<IFoo>(client, new WcfCallInterceptor());
}
And define the interceptor
internal class WcfCallInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
RaiseStart(invocation.Method.Name);
invocation.Proceed();
}
finally
{
RaiseEnd(invocation.Method.Name);
}
}
//you can define your implementation for RaiseStart and RaiseEnd
}
I can also change the intercept method as I wish, for example I can add a catch block to call a different handler in case the method throw exception, etc.

Related

WCF channel Factory caching

A WCF service will consume another Wcf service. Now, i want to create channel factory object and cache it manually. I know performance will be good but concern any other issue will be raised or not.
I have found info as follows:
"Using ChannelFactory you can still achieve channel factory caching with your own custom MRU cache. This still implies an important restriction: calls to the same service endpoint that share the channel factory must also share the same credentials. That means you can t pass different credentials for each thread calling application services from the Web server tier. One scenario where this is not an issue is if you use the same certificate or Windows credential to authenticate to downstream services. In this case, if you need to pass information about the authenticated user, you can use custom headers rather than a security token."
Link: http://devproconnections.com/net-framework/wcf-proxies-cache-or-not-cache
I have found a sample code in Google as follows.
internal delegate void UseServiceDelegate<in T>(T proxy);
internal static class Service<T>
{
private static readonly IDictionary<Type, string>
cachedEndpointNames = new Dictionary<Type, string>();
private static readonly IDictionary<string, ChannelFactory<T>>
cachedFactories =
new Dictionary<string, ChannelFactory<T>>();
internal static void Use(UseServiceDelegate<T> codeBlock)
{
var factory = GetChannelFactory();
var proxy = (IClientChannel)factory.CreateChannel();
var success = false;
try
{
using (proxy)
{
codeBlock((T)proxy);
}
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
private static ChannelFactory<T> GetChannelFactory()
{
lock (cachedFactories)
{
var endpointName = GetEndpointName();
if (cachedFactories.ContainsKey(endpointName))
{
return cachedFactories[endpointName];
}
var factory = new ChannelFactory<T>(endpointName);
cachedFactories.Add(endpointName, factory);
return factory;
}
}
private static string GetEndpointName()
{
var type = typeof(T);
var fullName = type.FullName;
lock (cachedFactories)
{
if (cachedEndpointNames.ContainsKey(type))
{
return cachedEndpointNames[type];
}
var serviceModel =
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
.SectionGroups["system.serviceModel"] as ServiceModelSectionGroup;
if ((serviceModel != null) && !string.IsNullOrEmpty(fullName))
{
foreach (var endpointName in
serviceModel.Client.Endpoints.Cast<ChannelEndpointElement>()
.Where(endpoint => fullName.EndsWith(endpoint.Contract)).Select(endpoint
=> endpoint.Name))
{
cachedEndpointNames.Add(type, endpointName);
return endpointName;
}
}
}
throw new InvalidOperationException("Could not find endpoint element
for type '" + fullName + "' in the ServiceModel client
configuration section. This might be because no configuration file
was found for your application, or because no endpoint element
matching this name could be found in the client element.");
}
}
I am totally confused what should i do. Can anyone give me a best practice guideline?
This is a complex topic with a lot of details to go over, but here it goes.
First, as a general rule you should be caching a ChannelFactory and not an individual Channel. A ChannelFactory is expensive to construct as well as thread-safe so it is a great candidate for caching. A Channel is cheap to construct and it is generally recommended to only create channels on an as-needed basis and to close them as early as possible. Additionally, when you cache a Channel then you have to worry about it timing out which will cause it to fault which invalidates the entire benefit of caching it in the first place.
The article you linked to by Michele Leroux Bustamante is one of the best resources out there. As she states, there are differences to consider between Windows clients and server-side clients. Mostly only Windows clients benefit from caching as typically the credentials differ from thread to thread on server-side clients. For your typical Windows clients, there are two main options: Caching the references yourself or leveraging the MRU cache.
Leveraging the MRU cache: Essentially this means that you are letting Microsoft take the wheel. The ClientBase class will use an MRU cache for the internal ChannelFactory instance. The caching behavior is controlled via a CacheSetting property and by default caching will be disabled if any of the "security-sensitive" properties are accessed. ClientBase properties which will invalidate and remove a ChannelFactory from the MRU cache when accessed include the Endpoint, ClientCredentials or the ChannelFactory itself. There is a way to override this behavior by setting the CacheSettings property to CacheSettings.AlwaysOn. Additionally, if the Binding is run-time defined then the ChannelFactory is no longer a candidate for the MRU cache. See more details here.
Caching the references yourself: This means that you are going to keep a collection of ChannelFactory references yourself. The snippet you provide in your question uses this approach. The best approach I have ever seen and admittedly use a modified version of at work is by Darin Dimitrov via this related SO question. For those of us who like to have more fine-grained control over the caching mechanism then this is the approach to use. This is typically used when credentials must be set at run-time like is often required by internet services.
Quite similarly, client proxies can be cached to improve performance - Wenlong Dong has an article about this topic.
(Update) Server-side clients as noted before are quite limited in their options when it comes to ChannelFactory caching. For this brief discussion, we will assume that our deployment scenario looks like this:
Client -> Service A -> Service B
The most likely method to use in order to leverage ChannelFactory caching in this scenario is to cache the references yourself for the session between the Client and Service A. This way Service A does not have to construct a different ChannelFactory instance every time Service A needs to call into Service B. However, if the properties of the ChannelFactory need change for each call, then this is no longer going to be appropriate.
Of course this also holds if Service A is a Singleton and each call to the downstream service (Service B) does not require new credentials, but Singleton services have their own set of performance problems.

Changing ConcurrencyMode

I'm using Castle Windsor WCF Facility.
The docs say:
If you are switching from WCF activation to Windsor's WcfFacility, please make sure to remove the ServiceBehavior attribute from service type.
How can I then control the concurrency mode?
In vanilla WCF I'd do:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
It seems that with WCF Facility the concurrence mode is set to Single and I can't find a way to change it.
EDIT: The client calls asynchronously BeginFoo method and the call is not blocking on client side.
I put logging at the beginning and at the end of the BeginFoo method. The logs indicate that the server call enters and exits BeginFoo method only once at a time.
The following client calls get magically queued.
I figured it out.
If you don't specify the attribute, then WCF Facility creates one for you and adds it to
ServiceHost.Description.Behaviors
So the solution is to add an attribute to Behaviors collection (Yes, the attribute implements IServiceBehavior, a bit counterintuitive though...) and set the relevant properties there.
I'm adding the behaviors in WcfServiceModel's extension OnCreated. As at this point the default behavior is already there, I had to remove it first.
For anyone interested, here's the code for what dzendras posted earlier:
static void Main(string[] args) {
_container = new WindsorContainer();
_container.AddFacility<WcfFacility>();
_container.Register(Component.For<IHelloService>()
.ImplementedBy<HelloService>()
.AsWcfService(new DefaultServiceModel().OnCreated(OnCreated)));
}
private static void OnCreated(ServiceHost serviceHost)
{
var serviceBehavior = (ServiceBehaviorAttribute) serviceHost.Description.Behaviors.Single(_ => _ is ServiceBehaviorAttribute);
serviceBehavior.ConcurrencyMode = ConcurrencyMode.Multiple;
serviceBehavior.InstanceContextMode = InstanceContextMode.PerSession;
}
As I Tried Some ways ,
You can use
[OperationContract(IsOneWay=true)]
this will not make client to wait for response and this can work as or replace multiple or reentrant concurrency model

How To create Extensible WCF service

I need to have a service which would be called from my client project. The requirement is that I can change and release a service but after changing the service there should not be a need to rebuild the client. The example is, suppose I have service which helps s person reach the destination
[ServiceContract]
IDestinationHelper
{
[OperationContract]
void ReachDestination(string person);
}
class ReachedByTrain:IDetinationHelper
{
void ReachDestination(string person)
{
//Help the person to reach destination
}
}
Now the service is helping the person to reach the destination by train, in this case I will be calling the ReachedByTrain service from client, but suppose a requirement comes and I want the person to reach by Flight, in that case how should I proceed without changing or building the client. The functionality should be plugable and client should automatically detect it
class ReachedByFlight:IDetinationHelper
{
void ReachDestination(string person)
{
//Help the person to reach destination
}
}
Please provide any help or reference about how it can be done.
P.S There will be only one mode present to the client at a time. No matter if the client doesn't know about it.
You have multiple ways to reach extensibility.
The interface is fixed in your client. Building code that handles a changing interface is hard and error prone. Don't do that.
So you will need to keep the interface intact and change the internal behaviour of your class.
In your example, your service could return a list of points as a route to the target and a string that notes the transportation mode. Now you can include all sort of transportation modes and return routes for them without changing the interface.
When you add a new possible transportation mode, the client must be notified so it can be presented to the user for example in a ComboBox. That means you need a method in your interface that returns all possible transportation modes. That way, your client can handle new ones without recompile. It can even handle it when you remove modes.
This way your client has a contract and the contract never changes. But your methods can return different things when you rebuild and redeploy your service.
Example:
This contract never changes:
[ServiceContract]
IDestinationHelper
{
[OperationContract]
IEnumerable<Waypoint> ReachDestination(string transportationMode);
[OperationContract]
IEnumerable<string> GetAvailabletransportationModes();
}
IDestinationHelperService : IDestinationHelper
{
public IEnumerable<Waypoint> ReachDestination(string transportationMode)
{
// decide return value by transportation mode. Use a switch statement, dependency injection, IoC containers, whatever you want
}
public IEnumerable<string> GetAvailabletransportationModes()
{
// decide return value by getting all modes from wherever you decided upon above.
}
}
I think you need to have a [ServiceContract] with an [OperationContract] which would take "ModeOfTransport" as a parameter and has a routing logic to create an object of either ReachByTrain or ReachByPlane or ReachByAnything and would call it from within the [OperationContract]. From the client side you can call the [OperationContract] which has the routing logic with the appropriate parameter on hand.

How to separate the layer of the communication and processing?

I created an application that provides several services. Each service provides a specific processing capabilities, except one service (that is the main service) that returns true or false to the clients which request if the specified processing capabilities is available or not.
Now I would modify the application, leaving the main service unchanged and adding the support for the installation of plugin with new processing capabilities: each plugin should add new processing capabilities without the need of implement a new service, but after installing the new plugin, a new service should be avaible. In this way, a plugin should not handle the communication layer. In other words, I would like to separate the layer of the communication and processing, in order to simplify the creation of new plugins.
Is it possible?
I could create two services: the main service and the service for processing.
The first service may be used by clients to know if a certain feature is present on the server (for example, clients may ask the server if it has installed the plugin that provides the functionality for solving differential equations).
The second service could be used to send a generic task and to receive a general result, for example:
Result executeTask(Task task);
where Result and Task are abstract classes...
For example, if I develop a plugin to solve the differential equations, I first create the classes for transferring data:
public class DifferentialEquationTask : Task
// This class contains the data of the differential equation to be solved.
...
public class DifferentialEquationResult : Result
// This class contains the the result.
...
Therefore, the client should instantiate a new object DifferentialEquationTask and pass it to the method of the second service:
DifferentialEquationTask myTask = new DifferentialEquationTask(...);
...
Result result = executeTask(myTask); // called by basic application
// The second service receives myTask as a Task object.
// This Task object also contains the destination plugin, so myTask is send
// to the correct plugin, which converts it to DifferentialEquationTask
...
myResult = result as DifferentialEquationResult;
// received by the client
Moreover, each plugin should have a version for the application server and a version for the client application.
An alternative would be to include the service in the plugin itself: in this way, a new plugin should implement a new functionality and expose it via an additional service.
In summary, I thought the following two alternatives:
a main service to ask the server if it has a plugin or not, and a second service to deliver tasks at the correct plugin;
a main service to ask if the server has a plugin or not, and various additional services (an additional service for each plugin installed).
In order to choose the best approach, I could use the following requirements:
Which of the two alternatives may provide better performance?
What advantages would be obtained using a new service for each plugin than using a single service that delivers tasks at the correct plugin?
Which of the two alternatives simplifies the development of a new plugin?
Being a novice, I was wondering if there was a better approach...
Thanks a lot!
It seems like the main service could maintain a dictionary of plugins, indexed by name. Then for a client to see if the server provides a particular service, all the main service has to do is look up the name in the dictionary. And to process, the service just has to call a method on the object that's in the value portion of the dictionary entry. An example:
You have three abstract classes: Service, ServiceResult, and ServiceTask. The contents of ServiceTask and ServiceResult aren't really important for this discussion. Service must have a parameterless constructor and a method called Process that takes a ServiceTask as its sole parameter. So your differential equation solver would look like:
public class DiffeqSolver : Service
{
public DiffeqSolver()
{
// do any required initialization here
}
public ServiceResult Process(ServiceTask task)
{
DiffeqTask dtask = task as DiffeqTask;
if (dtask == null)
{
// Error. User didn't pass a DiffeqTask.
// Somehow communicate error back to client.
}
// Here, solve the diff eq and return the result.
}
}
The main service is somehow notified of existing plugins. It maintains a dictionary:
Dictionary<string, Service> Services = new Dictionary<string, Service>();
I assume you have some idea how you're going to load the plugins. What you want, in effect, is for the dictionary to contain:
Key = "DiffeqSolver", Value = new DiffeqSolver();
Key = "ServiceType1", Value = new ServiceType1();
etc., etc.
You can then have two methods for the main service: ServiceIsSupported and Process:
bool ServiceIsSupported(string serviceName)
{
return Services.ContainsKey(serviceName);
}
ServiceResult Process(string serviceName, ServiceTask task)
{
Service srv;
if (Services.TryGetValue(serviceName, out srv))
{
return srv.Process(task);
}
else
{
// The service isn't supported.
// Return a failure result
return FailedServiceResult;
}
}
I've simplified that to some extent. In particular, I'm using a Dictionary, which is not thread safe. You'd want to use a ConcurrentDictionary, or use locks to synchronize access to your dictionary.
The more difficult part, I think, will be loading the plugins. But there are many available examples of creating a plugin architecture. I think you can find what you need.

C# Async call garbage collection

I am working on a Silverlight/WCF application and of course have numerous async calls throughout the Silverlight program. I was wondering on how is the best way to handle the creation of the client classes and subscribing. Specifically, if I subscribe to an event in a method, after it returns does it fall out of scope?
internal MyClass
{
public void OnMyButtonClicked()
{
var wcfClient = new WcfClient();
wcfClient.SomeMethodFinished += OnMethodCompleted;
wcfClient.SomeMethodAsync();
}
private void OnMethodCompleted(object sender, EventArgs args)
{
//Do something with the result
//After this method does the subscription to the event
//fall out of scope for garbage collection?
}
}
Will I run into problems if I call the function again and create another subscription?
Thanks in advance to anyone who responds.
You shouldn't let WCF client proxies simply fall out of scope like this. Your code will work but it will also leak resources. WCF clients all implement IDisposable, but this is one case where you can't just use using or Dispose; the Service Proxy Helper can be used for synchronous operations but the cleanup code in there demonstrates how to safely dispose of the client in any context.
When making async operations like this, something needs to be managing the lifetime of that client in a similar fashion. Normally whatever class "owns" the WCF client should implement IDisposable itself, keep a reference to that client in a private field somewhere, and invoke Close/Abort on the client in its disposal method.
Generally, whichever class actually implements the async callback method is going to be the owner, and so that class should be managing the lifetime; therefore, if you really need an "on-demand" client, it may also make sense to perform the cleanup after the callback is finished.
WCF clients are not cheap to create, either, so you should actually try to keep them around as long as possible and not create them ad-hoc like this; think of them as application-wide dependencies.
If you just keep the client instance around, then you don't need to keep subscribing to its events, either; the question effectively goes away.
You won't run into problems. It will generate a new WcfClient instance, and both will call your OnMethodCompleted callback on completion.

Categories

Resources