My WCF service uses callbacks. To be able to call all clients, I'm using something like this:
[ServiceBehavior (InstanceContextMode = InstanceContextMode.PerSession)]
class Svc
{
// stores all connections
private static List<Svc> Connections = new List<Svc> ();
// callback for this instance
private ICallback Cb;
public Svc ()
{
Cb = OperationContext.Current.GetCallbackChannel<ICallback> ();
Connections.Add (this);
}
// ... lots of other code that uses or updates the list of connections
}
Is this the right way to do it?
I'm asking because I'm fighting with an apparent design problem in the above approach. I tried to move a lot of common code, including the static List<Svc> to a common base class that can be used by all my WCF services. But when deriving, this list is shared among all subclasses.
I then tried to avoid this undesirable sharing by making the base class generic (Svc<T>, meaning each subclass gets its own static members) but this leads to other annoyances and is not a clean design.
Yes, this is the right approach of storing references to your clients to send callbacks to all of them. I don't store the CallbackChannel objects but the OperationContext instances in my service.
To your other question: You could extract the code to administrate the list of connected clients to a separate class and use an instance of that class in your service.
Use the Singleton pattern when you need to store global state in a centralized manner.
In your case it could look like this:
public Svc()
{
this.CallbackChannel = OperationContext.Current.GetCallbackChannel<ICallback>();
// The static 'Instance' property returns the singleton
SvcActiveInstanceContainer.Instance.Add(this);
}
Related resources:
Singleton Design Pattern
Related
I have question about the article in here. The related code is as follow.
public CustomClientChannel(string configurationPath) : base(typeof(T))
{
this.configurationPath = configurationPath;
base.InitializeEndpoint((string)null, null);
}
protected override ServiceEndpoint CreateDescription()
{
ServiceEndpoint serviceEndpoint = base.CreateDescription();
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = this.configurationPath;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
ServiceModelSectionGroup group = ServiceModelSectionGroup.GetSectionGroup(config);
ChannelEndpointElement selectedEndpoint = null;
......
}
The first function is the constructor of the class and the second one overloads the CreateDescription function in DuplexChannelFactory since the class inherents from DuplexChannelFactory.
However, when I use this class to create an object, the code runs directly into CreateDescription().
Therefore, even though I pass a configurationPath to the constructor, the this.configurationPath is still null.
If I inherent CustomClientChannel class from ChannelFactory, then it works fine.
Please help to see what is wrong and what is the difference between ChannelFactory and DuplexChannelFactory? I am using netTcpBinding. Thank you.
Your constructor is calling into a base constructor that takes a single type.
: base(typeof(T))
Both ChannelFactory<T> and DuplexChannelFactory<T> implement a protected constructor that takes a single type, but they are different.
ChannelFactory<T> wants the channel type.
DuplexChannelFactory<T> want the callback instance type
In other words, they do completely different things and can have completely different code paths. Protected constructors are to be used by derived types only, and generally infer some level of knowledge of how the class hierarchy works.
You would be better picking the public constructor that you would normally use, and calling that instead. If that is not possible then you need to work out the appropriate DuplexChannelFactory constructor to call instead.
Let's start with
what is the difference between ChannelFactory and
DuplexChannelFactory?
First it is necessary to understand the difference between simplex and duplex communications in WCF.
A simplex connection is like sending a text message and then receiving a delivery notification - even though at a lower transport level there may be multiple calls between your phone and the carrier, from a communications level, you are sending the text message in one direction only.
A duplex connection is like making a phone call, you are able to send voice data to your carrier, and your carrier can send voice data in the other direction at the same time. This requires a simplex channel open in both directions.
Both ChannelFactory and DuplexChannelFactory can be used to create a client channel to a service.
Which one you choose is down to whether the service you are calling exposes simplex or duplex service operations, and whether you, as a comsumer, need to consume these operations.
If the service exposes normal (i.e, simplex) operations, for example:
void DoCoSomething(int x);
List<Things> GetThings();
etc...
...then you can consume these operations with ChannelFactory.
If the service exposes a callback contract:
public interface IMyDuplexCallback
{
[OperationContract(IsOneWay = true)]
void NotifyMeOf(string message);
}
for example, in order to send notifications or message of some kind to the consumers, and you as a consumer want to take advantage of this, you can use the DuplexChannelFactory to call the service (after implementing the callback contract on your client of course).
As a general rule, duplex communication in WCF is complex at best, and is therefore best avoided.
Appreciate this does not address your original question.
I have created a WCF service which reads from a database and sends back results. For performance reasons I'd like to cache the tables on service startup (which happens in a windows service OnStart). But there's no such thing as constructors in WCF (right?) so best thing I came up with is create an Init() function and call that like the following:
protected override void OnStart(string[] args)
{
mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
((DLSService.DLSService)mServiceHost.SingletonInstance).Init();
mServiceHost.Open();
}
But using SingletonInstance and casting to the correct type does not seem all that elegeant to me.
Are there more elegant ways to achieve constructor like functionality in WCF?
The recommended best practice is to use the per-call activation model in WCF and keep the services totally stateless.
This means: every time the client makes a request, on the server-side, an instance of your service implementation class will be created, the requested service call will be made, and then the service class will be destroyed again.
So putting your initialization code into the service implementation class constructor would be a really bad idea - it would be executed for each and every single request.
What you could do is have some kind of logic (either in your service class, or some support code, e.g. some kind of an admin interface) that would load those tables you want to cache into a persistent cache, e.g. something like the AppFabric cache. Once done, multiple service instances handling requests could use that common cache to get better performance.
This can be solved with a memoization library, like MbCache. We are doing exactly what you are looking for; on application start-up we call each service operation that we want to cache, and MbCache caches the result for consecutive calls (i.e. no database round-trip to get results) until the cache expires.
MbCache does come with its on fair share of complexity, but once it is running it works very well and handles all the cache logic for us.
You can use the IInstanceProvider interface to create your service, read this article for more information.
Here's an example of code:
public class CustomInstanceProvider:IInstanceProvider
{
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return new DLSService.DLSService();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
var mServiceHost = new ServiceHost(typeof(DLSService.DLSService), new Uri("http://localhost:8000/DLS"));
mServiceHost.AddServiceEndpoint(typeof(DLSService.IDLSService), new BasicHttpBinding(), "ServicesHost");
foreach (var channelDispatcher in mServiceHost.ChannelDispatchers.OfType<ChannelDispatcher>())
{
foreach (var endpointDispatcher in channelDispatcher.Endpoints)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new CustomInstanceProvider();
}
}
mServiceHost.Open();
With framework 4.5 you can use a configuration's function in your service implementation code:
http://msdn.microsoft.com/en-us/library/hh205277(v=vs.110).aspx.
I'll try to explain what I want in code, cause can't formulate it in words.
I have some kind of resource and I encapsulate its usage in a WCF service, and I have a resource manager that controls access to this resources which is also a WCF service, something like this:
//Allows only one client to use it at the same time...
public interface IResource
{
string GetResourceDescription();
void DoWork();
void BeginWork();
void EndWork();
}
//Governs access and location of resources
public interface IResourceManager
{
IEnumerable<string> GetResourcesDescriptions();
bool IsResourceAvailable(string resourceDescription);
void BeginWorkWith(string resourceDescription);
void DoWorkWith(string resourceDescription)
void EndWorkWith(string resourceDescription);
}
What I don't like in this code is that when working with IResourceManager I need to always tell what resource I want to use for service operation, so basically IResourceManager have the same service operations as IResource but takes additional IResource identifier as parameter.
What I want is:
public interface IResourceManager
{
IEnumerable<string> GetResourcesDescriptions();
//I want it to return service proxy (ICommunicationObject)
IResource GetResource(string resourceDescription);
}
First this is impossible, second, the clients can't communicate with IResource directly on network layer (there is no direct connection).
So far I found only one not ugly solution, to create a client side wrapper, that mimics this behavior. How to implement, and use such WCF services?
Keep in mind that objects returned from service operations are only data. On the other side of communication channel, these objects will be "dead" (will contain only data, no methods). The only way to deal with it, is the way you solve it. Client side wrapper sounds nice and I think it is reasonable solution.
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 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.