As the title implies I am trying to get an understanding of why in WCF sometimes people choose to "generate proxies" vs using a ChannelFactory to manually create new channel instances. I have seen examples of each, but haven't really found any explanations of WHY you would go for one vs the other.
To be honest I have only ever worked with channels and the ChannelFactory<T> from code I have inherited, ie:
IChannelFactory<IDuplexSessionChannel> channelFactory =
binding.BuildChannelFactory<IDuplexSessionChannel>();
_duplexSessionChannel = channelFactory.CreateChannel(endpointAddress);
So why would I "generate a proxy"? What are the benefits and drawbacks?
The main difference is this:
generating a proxy only requires you to know the URL where the service resides. By generating the proxy, everything else (the service contract and the data contracts involved) will be determined by inspecting the metadata of the service
in order to directly create a ChannelFactory<T>, you must have direct access to the assembly that contains that service contract T for which you're generating a channel factory. This only ever works if you basically control both ends of the channel and you can share the assembly that contains those service contracts. Typically, with a third-party service, this won't be the case - with your own services, yes.
The second important point is this:
creating a generated proxy basically does the two steps that you would do - create a ChannelFactory<T>, and from that, create the actual channel - in a single constructor. You have no control over these two steps.
doing your own Channel creation is beneficial, since the creation of the ChannelFactory<T> is the expensive step - so yo could cache your channel factory instance somewhere. Creating and re-creating the actual channel from the factory is much less involved step which you can do more frequently
So if you do control both ends of the communication, service and client, you do have the option to share the service contracts in a separate assembly, and thus you have more options.
With most third-party services, you just simply don't have that option.
Using a proxy is simpler and easier to understand. You get to deal in terms of simple things - classes and methods on those classes - instead of complex, network-related things like channels.
OTOH, this is not made easier by the design flaw in WCF that prevents the same simple use of a WCF proxy that we could do with ASMX proxies:
using (var client = new MyServiceClient())
{
}
If you use this pattern with WCF, you can lose the original exception when the block is exited due to an exception. client.Dispose() can throw an exception, which will overwrite the exception originally being thrown. A more complex pattern is required.
This may help you:
When to use a proxy?
If you have a service that you know is going to be used by several applications or is generic enough to be used in several places, you’ll want to use the proxy classes.
When to use ChannelFactory?
ChannelFactory class is used to construct a channel between the client and the service without the need of a proxy. In some cases, you may have a service that is tightly bound to the client application. In such a case, you can reference the Interface DLL directly and use ChannelFactory to call your methods using that.
You could also refer following link to understand the difference between Channel Factory and Proxy class
http://ashishkhandelwal.arkutil.com/wcf/channelfactory-over-proxy-class-in-wcf/
The main advantage of the channelFactory is you can create the proxy at runtime dynamically on the fly. With SvcUtil (Add web reference in VS) you create the proxy at design time, so it's implementation is more static.
Related
I went through many posts but, i did not able to clear my some of basic doubts related to WCF service as follow:
Why should we keep separate class library projects assembly for Service.Contracts and Service.Implementation ?
we can implement one interface multiple times even it in single assembly.
It suppose to create - WCF Application project and maintain interfaces into separate folder and SVC.cs file separately.
Add service reference is not good option as it adds all the schemas into client side.
svcutil.exe is also do same thing. Then, what is the best way to consume wcf service at client side ?
All is explained in this great article - WCF the Manual Way…the Right Way.
Essentially, Add Service Reference and svcutil just lead to client proxies that become out of date over time; and the fact that the solution has multiple types defined for what are essentially the same class.
Update: Since writing this answer I have learnt not to have answers in another castle so I update below:
Essentially, WCF the Manual Way…the Right Way describes that rather than using Add Service Reference, you instead divide your WCF system into separate dlls for:
Contracts
Service implementation
Roll-your-own client proxies
Both the service and client add normal code references (not service references) to the contracts dll.
In this way, the service and client are using the same types (and not code-generated ones in the client) and when the contract changes - both the service and client are forced to update less a compile error appears. No more out-of-date clients.
The project I'm currently working on includes a server that receives C# scripts (partial code) from clients, wraps it to create a complete class, compiles it then load it into a separate AppDomain for execution.
A task (currently running script) can send feedback to the user at any point of it's execution, as defined in the script by the user. And possibly the task might wait for a response from the user (currently assuming it's only right after having sent feedback). And the user might, at any moment, decide to kill a task.
The server is implemented as a Windows Service hosting a WCF Service Library.
As I don't want to overcomplicate the client to make it communicate directly with the dynamically created AppDomains, the (partial) solution that I considered after some research was hosting a second WCF service with named pipe binding to make the dynamic AppDomains use it as a relay between them and the client facing WCF service.
My issue is that now I can't think of a clean way to have the two WCF services interact.
My ideas are:
Having them maintain direct references to each other:
Seeing as Normally both of the services are singletons it shouldn't be hard to do.
But that would be a pain to maintain in the case one of them fails and needs to be restarted. (I'm still new to WCF so I have no idea how common that is, but it's still an issue to consider. I think.)
Introducing some sort of a "message queue" (or two, one for each direction) with properties that can be set and subscribed to. Thus when one service sets a property an event will be triggered in the second. But that feels somewhat hacky to me, even though I can't really think of any clear issues.
I could really use some expert input on what I'm trying to accomplish, be it opinions on my thoughts or new ideas. Even if that involves rethinking the architecture. This project is still in an early enough stage to afford some rework, as long as there is enough reason to do that of course.
Since I've put lots of efforts (read: 2 minutes on paint) to prepare a quick (read: useless) schema of the system, I'll link it here since I don't have the reputation to post images:
Link to schema
Edit:
As I now have the reputation thanks to an upvote:
Still after rereading my question, I feel that perhaps I have been looking at this issue from a too narrow perspective by thinking of the services as something more special than ordinary classes. The more I think about it the more I feel that the observer pattern is probably the best approach to take.
Just for the record, and to avoid leaving my (silly) question unanswered, I've realised that I was looking at this too narrowly by trying to find a solution specific to WCF services.
And finally I ended up using a variation of the observer pattern (based on the IObservable<T>Interface).
I came across the same issue. The way I handled a duplex communication between the two servers is as following:
For each process (AppDomain Seperated Task) create a pair of WCF services. Both services have their Instancing set to PerSession (no need for singleton which may cause problems in the long run like disconnect). This means the Client will be communicating for each process (AppDomain Separated Task) with two distinct Service instances or a service pair (i.e. Service1 and Service2).
We want a duplex communication in between these two services, which means that both can communicate with the other and pass data (in the form of a DataContract class object).
For this:
1- Declare two services (i.e. in a separate class library) and host them (self hosting or else).
2- Create your DataContract class and add any property, collection, enum etc. as you like. Both services must have a get-set property for this class.
3- In the same class library (where the Service1 and 2 classes reside), create another class. This class will act as a depository for the Service pair instances. It has a static List in order to register the service pair instances (you can identify each service with a GUID).
4- We setup the client proxy using svcUtil.exe (or by code). When the client makes a service request, a service (i.e. service1) will be created by the WCF. At service1, create or launch the process (App Domain Separated Task) as client2 and at its constructor create the Service2 proxy by code.
5- Initialize the Service2 instance (i.e. by a call to the service2) and register the service pair instances at static list of the depository (so that it can be retrieved later for duplex communication). Now we have both service instances and both of them are registered as a pair into a static list.
6- Start communication between both services by making a call from Client1 proxy.
7- At Service1 call method, retrieve the service pair from the static list. Deep copy (DeepClone) the Datacontract class object from Service1 to the Service2 using the get-set property mentioned at (2). (Note that you can use one of the many Deep Clone libraries from Nuget like DeepCloner).
8- Make a call back from Service2. Client2 now has the identical DataContract class property values as Client1
9- Repeat steps 6-8 for Client2 proxy for Service2-Service1 communication.
Just wondering under what circumstances would you prefer to generate a proxy from a WCF service when you can just invoke calls using the ChannelFactory?
This way you won't have to generate a proxy and worry about regenerating a proxy when the server is updated?
Thanks
There are 3 basic ways to create a WCF client:
Let Visual Studio generate your proxy. This auto generates code that connects to the service by reading the WSDL. If the service changes for any reason you have to regenerate it. The big advantage of this is that it is easy to set up - VS has a wizard and it's all automatic. The disadvantage is that you're relying on VS to do all the hard work for you, and so you lose control.
Use ChannelFactory with a known interface. This relies on you having local interfaces that describe the service (the service contract). The big advantage is that can manage change much more easily - you still have to recompile and fix changes, but now you're not regenerating code, you're referencing the new interfaces. Commonly this is used when you control both server and client as both can be much more easily mocked for unit testing. However the interfaces can be written for any service, even REST ones - take a look at this Twitter API.
Write your own proxy - this is fairly easy to do, especially for REST services, using the HttpClient or WebClient. This gives you the most fine grain control, but at the cost of lots of service API being in strings. For instance: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - if the details of the API change you won't encounter an error until runtime.
Personally I've never liked option 1 - relying on the auto generated code is messy and loses too much control. Plus it often creates serialisation issues - I end up with two identical classes (one in the server code, one auto generated) which can be tided up but is a pain.
Option 2 should be perfect, but Channels are a little too limiting - for instance they completely lose the content of HTTP errors. That said having interfaces that describe the service is much easier to code with and maintain.
I use ChannelFactory along with MetadataResolver.Resolve method. Client configuration is a bother, so I get my ServiceEndpoint from the server.
When you use ChannelFactory(Of T), T is either the original contract that you can get from a reference in you project or a generated contract instance. In some projects, I generated the code from a Service Reference because I could not add a reference to the contract dll. You can even generate an asynch contract with the service reference and use that contract interface with ChannelFactory.
The main point of using ChannelFactory for me was to get rid of the WCF client config information. In the sample code below, you can see how to achieve a WCF client without config.
Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()
In my final project, the availableBindings are checked to use net.tcp or net.pipe if available. That way, I can use the best available binding for my needs. I only rely on the fact that a metadata endpoint exist on the server.
I hope this helps
BTW, this is done using .NET 3.5. However it does work also with 4.0.
Well in order to use ChannelFactory<T> you must be willing to share contract assemblies between the service and the client. If this is okay with you then ChannelFactory<T> can save you some time.
The proxy will build async functions for which is kind of nice.
My answer is a kind of summary of Keith's and Andrew Hare's answers.
If you do not control server, but have only WSDL/URL- generate proxy using Visual Studio or svcutil. (Note that Visual Studio sometimes failed, when svcutil works better).
When you control both server and client, share interfaces/contracts and call ChannelFactory
.
It's not just a matter of time saved. Using the WSDL generated proxy is dangerous because if you forget to update the service reference you can leave the solution in an inconsistent state. Everything compiles but the service contract is broken. I definetly suggest to use a ChannelFactory whenever possible, you make your life much easier.
A possible alternative could be to write a prebuild script that calls the SVCUtil utility to create the proxy everytime you build your project, but anyway ChannelFactory is much more neat and elegant.
I have a WCF server that is a library assembly. (I am writing it so I can mock the level below it) It is called var a client helper class that is in a different assembly. As the data that is transferred is complex and the server has to send call-backs to the clients I wish to test the WCF code in isolation.
(I am only interested in the TCP channel or NamePipe channel)
I do not wish to mock WCF, as the risk I am trying to control is my usage of WCF.
It there a easy way to
Load my WCF server into a different app domain
(I could load the WCF server into the main app domain, but then I it harder to prove that the objects were serialized correctly rather than just pointer moved about.)
Setup all the WCF config so the client class can call it (most likely named pipes or TCP)
And use it in some nunit test
I rather not have my unit tests depending on config file.
I expect (hope) that there are some util classes for setting up WCF unit test that I can just pass the type of my server class to and will give me back a client factory that connects to the server.
Am I going about this the wrong way, e.g there a better way of testing my communication layer and usage of WCF?
It is by far the easiest approach if you spin up the service in-proc, because then you don't need to write a lot of complex synchronization code to determine when the service is running and when it isn't.
Don't worry about pointers being passed around - they won't (unless you choose the new in-proc binding in WCF 4). It's the binding that determines how and if objects are serialized. Named pipes are excellent for this purpose.
I always spin up a new ServiceHost in each test case inside a using statement, which effectively guarantees that the host is running before calls are being made to it, and that it is properly closed after each test. This last part is important because it ensures test independence.
You may also want to look at a series of blog posts I wrote about a very similar subject.
You can use SOA Cleaner for testing your WCF. Take a look at http://xyrow.com
no installation is needed. It's not unit testing, but it can be very helpful (you can have it run on your build, as it supports command line too).
When working with WCF services, is it better to create a new instance of the service every time you use it? Or is it better to create one and re-use it? Why is either approach better? Is it the same for asynchronous proxies?
Or is it better to create one and re-use it?
Do not start to implement your own pooling implementation. That has already been done in the framework. A WCF proxy uses cached channels factories underneath. Therefore, creating new proxies is not overly expensive (but see Guy Starbuck's reply regarding sessions and security!).
Also be aware that a proxy times out after a certain idle time (10mins by default).
If you want more explicit control you might consider using ChannelFactories and channels directly instead of the "easy to go, full out of the box" ClientBase proxies.
http://msdn.microsoft.com/en-us/library/ms734681.aspx
And a "must read" regarding this topic is:
http://blogs.msdn.com/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx
in addition to the things Guy Starbuck mentioned a key factor would be the security model you're using (in conjunction with the session requirements) - if you don't re-use your proxy, you can't re-use a security sessions.
This means that the client would have to authenticate itself with each call which is wasteful.
If, however, you decide this is what you wish to do, make sure to configure the client to not establish a security context (as you will never use it), this will save you a couple of roundtrips to the server :-)
One more point to consider is channel faults. By design WCF does not allow to use client proxy after unhandled exception happened.
IMyContract proxy = new MyContractClient( );
try
{
proxy.MyMethod( );
}
catch
{}
//Throws CommunicationObjectFaultedException
proxy.MyMethod( );
There is a corollary here to Server Activated Objects in .NET Remoting (one of the technologies that is replaced by WCF), which have two modes, "Single Call" (stateless) and "Singleton" (stateful).
The approach you take in WCF should be based on your performance and scaling requirements in conjunction with the needs of your consumers, as well as server-side design constraints.
If you have to maintain state between calls to the service, then you will obviously want to have a stateful instance, but if you don't you should probably implement it so that it is static, which should scale better (you can more easily load balance, etc).