Async WCF Service and Call Duration Performance Counter - c#

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.

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.

Call async method in AddTransient in Startup - Asp.Net Core

I have a service which is used to get some information and the method has a bunch of async calls in the chain.
public interface IFooService
{
Task<IFoo> GetFooAsync();
}
The concrete class,
public class FooService : IFooService
{
public async Task<IFoo> GetFooAsync()
{
// whole bunch of awaits on async calls and return IFoo at last
}
}
I register this service on StartUp,
services.AddTransient<IFooService, FooService>();
Several other services are injected with this service. One among them,
public class BarService : IBarService
{
private readonly IFooService _fooService;
public BarService(IFooService fooService)
{
_fooService = fooService;
}
public async Task<IBar> GetBarAsync()
{
var foo = await _fooService.GetFooAsync();
// additional calls & processing
var bar = SomeOtherMethod(foo);
return bar;
}
}
IFoo is integral to the application and used across several services. Most of my code is async just due to this one IFooService and the one method it has which returns IFoo.
Considering this use case, I would like to be able to just inject IFoo to all other services as opposed to injecting them with IFooService.
I gave this a shot,
services.AddTransient<IFoo>(provider =>
{
var fooService = provider.GetService<IFooService>();
var foo = fooService.GetFooAsync().GetAwaiter().GetResult();
return foo;
});
but it raises a red flag to me as I'm doing sync over async and I'm unsure if this will cause any issues like race conditions. Would startup be blocked by doing this. Im looking for a clean way to handle this, any recommendation for when we need something like this? Thank you for your help.
I guess what you want is an async constructor, which is not recommended.
here is more info about it and contains a solution using Lazy<T>.
but it raises a red flag to me as I'm doing sync over async
For this red flag, it is caused by that you call method GetFoo which is not defined in IFooService, it is not related with async or sync method.
Try the method which is defined
services.AddTransient<IFoo>(provider =>
{
var fooService = provider.GetService<IFooService>();
var foo = fooService.GetFooAsync().Result;
return foo;
});
2 Other options
Inject Func<Task> as the transient, the caller can await !
Task.Run( async () await abc).Wait(); // this deadlocks much less
due to creating a task and having less issues .

Implementing async/await pattern for manually generated WCF (client-side) proxies

Given this interface
[ServiceContract]
public interface IProductService
{
[OperationContract]
Product Get(int id);
}
I would like to manually (that is, without using scvutil or Add Service Reference in VS) create a client-side proxy.
I do it in the following way
public class ProductService: IProductService
{
readonly ChannelFactory<IProductService> factory;
public ProductService()
{
factory = new ChannelFactory<IProductService>("*");
}
public Product Get(int id)
{
var channel = factory.CreateChannel();
return channel.Get(id);
}
}
My problem is that I also want async/await version of this method, only on client-side, server side is still synchronous.
I want this to be a generic solution because I have many methods and services of this sort.
If you're using ChannelFactory to allow for async-await your interface needs to return a Task or Task<T>.
It will force your server side to also return a task but you can do that synchronously with Task.CompletedTask and Task.FromResult if you insist on keeping it synchronous (though why would you if you have the option).
For example:
[ServiceContract]
interface IProductService
{
[OperationContract]
Task<Product> GetAsync(int id);
}
class ProductService : IProductService
{
ChannelFactory<IProductService> factory;
public ProductService()
{
factory = new ChannelFactory<IProductService>("*");
}
public Task<Product> GetAsync(int id)
{
var channel = factory.CreateChannel();
return channel.GetAsync(id);
}
}
class ProductAPI : IProductService
{
public Task<Product> GetAsync(int id) => Task.FromResult(Get(id))
}
You can actually do that without changing the service itself. You can simply define a second interface which contains async and Task returning versions of the methods and is marked with [ServiceContract(Name = "NameOfTheIterfaceWhichIsActuallyExposedOnTheServer")]
In the example you mentioned you would define a second interface with GetAsync() operation:
[ServiceContract(Name = "IProductService")]
public interface IProductServiceAsync
{
[OperationContract]
Task<Product> GetAsync(int id);
}
and even though your service still implements and exposes IProductService you can use ChannelFactory<IProductServiceAsync> to call into it. As long as the method names match the GetFoo/GetFooAsync pattern everything will just work. That's how Add Service Reference in Visual Studio can generate you an async service reference to a synchronous service.
See Calling a synchronous WCF method asynchronously using ChannelFactory for a more detailed explanation on how this work.

Check if your are in wcf service

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
}

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