I have a DLL that handles making hundreds of method calls either via WCF or directly to QuickBooks. In each method I have code similar to this:
public Response GetSomethingFromQuickBooks()
{
Response response = new Response();
if (useWCF == true)
{
System.ServiceModel.BasicHttpBinding binding = new System.ServiceModel.BasicHttpBinding();
System.ServiceModel.EndpointAddress endpoint = new System.ServiceModel.EndpointAddress(new Uri(wcfEndpoint));
WCFClient = new ServiceReference.OperationsClient(binding, endpoint);
WCFClient.CreateConnection(opsConnectionDTO);
response = WCFClient.GetSomethingFromQuickBooks();
try
{
WCFClient.Close();
}
catch (Exception)
{
WCFClient.Abort();
}
}
else
{
response = qbManager.GetSomethingFromQuickBooks();
}
return response;
}
I have a couple of questions:
1) Is this the proper way to handle WCF calls on a per method basis?
2) Is there a way I can instantiate the WCF client on a per method basis without having to put duplicate code in each method?
Is this the proper way to handle WCF calls on a per method basis?
Well, if we can conveniently ignore fact that you're talking to a service with hundreds of operations defined on it, there are still some things you could be doing differently.
Spinning up a client channel for each call is excessive. Although low, the cost is still significant. It would be better to have some wrapper or factory which could be depended on to manage the lifecycle of the client channel in a sensible way.
Also, it looks like you're using a service reference to call the service. This is sub-optimal for many reasons and should be done only as a last resort, for example when you don't have access to the service interface definition other than via the service metadata. You should be using a WCF Channel otherwise.
Is there a way I can instantiate the WCF client on a per method basis
without having to put duplicate code in each method?
Setting aside the fact that client channels are generally reusable as long as they are not faulted, you could utilise an IoC container to inject a runtime dependency containing a freshly-initialised client channel implementation. Either that or reimplement WCFClient as a reusable wrapper around the client channel as mentioned before.
Related
I have desktop application, that uses WCF services. I have got great usability improve when I implemented async WCF calls.
My question is: what is the best practice to initialize service client?
In previous realization there was single static object with credentials and a public method GetClient(), that was creating new ServiceClient before every call. In application there was commonly used such construction:
using (var svc = ServiceClientFactory.GetClient()) {
var data = svc.CallMethod(...);
some_application_context.specific_attribute = data;
}
so, before any call, was created new client, that was destroyed immediately after operation was finished and received data was used.
My question is: is it the best practice to call client constructor before every call?
I've tried to create single static client object, that is initialized once at startup and destroyed once on application closing, but I haven't got any notional performance gain.
Seems like it works fine, but I wonder if there any not very obvious obstacles in using single client? And what is recommended?
It's kind of a broad question, it depens on a lot of factors and also on style I guess.
When using reliable sessions or sessions in general you have to store the reference of course.
When calling the service many times it might be better to store the reference, or it might not. Better profile it then and there.
I always store a reference and create a property which check if the client is null or in the Faulted State.
Service.ServiceClient ShippingService
{
get
{
if (mService == null || mService.State == CommunicationState.Faulted)
{
mService = new Service.ServiceClient("netTcpService");
mShippingService.Open();
}
return mService;
}
}
You should look at dependency injection for getting your service references. Effectively it would be similar if not the same performance to what your doing now but it would make long term management easier and allow easier unit testing.
Most of the WCF overhead is connection negotiation so singleton vs new on each call won't really end up making a huge difference.
I have a client application that consumes a number of services. It's not always immediately obvious when a service is down or incorrectly configured. I own the service side code and hosting for most of the services, but not all of them. It's a real mixed bag of client proxies - different bindings (basichttp/wshttp/nettcp), some have been generated using svcutil.exe, while others are made programatically with ChannelFactory where the contract is in a common assembly. However, I always have access to the address, binding and contract.
I would like to have a single component in my client application that could perform a basic check of the binding/endpoint config and the service availability (to show in some diagnostic panel in the client). As a minimum I just want to know that there is an endpoint at the configured address, even better would be to find out if the endpoint is responsive and supports the binding the client is trying to use.
I tried googling and was surprised that I didn't find an example (already a bad sign perhaps) but I figured that it couldn't be that hard, all I had to do was to create a clientchannel and try to open() and close() catch any exceptions that occur and abort() if necessary.
I was wrong - in particular, with clients using BasicHttpBinding where I can specify any endpoint address and am able to open and close without any exceptions.
Here's a trimmed down version of my implementation, in reality I'm returning slightly more detailed info about the type of exception and the endpoint address but this is the basic structure.
public class GenericClientStatusChecker<TChannel> : ICanCheckServiceStatus where TChannel : class
{
public GenericClientStatusChecker(Binding binding, EndpointAddress endpoint)
{
_endpoint = endpoint;
_binding = binding;
}
public bool CheckServiceStatus()
{
bool isOk = false;
ChannelFactory<TChannel> clientChannelFactory = null;
IClientChannel clientChannel = null;
try
{
clientChannelFactory = new ChannelFactory<TChannel>(_binding, _endpoint);
}
catch
{
return isOk;
}
try
{
clientChannel = clientChannelFactory.CreateChannel() as IClientChannel;
clientChannel.Open();
clientChannel.Close();
isOk = true;
}
catch
{
if (clientChannel != null)
clientChannel.Abort();
}
return isOk;
}
}
[Test]
public void CheckServiceAtNonexistentEndpoint_ExpectFalse()
{
var checker = new GenericClientStatusChecker<IDateTimeService>(new BasicHttpBinding(), new Endpointaddress("http://nonexistenturl"));
// This assert fails, because according to my implementation, everything's ok
Assert.IsFalse(checker.CheckServiceStatus());
}
I also tried a similar technique with a dummy testclient class that implemented ClientBase with the same result. I suppose it might be possible if I knew that all my service contracts implemented a common CheckHealth() method, but because some of the services are outside my control, I can't even do that.
So, is it even possible to write such a simple general purpose generic service checker as this? And if so how? (And if not, why not?)
Thanks!
Have you looked at WCF Discovery?
WCF Discovery allows a client to search for a service based on
different criteria including contract types, binding elements,
namespace, scope, and keywords or version numbers. WCF Discovery
enables runtime and design time discovery. Adding discovery to your
application can be used to enable other scenarios such as fault
tolerance and auto configuration.
For a first attempt, you could query the endpoint to see if it supports the expected contract.
The big benefit is that you can have the client “discover” which service it wants to talk to at runtime. Which removes a lot of the client side configuration errors that you are likely used to seeing.
You need to check out SO-AWARE. It is a web service management tool that can manage SOAP or REST WCF-based service across your organization. Further it has a Test Workbench!
Here are a couple of videos that show it off too:
Part 1
Part 2
To put it in perspective, this is so complex that these people make a living doing it, I don't think it's something you want to realistically build on your own.
So I've decided to up the performance a bit in my WCF application, and attempt to cache Channels and the ChannelFactory. There's two questions I have about all of this that I need to clear up before I get started.
1) Should the ChannelFactory be implemented as a singleton?
2) I'm kind of unsure about how to cache/reuse individual channels. Do you have any examples of how to do this you can share?
It's probably important to note that my WCF service is being deployed as a stand alone application, with only one endpoint.
EDIT:
Thank you for the responses. I still have a few questions though...
1)I guess I'm confused as to where the caching should occur. I'm delivering a client API that uses this code to another department in our company. Does this caching occur on the client?
2)The client API will be used as part of a Silverlight application, does this change anything? In particular, what caching mechanisms are available in such a scenario?
3)I'm still not clear about the design of the GetChannelFactory method. If I have only one service, should only one ChannelFactory ever be created and cached?
I still haven't implemented any caching feature (because I'm utterly confused about how it should be done!), but here's what I have for the client proxy so far:
namespace MyCompany.MyProject.Proxies
{
static readonly ChannelFactory<IMyService> channelFactory =
new ChannelFactory<IMyService>("IMyService");
public Response DoSomething(Request request)
{
var channel = channelFactory.CreateChannel();
try
{
Response response = channel.DoSomethingWithService(request);
((ICommunicationObject)channel).Close();
return response;
}
catch(Exception exception)
{
((ICommenicationObject)channel).Abort();
}
}
}
Use the ChannelFactory to create an instance of the factory, then cache that instance. You can then create communicatino channels as needed/desired from the cached istance.
Do you have a need for multiple channel factories (i.e.., are there multiple services)? In my experience, that's where you'll see the biggest benefit in performance. Creating a channel is a fairly inexpensive task; it's setting everything up at the start that takes time.
I would not cache individual channels - I'd create them, use them for an operation, and then close them. If you cache them, they may time out and the channel will fault, then you'll have to abort it and create a new one anyway.
Not sure why you'd want to usea singleton to implement ChannelFactory, especially if you're going to create it and cache it, and there's only one endpoint.
I'll post some example code later when I have a bit more time.
UPDATE: Code Examples
Here is an example of how I implemented this for a project at work. I used ChannelFactory<T>, as the application I was developing is an n-tier app with several services, and more will be added. The goal was to have a simple way to create a client once per life of the application, and then create communication channels as needed. The basics of the idea are not mine (I got it from an article on the web), though I modified the implementation for my needs.
I have a static helper class in my application, and within that class I have a dictionary and a method to create communication channels from the channelf factory.
The dictionary is as follows (object is the value as it will contain different channel factories, one for each service). I put "Cache" in the example as sort of a placeholder - replace the syntax with whatever caching mechanism you're using.
public static Dictionary<string, object> OpenChannels
{
get
{
if (Cache["OpenChannels"] == null)
{
Cache["OpenChannels"] = new Dictionary<string, object>();
}
return (Dictionary<string, object>)Cache["OpenChannels"];
}
set
{
Cache["OpenChannels"] = value;
}
}
Next is a method to create a communication channel from the factory instance. The method checks to see if the factory exists first - if it does not, it creates it, puts it in the dictionary and then generates the channel. Otherwise it simply generates a channel from the cached instance of the factory.
public static T GetFactoryChannel<T>(string address)
{
string key = typeof(T.Name);
if (!OpenChannels.ContainsKey(key))
{
ChannelFactory<T> factory = new ChannelFactory<T>();
factory.Endpoint.Address = new EndpointAddress(new System.Uri(address));
factory.Endpoint.Binding = new BasicHttpBinding();
OpenChannels.Add(key, factory);
}
T channel = ((ChannelFactory<T>)OpenChannels[key]).CreateChannel();
((IClientChannel)channel).Open();
return channel;
}
I've stripped this example down some from what I use at work. There's a lot you can do in this method - you can handle multiple bindings, assign credentials for authentication, etc. Its pretty much your one stop shopping center for generating a client.
Finally, when I use it in the application, I generally create a channel, do my business, and close it (or abort it if need be). For example:
IMyServiceContract client;
try
{
client = Helper.GetFactoryChannel<IMyServiceContract>("http://myserviceaddress");
client.DoSomething();
// This is another helper method that will safely close the channel,
// handling any exceptions that may occurr trying to close.
// Shouldn't be any, but it doesn't hurt.
Helper.CloseChannel(client);
}
catch (Exception ex)
{
// Something went wrong; need to abort the channel
// I also do logging of some sort here
Helper.AbortChannel(client);
}
Hopefully the above examples will give you something to go on. I've been using something similar to this for about a year now in a production environment and it's worked very well. 99% of any problems we've encountered have usually been related to something outside the application (either external clients or data sources not under our direct control).
Let me know if anything isn't clear or you have further questions.
You could always just make your ChannelFactory static for each WCF Contract...
You should be aware that from .Net 3.5 the proxy objects are pooled for performance reasons by the channel factory. Calling the ICommunicationObject.Close() method actually returns the object to the pool in the hope it can be reused.
I would look at the profiler if you want to do some optimisation, if you can prevent just one IO call being made in your code it could far outweigh any optimisation you will make with the channel factory. Don't pick an area to optimise, use the profiler to find where you can target an optimisation. If you have an SQL database for instance, you will probably find some low hanging fruit in your queries that will get you orders of magnitude performance increases if these haven't already been optimised.
Creating the Channel costs the performance so much. actually , WCF already has the cache mechanism for the ChannelFactory if you use the ClientBase in the client instead of the pure ChannelFactory. But the cache will be expired if you make some anditional operations(Please google it for details if you want).
For the ErOx's issue i got another solution i think it is better. see below:
namespace ChannelFactoryCacheDemo
{
public static class ChannelFactoryInitiator
{
private static Hashtable channelFactories = new Hashtable();
public static ChannelFactory Initiate(string endpointName)
{
ChannelFactory channelFactory = null;
if (channelFactories.ContainsKey(endpointName))//already cached, get from the table
{
channelFactory = channelFactories[endpointName] as ChannelFactory;
}
else // not cached, create and cache then
{
channelFactory = new ChannelFactory(endpointName);
lock (channelFactories.SyncRoot)
{
channelFactories[endpointName] = channelFactory;
}
}
return channelFactory;
}
}
class AppWhereUseTheChannel
{
static void Main(string[] args)
{
ChannelFactory channelFactory = ChannelFactoryInitiator.Initiate("MyEndpoint");
}
}
interface IMyContract { }
}
you can customize the logic and the parameters of the Initiate method yourself if you got another requirement. but this initiator class is not limited only one endpoint. it is powerful for all of the endpoint in your application. hopefully. it works well for you. BTW. this solution is not from me. i got this from a book.
I have multiple services in my application. WebService1, WebService2,WebService3 and so on..
All the services have same methods, but they are hosted on different IPs.
Now when a client calls a methodA(1) then
WebService1Client.Method() should be called;
client calls a methodA(2) then WebService2Client.Method() should be called.
I do not want to do a switch case for each and every function on the client.
I would rather prefer to create some class/methods which would return the appropriate proxyClient.
How can I create a class to return the object and further how to use that object.
Please point me to some sample codes or references.
Thanks
If all your services implement the same contract (I mean exactly the same, not a contract with the same methods), you can simply create proxies using the ChannelFactory class and cast the returned object into the contract interface.
This should give you the expected generic behavior.
One way to ensure the same interface is used all over is to put it into a separate class library and share it between all projects. Make sure you configure your service references to reuse types in referenced assemblies.
EDIT: This is how you would use the ChannelFactory, you can get rid of the service reference:
BasicHttpBinding myBinding = new BasicHttpBinding();
EndpointAddress myEndpoint = new EndpointAddress("http://localhost/MathService/Ep1");
ChannelFactory<IMath> myChannelFactory = new ChannelFactory<IMath>(myBinding, myEndpoint);
I am not quite sure why you want to wrap the creation of the proxies into a factory. The easiest usage pattern is to new the proxy where you need it and each time when you need. When you are not running reliable sessions or something other heavy stuff it does not have much overhead to new a proxy instance. On the other hand it makes sure that you have a connection that is working and that the channel is not in a faulted state.
When using the proxy you should make sure to close it when done and abort it when it throws an exception.
var proxy = new Proxy();
try { proxy.SomeMethod(); }
catch { proxy.Abort(); }
finally { proxy.Close(); }
I need some advice on what's the best way to create WCF client proxy wrapper for ASP .NET client. I want to work equally well with ObjectDataSource control with no extra coding and also when I need to manually call WCF service to get some data. I basically have come up with two models, but I'd like to know which is is more efficient.
Here is the first client wrapper
public class Facade1 : IDisposable
{
private readonly IClient proxy = ClientProxyFactory.GetObject<IClient>();
public List<string> GetData()
{
proxy.GetData()
}
public List<string> GetMoreData()
{
proxy.GetMoreData()
}
public void Dispose()
{
ClientProxyFactory.CloseChannel(this.proxy);
}
}
Now here is another WCF wrapper.
public class Facade2
{
public List<string> GetData()
{
IClient proxy = ClientProxyFactory.GetObject<IClient>();
try
{
return client.GetData();
}
finally
{
ClientProxyFactory.CloseChannel(proxy);
}
}
public List<string> GetMoreData()
{
IClient proxy = ClientProxyFactory.GetObject<IClient>();
try
{
return client.GetMoreData();
}
finally
{
ClientProxyFactory.CloseChannel(proxy);
}
}
}
In the first example, there is only one instance of the client proxy and it can be reused between various methods, but the class needs to implement IDisposable so that the proxy can be correctly disposed by the client. In the second example, there is one client proxy per method and the client does not have worry about disposing the proxy.
Is reusing proxy between different method a good way to go? Is there performance hit when you open/close WCF proxy? (In both examples, assume that ChannelFactory is cached and new channel is created every time via cached_factory.CreateChannel() method.)
For example, with the first wrapper I can do something like:
using (Facade1 facade = new Facade1())
{
facade.GetData()
...
...
facade.GetMoreData()
}
In the second example, I can just instantiate my facade and call the needed methods without worrying about disposing a proxy.
Thanks in advance,
Eric
If you use this wrapper for multiple calls to WCF service in single HTTP request processing in your ASP.NET application than the model with shared proxy is better. If you want to share the wrapper (make it global) then second model should be used.
Performance of recreating a proxy is dependent on type of used binding and its configuration. For example in case of BasicHttpBinding recreation of a proxy can be quick because there can still exists persistant HTTP connection from previous proxy. But in case of WSHttpBinding with security context, recreation of proxy means new security handshake for estabilishing security session.