I'm working on a project that is consuming SOAP services via WCF. Initially, we used generated service references because it was easy to get started. This provides ChannelFactory caching and task-based async methods out of the box, which is clearly desirable.
We've recently switched to using service interfaces and instantiating our own ChannelFactory. We treat the ChannelFactory as a singleton object to cache it. On caching the ChannelFactory -- I've been told that a ChannelFactory can go bad if, for example, one of its channels fault. Is this a real concern?
My second question is in regards to using task-based async calls like the ones generated when using the service reference. How is this done when using a ChannelFactory<T>? I understand that you can annotate methods on T with [OperationContract(AsyncPattern = true)], but these return IAsyncResult and not Task.
Any help would be appreciated.
Related
I have gone through the question Singleton Per Call Context (Web Request) in Unity.
Basically I want to create a singleton object per wcf request using Unity Container. Though I found the answers of other question helpful for the ASP.Net web application, I am not sure those answers still apply to WCF service.
The questions is, Using both CallContext and HttpContext in WCF service, can we create PerCallContextOrRequestLifeTimeManager? Would that serve singleton object per wcf call?
Andrew Oakley's Unity Lifetime Managers and WCF.
He creates both a UnityOperationContextLifetimeManager and a UnityInstnaceContextLifetimeManager. Full code is linked at the bottom of the blog. Its not the simplest implementation and takes a little time to fully understand the power of all that's there. But there are good tests included and IMO this is what Unity.WCF should have been. I've used a couple of these myself and been glad that I did.
I'm running a WCF service hosted in a Windows service; dependencies of the WCF service are injected via Unity, which is all good. As a result, the service is also easy to write unit tests for.
Recently, I added functionality to the service that makes use of the OperationContext to inspect incoming messages. Unfortunately this rather blows the testability of the service out of the water, owing to Microsoft's fondness for sealed and/or static classes and lack of interfaces and/or virtual methods.
So I turned to the .NET'ers favourite tool in this situation, a wrapper class. Since this is a common problem, someone's already done the hard work for us. So this adds a new dependency to my WCF service, an implementation of IOperationContext. This was no problem for my unit tests, NSubstitute is my mock framework of choice (like Moq, but without the curse of the .Object).
However, when I try to fire up the service for real, I have the following problem - the OperationContext which is being wrapped has not been initialised at the time the IoC container registrations are done. My initialisation code (using Unity here) is:
container.RegisterType<IOperationContext, OperationContextWrapper>(new InjectionConstructor(OperationContext.Current));
but at this point, OperationContext.Current is null, so Unity promptly throws an exception, and my dreams of retiring before 40 go up in smoke.
So, the question is: how do you get WCF to play nicely with DI and a wrapped OperationContext?
Maybe I'm not understanding, but I'm not sure why you want to inject OperationContext.Current into your wrapper. If OperationContextWrapper is wrapping OperationContext, than why not just have it's implementation interact directly with OperationContext.Current where it needs to? I presume the code you're trying to keep testable is not OperationContextWrapper, but rather the code that depends on it via the IOperationContext interface? Then who care what OperationContextWrapper does?
OperationContext.Current is a settable property. Can you change your test initialization to
OperationContext.Current = new OperationContextWrapper();
and have it work that way? If you need it in unity, you could also:
var oc = new OperationContextWrapper();
OperationContext.Current = oc;
container.RegisterInstance<IOperationContext>(oc);
You can also use Microsoft Fakes :
using (ShimsContext.Create())
{
ShimOperationContext shimOperationContext = new
ShimOperationContext(); shimOperationContext.SessionIdGet = () => "sessionId";
OperationContext.Current = shimOperationContext;
}
I have a c# solution with 3 projects - Data, WCF and UI. The first one is a class library that talks to db. It's exposed via the second one, which is of type WCF Service Library - the reason for that is it will be exposed in third project - Asp.net app called UI - as a simple svc pointing to dll.
Just to point it out, I'm not using Repository pattern.
I need to have ISession for a WCF call (similiar to Session-per-request approach for asp.net). Can anyone share a solution that simply works? I don't want to use any IOC for that.
Use WcfOperationSessionContext (new in 3.0).
Once bound, your Data classes just have to use SessionFactory.GetCurrentSession().
Each call to service is associated with unique OperationContext. OperationContext doesn't have any store for custom objects but you can implement extension. By setting session in MessageInspector you can initiate NHibernate Session per call in centralized place and access your extended context in any operation.
At first I treated them as any dependency passing them in the ctor to the class consuming the service:
var serviceConsumer = new ServiceConsumer(new MailingServiceClient())
The problem was that once an exception was thrown from the service it entered a faulted state and would not reply to any requests, so re-initialization was due.
Further more, I became familiar with the fact that wcf services may not be disposed properly on several occasions, because the dispose method of the generated proxy is broken (calls close without checking the fault state) and encountered a couple of ways to overcome that:
wrapping every call to every service.
override the default IDisposable behavior of the scvutil.exe-generated class
Since I wouldn't like the consumer code to create the service client himself for testing reasons, my questions are:
how can I maintain a working un-faulted service?
how can I still use dependency injection for testability?
Found a nice solution.
a proxy generator that replaces the VS one, and generates a wrapper around the default proxy that deals with proxy faults, timeouts, and correct disposal.
http://wcfproxygenerator.codeplex.com/
seems to be working fine for me.
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.