6

ServiceStack version 3

I'm quite familiar with https://github.com/ServiceStack/ServiceStack/wiki/New-API and on this page it specifically says "All these APIs have async equivalents which you can use instead, when you need to."

Is it possible to use async await with ServiceStack's new api?

What would the server and client code look like with async await?

[Route("/reqstars")]
public class AllReqstars : IReturn<List<Reqstar>> { }

public class ReqstarsService : Service
{
    public List<Reqstar> Any(AllReqstars request) 
    {
        return Db.Select<Reqstar>();
    }
}

Client

var client = new JsonServiceClient(BaseUri);
List<Reqstar> response = client.Get(new AllReqstars());

Would some please convert these synchronous examples to asynchronous?

Chris Marisic
  • 32,487
  • 24
  • 164
  • 258

2 Answers2

11

The "async" methods mentioned in the documentation do not return Task so they can't be used with async/await as they are. They actually require callbacks to call on success or failure.

E.g. the signature for GetAsync is :

public virtual void GetAsync<TResponse>(string relativeOrAbsoluteUrl, 
    Action<TResponse> onSuccess, 
    Action<TResponse, Exception> onError)

This is the APM-style of asynchronous functions and can be converted to Task-based functions using a TaskCompletionSource, eg:

    public static Task<TResponse> GetTask<TResponse>(this JsonServiceClient client, string url)
    {
        var tcs = new TaskCompletionSource<TResponse>();

        client.GetAsync<TResponse>(url,
            response=>tcs.SetResult(response),
            (response,exc)=>tcs.SetException(exc)
            );

        return tcs.Task;
    }

You can call the extension method like this:

var result = await client.GetTask<SomeClass>("someurl");

Unfortunatelly, I had to name the method GetTask for obvious reasons, even though the convention is to append Async to methods that return Task.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
  • Actually, couldn't you have named the method GetAsync? The signatures would be different and it should resolve fine. But thank you for making this clear, it wasn't entirely clear to me in those docs. I'll try to get around to updating them with information from this answer! – Chris Marisic Oct 08 '13 at 16:52
  • 1
    APM is a very specific pattern (with `Begin` and `End` methods, `IAsyncResult`, etc.) and the `GetAsync()` method doesn't fit it. It's similar (callback-based), but not the same. – svick Oct 08 '13 at 17:44
  • @svick meh, if I use the extension method I will be using GetAsync(). I guess if you wanted some clear denotation it's different, albeit slightly, GetAsynchronous() / GetAwaitable() would fit. – Chris Marisic Oct 09 '13 at 13:18
8

With ServiceStack 4, GetAsync now returns a Task, so can can simply use await as expected:

var client = new JsonServiceClient(BaseUri);
var response = await client.GetAsync(new AllReqstars());

Documentation here: https://github.com/ServiceStack/ServiceStack/wiki/C%23-client#using-the-new-api

Note: From what I can tell ServiceStack v4 has many breaking changes from v3.x, and has moved away from BSD licensing with usage limits for their free tier: https://servicestack.net/pricing, so upgrading to 4 may not be an option.

Chris Curtis
  • 1,478
  • 1
  • 10
  • 21
  • FWIW i specifically clarified this question is only about ServiceStack3, i don't see anything wrong with leaving this answer here for completeness. – Chris Marisic Jan 17 '14 at 14:41
  • 1
    Yea wasn't sure if it would be helpful to you or not, as you didn't specify a version originally. But was more thinking it might be helpful to other viewers of this question anyway. Thanks for updating – Chris Curtis Jan 17 '14 at 19:03