C# - WCF Message Inspector Doesn't Run - c#

I'm working on refactoring a project that has about 5 different web services, and each web service had a ton of identical code, including adding a message inspector onto the client endpoint behaviors so we could see the request and response data.
Part of the refactoring was to come up with a cleaner model for the web services (e.g. one abstract base service model that did all the common setup, including the addition of the message inspector).
Now, when I make the service calls (invoked via reflection), the service call works perfectly fine, and if I add a breakpoint right after the response comes back, I can see that there are 3 behaviors added to the client's endpoint:
[0] Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior
[1] System.ServiceModel.Description.ClientCredentials
[2] MyProject.MyMessageInspector
...but the message inspector code doesn't seem to get called at all anymore. The inspector code is currently identical to the MSDN example here (except for the class name):
https://msdn.microsoft.com/en-us/library/ms733786(v=vs.110).aspx
The primary difference is that I'm now using generic methods for setting up the client, which looks like this:
...sanity checks, etc...
TClient client = Activator.CreateInstance(typeof(TClient), binding, new EndpointAddress(url)) as TClient;
ClientBase<TInterface> _clientBase = client as ClientBase<TInterface>;
...credentials, timeout, etc...
MyEndpointBehavior _inspector = new MyEndpointBehavior()
_clientBase.Endpoint.Behaviors.Add(_inspector);
Then, when I make a call, I use this code that is located in the new abstract base class (the original code did it this way, and so far the only difference is the use of generics):
ClientBase<TInterface> _clientBase = _client as ClientBase<TInterface>;
using (new OperationContextScope(_clientBase.InnerChannel))
{
// Get the method
MethodInfo mi = _client.GetType().GetMethod(APICall);
// Make the call and return the result if successful
object response = mi.Invoke(_client, APICallParameters);
return response;
}
Any ideas why this worked prior to the switchover to generic methods and not now?

I'm not sure why this made a difference, but I re-ordered the code to move the inspector addition to happen immediately after the client creation, so the code now looks like this:
...sanity checks, etc...
TClient client = Activator.CreateInstance(typeof(TClient), binding, new
EndpointAddress(url)) as TClient;
ClientBase<TInterface> _clientBase = client as ClientBase<TInterface>;
MyEndpointBehavior _inspector = new MyEndpointBehavior()
_clientBase.Endpoint.Behaviors.Add(_inspector);
...credentials, timeout, etc...
The inspector now seems to work as expected. Strange.

Related

How to handle a WCF call per method with lots of methods

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.

.net Remoting - Execute Getter on Host

i'm writing an application that uses .net Remoting via MarshalByRefObject.
I can connect and everything works fine for simple things like method calls.
now the problem is, when i try to access properties on an object i received from an earlier call, the property-getters are execute "client"-side, and not inside the host process.
inside these getters i'm using Marshalling on the local process, so they are required to be running on the host process instead of the client.
My question now: is there any specific way to achieve what i'm trying to do, or will i have to go the route and on the host-side write additional methods in the exposed interface and implementing class, that will return the value of the getters?
My code looks like this:
MyApi api = new MyApi();
var channel = new IpcChannel(processId.ToString());
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.CustomErrorsMode = CustomErrorsModes.On;
RemotingConfiguration.ApplicationName = "MyApi-Server" + processId;
RemotingServices.Marshal(api, "service");
for the host process.
And this is the Client-Side
api = (IMyApi)Activator.GetObject(typeof(IMyApi), "ipc://MyApi-" + process.Id + "/service");
MessageBox.Show(api.GetSomething().Someproperty);
thanks for your help
outch, i'm stupid.
not only the implementation of the interface class should derive from MarshalByRefObject, all the other objects that i'm passing around should too.

How to register two WCF service contracts with autofac

I have a WCF service that implements two service contracts...
public class MyService : IService1, IService2
and I am self-hosting the service...
host = new ServiceHost(typeof(MyService));
Everything was working fine when the service implemented only one service contract, but when I attempt to set up autofac to register both like this:
host.AddDependencyInjectionBehavior<IService1>(_container);
host.AddDependencyInjectionBehavior<IService2>(_container);
... it throws an exception on the second one, reporting:
The value could not be added to the collection, as the collection already contains an item of the same type: 'Autofac.Integration.Wcf.AutofacDependencyInjectionServiceBehavior'. This collection only supports one instance of each type.
At first glance I thought this was saying my two contracts were somehow being seen as the same type but on second reading I believe it is saying that the
AutofacDependencyInjectionServiceBehavior is the type in question, i.e. I cannot use it twice!
And yet, I found this post that explicitly showed using it multiple times in a slightly different form:
foreach (var endpoint in host.Description.Endpoints)
{
var contract = endpoint.Contract;
Type t = contract.ContractType;
host.AddDependencyInjectionBehavior(t, container);
}
Unfortunately, that gave the very same error message.
Is it possible to register more than one service contract on one service and, if so, how?
In fact you can register multiple endpoint for a single host with Autofac.
That is true that you cannot add multiple AutofacDependencyInjectionServiceBehavior but this behaviour iterates through all the endpoints and registers them in the ApplyDispatchBehavior method: source
In order to make this work you need to register your service AsSelf()
builder.RegisterType<MyService>();
Then you can configure your endpoint normally:
host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IService1), binding, string.Empty);
host.AddServiceEndpoint(typeof(IService2), binding, string.Empty);
And finally you need to call the AddDependencyInjectionBehavior with the sevicehost type itself:
host.AddDependencyInjectionBehavior<MyService>(container);
Here is a small sample project (based on the documentation) which demonstrates this behavior.
Update (the bold text) based on #nemesv's answer:
Further investigation revealed that with autofac one cannot register multiple endpoints on a single ServiceHost if one registers the WCF service contracts.
(See #nemesv's answer for the correct way to do it.)
Here is why:
Either form of this extension method...
host.AddDependencyInjectionBehavior<IService1>(_container);
host.AddDependencyInjectionBehavior(t, container);
...resolves down to adding a ServiceBehavior (according to Alex Meyer-Gleaves initial announcement of WCF integration in autofac)...
host.Description.Behaviors.Add(behavior);
Now this Behaviors property is an instance of KeyedByTypeCollection<TItem>, which can hold only only one object of a given type. Since the behavior being added will always be an instance of AutofacDependencyInjectionServiceBehavior, one can therefore only add one endpoint.
QED
The workaround is to use multiple ServiceHosts, each with a single endpoint.
(As a point of interest, I would be curious to know the impact on performance and scalability between those two approaches.)

C# Task.Factory.NewTask and WCF. Why I'm doing wrong?

I have an application in WCF that runs in all machines on my customer. But just one works like a server in the net.
In this model, every time the WCF "client" is called, he call your WCF "server" to obtain your response.
So, I have this configuration on my Interface:
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
MyObjectReturn CheckUpdate(string foo1, string foo2, string foo3);
In my code, this:
MyObjectReturn myObjReturn = new MyObjectReturn();
if (this.Master)
{
myObjReturn.Code = 15000;
myObjReturn.Message = "New Update found";
return myObjReturn;
}
else
{
var myTask = Task<MyObjectReturn >.Factory.StartNew(() =>
{
ServerContractClient server = new ServerContractClient(master.Url);
return server.CheckUpdate(foo1, foo2, foo3);
}
return myTask.Result;
}
When the WCF "client" calls his "server", the return is always null! If I do not use the "Task . Factory.StartNew", I get a Bad Request error
Any tip?
Uh, first, "server" and "client" are the preferred nomenclatures.
Second, Servy has a point that if you want the data back immediately, there's no real point in starting a thread. That said, threads are fun! Who doesn't want to thread? To do it properly you'll have to revise your application a bit, but for now you'll at least have to design the WCF method to be asynchronous, and the client making the call needs to know it's asynchronous; otherwise the result is null, as you experienced. Best starting point is here.
I'm ashamed to say it, but the problem was not what I thought. I noticed that when I called the WCF Server via browser, my return was not null. It was then that I realized that my Binding was the real problem. I noticed that there were two errors:
1) My Bindding is created via code. As noted in my interface, I declared my WebMessageBodyStyle as WrappedRequest. But when creating the Binding Client, I was using Wrapped;
2) The namespace of my ServiceBehavior and DataContract were different, which also caused confusion in WCF.
This link helped me clarify this last point:
WCF Web Service Call to Another WCF Web Service returns no data
Anyway, thank you all who gave me very valuable tips on this problem.

Writing a generic WCF service client config/endpoint checker?

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.

Categories