Check if your are in wcf service - c#

I use a WCF service and wonder if I can use the OperationContract methods for the caller and for the service.
Therefore I'd like to know the best way to say if the code is running in the application or in the service.
Like this:
[ServiceContract]
public interface IService
{
[OperationContract]
bool ServiceMethod(string param);
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.Single, UseSynchronizationContext=false)]
public class Service : IService
{
bool ServiceMethod(string param)
{
if(!isInWcfService) //How to do this?
{
//Call this ServiceMethod in WCF Service
}
else
{
//Do the work
}
}
}
Since the calling program and the service knows this class, I think it might be easier if both just have to call this one method and it decides itself if it has to forward the call to the service or can just do to work.
Thank you!

You can check if you are inside a WCF service by checking OperationContext.Current, which is a WCF service class comparable to HttpContext.Current in ASP.NET:
if (OperationContext.Current != null)
{
// inside WCF
}
else
{
// not
}

Related

WCF Services: Requests are limited to a single "Request" Paramater

I have a very strange and obscure issue with WCF services that I was hoping to get some insight on:
I am working a WCF service that we are building to replace one that we no longer have source code for. For some reason, in the new WCF service, everything is forced through a single paramater called "request". Using the WCF test client, this is what it looks like
On the "correct" service, this is what it looks like:
Is there any reason why this would be happening? I've defined all of the requests as follows:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest();
}
Which seems correct, but there may be something I've overlooked that is causing this.
In your original WCF service, there is a request function parameter, and it has a definition similar to the following:
[ServiceContract]
public interface IMyService
{
[OperationContract]
Request SomeRequest(Request request);
}
[DataContract]
public class Request
{
string documentId;
[DataMember]
public string DocumentId
{
get { return documentId; }
set { documentId = value; }
}
}
In the new wcf service:
[ServiceContract]
public interface IMyService
{
[OperationContract]
string SomeRequest(string documentId);
}
So this is because the function parameters are different. Originally your parameter was class, but later changed to string, so the display in WCFTestClient is different.

how can i consume a method from a connected service in .NET WCF and expose it 'AS IS' in a new method in my WCF

My interface look like this:
[ServiceContract]
public interface IMyService
{
[OperationContract]
myConnectedService.SomeComplexResponseType someMethod(myConnectedService.SomeComplexRequestType request);
}
My implementation look like this:
public class MyService : IMyService
{
myConnectedService_client client = new myConnectedService_client();
public myConnectedService.SomeComplexResponseType someMethod(myConnectedService.SomeComplexRequestType request)
{
myConnectedService.SomeComplexResponseType response = client.connectedServiceMethod(request);
return response ;
}
}
The error i get when i am trying to run my service:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
and
error CS0644: 'System.ComponentModel.PropertyChangedEventHandler' cannot derive from special class 'System.MulticastDelegate'

WCF with named pipes: how to allow parallel calls?

this is my first approach to WCF and named pipes.
What I have to do is a windows service listening on a named pipe while a small GUI tells it what to do through the pipe.
Everything works well: calls are made to the service, responses are delivered to the GUI and the job gets done.
But if I send two concurrent requests from the GUI then the service will process them one by one: I would like to manually manage concurrency service-side and let it run both requests at the same time.
I've tried creating 2 different pipes for the 2 requests and it does what I need, but of course it's not a solution.
I'm using .NET Framework 4.0 and I can't change it.
Here's my example code:
SERVICE: pipe configuration
ServiceHost host = new ServiceHost(typeof(CommandReceiver), new Uri[] {new Uri("net.pipe://localhost") });
host.AddServiceEndpoint(typeof(ICommandReceiver), new NetNamedPipeBinding(), "myPipe");
host.Open();
SERVICE: Contract interface and implementation
[ServiceContract]
public interface ICommandReceiver
{
[OperationContract]
string Foo();
[OperationContract]
string Bar();
}
public class CommandReceiver : ICommandReceiver
{
public string Foo()
{
//Do stuffs
System.Threading.Thread.Sleep(3000);
return "FOO";
}
public string Bar()
{
//Do stuffs
System.Threading.Thread.Sleep(3000);
return "BAR";
}
}
CLIENT: pipe configuration
ChannelFactory<ICommandReceiver> pipeFactory = new ChannelFactory<ICommandReceiver>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/myPipe"));
ICommandReceiver serviceProxy = pipeFactory.CreateChannel();
CLIENT: call to the service
public string GetFoo()
{
return serviceProxy.Foo();
}
public string GetBar()
{
return serviceProxy.Bar();
}
Any advice on how to improve the whole thing, even switching to another communication method, would be really appreciate.
Thank you very much in advance!
OK, I've solved this: first of all I was missing the following attribute on my contract implementation class:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class CommandReceiver : ICommandReceiver
{
public string Foo()
{
//Do stuffs
System.Threading.Thread.Sleep(3000);
return "FOO";
}
public string Bar()
{
//Do stuffs
System.Threading.Thread.Sleep(3000);
return "BAR";
}
}
And then I've discovered that the service works perfectly, but not while debugging in visual studio. Releasing and installing it on the system solved the issue.

Async WCF Service and Call Duration Performance Counter

I am trying to measure the Calls Duration performance counter for a WCF service method.
I have a very simple WCF service as given below.
Service interface:
[ServiceContract]
public interface IFooService
{
[OperationContract]
string DoSomeExpensiveOperation();
}
The service implementation:
public class FooService : IFooService
{
public string DoSomeExpensiveOperation()
{
Thread.Sleep(3000);
return "Some valuable information";
}
}
When the implementation is synchronous (as given above), I can see the Calls Duration being populated.
However, when the service implementation is async (as given below), nothing is populated.
Service interface:
[ServiceContract]
public interface IFooService
{
[OperationContract]
Task<string> DoSomeExpensiveOperation();
}
The service implementation:
public class FooService : IFooService
{
public async Task<string> DoSomeExpensiveOperation()
{
Thread.Sleep(3000);
return await Task.FromResult("Some expensive value");
}
}
I've even tried publishing a custom performance counter after the await. Even this did not work.
Appreciate if anyone can shed some light on this.
Thanks!
Call Duration is not supported for async calls (Operation/Service or Endpoint).
Others WCF counters are still valid but not this one.
From MSDN,
When used on an asynchronous WCF service the Call Duration counter
will always return -1.

Caching objects in a RESTful WCF service

I'm looking for a way to cache objects in memory with a RESTful WCF service. The service is completely stateless and is hosted outside of an IIS. I want to implement the caching by myself, so memcached isn't an option.
Right now I'm thinking of hosting a separate stateful System.ServiceModel.ServiceHost that does all the caching. It'll communicate with the rest of the WCF methods through a separate port or by some other means. However I'm not sure if this is the ideal solution to my problem. Has anyone got any tips?
I understand your confusion between stateless service and a stateful host and how the two can interact.
In this code sample I demonstrate conceptually how an in-memory singleton (Caching mechanism, I refer to as CachingProvider henceforth) can be referenced by both the service class (the service instance more precisely during the lifecycle of the request) and the service host (in this case I chose it to be a Console Application)
I assume here, the service interface and class are both located within the console applicaiton project that hosts the service.
In this simple example, my primitive CachingProvider class basically acts as a counter of how many service calls are made to the GetData method, and the service host will poll the CachingProvider every 5 seconds to get the count of service calls made so far.
note: you can use the WCFTestClient utility to test this quickly.
Disclaimer: I by no means suggest that a complex Caching mechanism be implemented as simply as in this sample, this code is merely for demosntration purposes.
namespace ServiceHostConsole
{
[ServiceContract]
public interface ITestService
{
[OperationContract]
string GetData(int value);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class TestService : ITestService
{
public TestService()
{
CachingProvider.CallCount++;
}
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
//For demonstration purposes only
static class CachingProvider
{
static CachingProvider()
{
//private static constructor can initialize
//static cacheable resources
_callCounter = 0; //Trivial example of initialization
}
private static int _callCounter;
public static int CallCount
{
set { _callCounter = value; }
get { return _callCounter; }
}
}
class Program
{
static void Main()
{
using (var host = new ServiceHost(typeof(TestService), new Uri("http://localhost/TestService")))
{
host.Open();
//Example how the ServiceHost can report on a persistent in-memory object that is being
//updated each time the service is called.
new Timer(state => Console.WriteLine("# of service calls: {0}", CachingProvider.CallCount), null, 0, 5000);
Console.Read();
host.Close();
}
}
}
}

Categories