I'm in the process of converting our WCF services to use async programming. As expected the interface looks like this:
public interface IFoo
{
Task<string> DoSomething(string request);
}
On the client side I'm not creating a service reference from Visual Studio. Since I own both client and server I just share the interface with the client, then I create (and cache) a ChannelFactory. To invoke the method asynchronously I use the expected syntax:
IFoo clientChannel = channelFactory.CreateChannel();
bool result = await clientChannel.DoSomething("Hello World");
My question is: Is the IClientChannel generated by the ChannelFactory really using the async features underneath? I mean, can I be sure there's no thread blocked waiting for the server response?
Looking at the ClientBase code, async calls all boil down to:
http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Channels/ServiceChannel.cs,0353de22100bb396
There doesn't seem to be any reason to think the thread would block waiting for a network response.
Related
I am trying to call grpc server that implements code first service. I am unable to call that service from client if I add CallOptions to the service method parameters for passing bearer token.
When I execute the client it throws the following exception:
Unhandled exception. System.NotSupportedException: Specified method is not supported.
at ProtoBuf.Grpc.Internal.Proxies.ClientBase.ICustomerService_Proxy_0.ICustomerService.CreateCustomer(CreateCustomerCommand , CallOptions )
If I remove the CallOptions parameter and then execute the call it works perfectly as it should.
Additionally, Grpc.Core.Api package referenced in client and server have the same version.
Service Implementation
[Authorize]
public class CustomerService : ICustomerService
{
IMediator _mediator;
public CustomerService(IMediator mediator)
{
_mediator = mediator;
}
public Task CreateCustomer(CreateCustomerCommand request, CallOptions callOptions)
{
return _mediator.Send(request);
}
}
Can someone please tell me if I am missing anything or if I can pass token in my grpc request in a better way?
thanks #Marc Gravell for the support. I have copied the solution here:
short version: use CallContext, not CallOptions; CallContext has a .CallOptions, or many of the expected features are directly available (for example, .RequestHeaders, .CancellationToken, etc)
longer version: protobuf-net.Grpc, being code-first, attempts to unify the client and server APIs so that the same interface (presumably ICustomerService in this case) makes sense for both the client and server side. This is not possible with CallOptions (client) vs ServerCallContext (server), so protobuf-net.Grpc creates CallContext which bridges the gap between both
I have created WCF service in VS2015:
[ServiceContract(CallbackContract = typeof(IMyCallback))]
public interface IMyService { }
IMyCallback looks like:
[ServiceContract]
public interface IMyCallback {
[OperationContract]
Task<string> OnServerEvent(UserAppEventData evData);
I've built the server, run it, then added service reference (by right click on solution explorer).
The client object is defined as
[CallbackBehaviorAttribute(
ConcurrencyMode = ConcurrencyMode.Reentrant,
IncludeExceptionDetailInFaults = true,
UseSynchronizationContext = true,
ValidateMustUnderstand = true
)]
public class QMyClient : IMyCallback { }
Automatically generated interface implementation made method in sync manner:
public string OnServerEvent(UserAppEventData evData) { }
This code does't work (and isn't asynchronous) and hangs client at OnServerEvent.
When I changed code manuallly to
public async Task<string> OnServerEvent(UserAppEventData evData)
and have done the same in auto generated "service references\...\Reference.cs, all works fine. But I don't want to change Referenece.cs every time I'm updating Service Reference.
Is there any method to force "Update Service Reference" make TBA OperationContractAttribute on callback?
At ordinary WCF service direction everything works OK, VS generates task based operations.
By default the service reference you've added to solution doesn't have asynchronous operations, but you can enable them and decide which option you use for your async methods - task-based or old-fashion asynchronous. This option is available in Advanced settings for service reference.
If you're using a svcutil tool, it will create the task-based methods by default, however, you can change that behavior by some flags like /async or /syncOnly.
What #VMAtm suggested will work out just fine.
I think, you could also use ChannelFactory for this scenario. It is very flexible and you can then await on the service operations from client side. Additional benefit, you don't need to modify client when there are these kind of changes on service side.
Something like:
var channelFactory = new ChannelFactory<IService>(
"WSHttpBinding_IService" // endpoint name
);
IService channel = channelFactory.CreateChannel();
string result = await channel.OnServerEvent();
Console.WriteLine(result);
Please note that for this scenario, you will have to import common interface library to client side as dll because then it will need to know about contracts and data contracts.
I'm working with .Net 4.5 and my services are written using Async and returning Task<>.
When I call the service from the client I use await.
When the service returns after the await it seems that the channel is blocked if the client code calls another operation which is not async.
Sample code:
value = await Service.InitAsync();
Service.SyncOperation(); // Further callbacks/return values from Server are blocked and this statement never returns
(The whole point of async/await as I see it is to allow me to write the full flow in one method and let the framework deal with threads and callbacks)
I was able to solve this by wrapping the call to the service with a new task and then Task.Yield:
async Task<T> CallAsync<T>(Func<Task<T>> func)
{
Task<T> t = await func;
await Task.Yield();
return t;
}
and in the client:
value = CallAsync(Service.InitAsync);
Service.SyncOperation(); //Now the server is not blocked since Yield changed back to the client context.
My question is, is there any other way to do this without wrapping the Service call in the Client?
Maybe some attribute or property in the Service?
Thanks
I have some problems with mocking WCF services:
1) I declare a class with empty methods which only implements my service interface:
public class MyFakeService : IMyService {
...
public virtual MyResult GetResult(MyResponse response){
throw new NotImplementedException();
};
}
2) I have the MyResponse class:
public class MyResponse {
public long myField;
}
3) I create a mock of the service class and a service host to host this fake service:
myFakeService = mocks.StrictMock<MyFakeService>();
ServiceHost host = new ServiceHost(myFakeService);
(here I have ommited the endpoint configuration etc.)
4) And now I try to test my client. The client.GetSomethingFromService() method exactly calls the GetResult(MyResponse) method of the service.
With.Mocks(mocks)
.Expecting(() => Expect
.Call(myFakeService.GetResult(null))
.IgnoreArguments()
.Constraints(PublicField.Value("myField", 777))
.Return(new MyResult()))
.Verify(() => myClient.GetSomethingFromService());
The issue is that if something wrong in the service, I can only see something like this:
System.ServiceModel.CommunicationObjectFaultedException:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used
for communication because it is in the Faulted state.
How do I know what exactly wrong? Maybe arguments constraints verification failed or something else...?
Thanks.
Firstly, avoid using strict mocks. They're a bad practice because they make your tests too brittle.
Secondly if you're testing a WCF service you don't need to spin up a ServiceHost since you'll then be doing an integration test. You're just wanting to test the logic of your service, not the WCF infrastructure.
For a run through of how to use RhinoMocks and WCF services have a look at my blog post on unit testing WCF services
I'm trying to use RhinoMock for mocking out a wcf service.
Say I have the following service:
[OperationContract]
List<User> SearchUsers(UserSearchFilter filter);
Adding this service with Visual Studio will generate a proxy, and that proxy has a Interface like:
public interface ResourceService {
System.IAsyncResult BeginSearchUsers(UserSearchFilter filter, System.AsyncCallback callback, object asyncState);
ObservableCollection<User> EndSearchUsers(System.IAsyncResult result);
}
Then I create a ViewModel that uses this service, like this:
private ResourceService service;
public ViewModelBase(ResourceService serv)
{
service = serv;
var filter = new UserSearchFilter();
service.BeginSearchUsers(filter, a =>
{
this.Users = service.EndSearchUsers(a);
}, null);
}
Then comes the question. How do I mock this service using RhinoMock?
[TestMethod]
public void UserGetsPopulatedOnCreationOfViewModel()
{
// Is stub the right thing to use?
ResourceService serv = MockRepository.GenerateStub<ResourceService>();
// Do some setup... Don't know how?
var vm = new ViewModel(serv);
Assert.IsTrue(vm.Users.Count > 0);
}
I be really happy if someone could help me with the correct usage of RhinoMock
(Note: I'm using Silverlight, but I don't think that would change the way RhinoMock is used)
Thanks a lot!
I wrote a 4-part article all about testing apps that use WCF services.
Part 2 talks about mocking out the service using RhinoMocks
Part 3 talks about mocking out an asynchronous service using Moq
Note that part 3 can be translated over to RhinoMocks very easily. I was just trying to show different mocking frameworks, and that the technique did not rely on the mocking framework.
Hope it helps!
EDIT
So, in Rhino Mocks, you do this in the setup:
mockService.YourEvent += null;
IEventRaiser loadRaiser = LastCall.IgnoreArguments().GetEventRaiser();
Then in the playback, you do this:
loadRaiser.Raise(mockService, CreateEventArgs());
You can find more info on mocking events in Rhino in Phil Haack's blog post.
I would create interface that service would implement (IResourceService).
Then on Silverlight side create custom implementation of IResourceService that calls WCF service itself.
RihnoMock would create the stub for IResourceService interface and not for WCF service.
It's very easy to do using Prism 2, you can read more here:
http://mokosh.co.uk/post/2009/04/19/prism-2-wpf-and-silverlight-services/