Correct way to write async / await services in ServiceStack - c#

I m trying to write an async service with ServiceStack and to me it seems that this feature is not really complete.
My questions:
1) How do you pass CancellationTokens in the service methods?
2) What about ConfigureAwait(false) in those methods? For example
public Task<SomeResponse> Get(SomeRequest request)
{
return _manager.ExecuteAsync(request).ConfigureAwait(false);
}
This doesnt compile.
3) Should we be marking such services with the async keyword and return Task to make them awaitable? For example this doesnt work (usage is silly but you get the point)
public async Task<SomeResponse> Get(SomeRequest request)
{
return await _manager.ExecuteAsync(request).ConfigureAwait(false);
}
Should we even be writing async services with ServiceStack? Is there a benefit or the current implementation defeats the purpose?
Thanks

If the methods don't accept cancellation tokens, then they weren't designed to be cancellable, and you can't cancel them.
You're not actually awaiting the task, so there's no await to configure. Just omit the ConfigureAwait since you have no await to configure.
There's no need to mark a method as async if you're not actually going to leverage any of the features of it or accomplish anything with it that isn't already done by just not doing that. It's not breaking anything other than making the code a tiny bit slower, but it's not adding anything either.

You can make an async request as normal using C# async/await, i.e:
var response = await client.GetAsync(requestDto);
Or if you prefer (or cannot use await), you can use Continuations on the returned Task<T>, e.g:
client.GetAsync(new Hello { Name = "World!" })
.Success(r => r => r.Result.Print())
.Error(ex => { throw ex; });
You can cancel an async request with:
client.CancelAsync();
This calls HttpWebRequest.Abort() behind the scenes.

Related

Nested async & await in Web API application

I want to build asynchronous Web API using .NET Core
If I have async Task that's awaiting for a result from the service as below
[HttpGet("User/")]
public async Task<IActionResult> GetUser()
{
var result = await _service.GetUser();
return Ok(result);
}
Now in _service.GetUser we do more than one task such as querying the database more than once.
So my question is do we have to use async & await as well in _service.GetUser, or is it enough that the caller method do? I'm kind of confused.
public async Task<UserResponseDTO> GetUser(UserRequestDTO userRequestDTO)
{
var userId = await _utilities.getUserId(); //shall we use it?
var user = await _dbContext.getFullUserInfo //shall we use it?
.Where(P => P.userId == userId).FirstOrDefault();
if (!string.IsNullOrEmpty(userRequestDTO.email))
{
var emailExists = await _dbContext.getFullUserInfo.Where(p =>
p.Email == userRequestDTO.email).AnyAsync(); //shall we use it?
}
await _dbContext.SaveChangesAsync();
return _mapper.Map<UserResponseDTO>(user);
}
I want to build asynchronous Web API Using .NET Core
Why?
There are a number of incorrect answers to that question; the most common one is probably "to make it faster". "To make it more scalable" I would say is only semi-correct.
The correct answer is "I have asynchronous work do to", where "asynchronous" in this context is roughly the same as "I/O-bound".
In your example code, you want an asynchronous Web API call because that call queries/updates the database.
So my question is do we have to use async & await as well in _service.GetUser or is it enough that the caller method do?
Once you have the correct reasoning around "why", the solution is clearer. Specifically, you want to have asynchronous database methods first, and then make your API method asynchronous if it calls them.
Generally, it's best to start at the lowest-level calls and make those use await. FirstOrDefaultAsync, AnyAsync, SaveChangesAsync, etc. Anything doing I/O can be changed to use await. Once GetUser is an asynchronous method (and should be called GetUserAsync), then make your GetUser action method use async/await.

Using HttpClient in the synchronous class library

I am writing a class library wrapper for a 3rd party API, using .Net Standard and later on I'm planning to use this wrapper in my other project. While looking around the web, I've found out that general concern is that one should use HttpClient class for making HTTP requests.
I am aware of two approaches that I could take:
Using async/await all the way down to the client project
Using Task.Wait() method
So far I am going for the 1st approach. But both approaches seem rather problematic. First one would be less reusable than having synchronous methods, which return their type and not a Task object. I'd rather take the second approach, but it's prone to deadlocks.
My code for making a single request (HttpClient initialized with parameterless constructor):
protected async Task<JObject> Request(string url)
{
Uri uri = BuildUrl(url);
HttpResponseMessage response = await HttpClient.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
return JObject.Parse(result);
}
return new JObject();
}
For multiple requests:
protected async Task<JObject[]> Request(IEnumerable<string> urls)
{
var requests = urls.Select(Request);
return await Task.WhenAll(requests);
}
And usage in the wrapper class:
protected async Task<JObject> RequestGet(string id, bool byUrl)
{
if (IsBulk && !byUrl)
return await Request($"{Url}?id={id}");
if (byUrl)
return await Request(Url + id);
return await Request(Url);
}
How could I modify the code (1st and 2nd snippet) so that it wouldn't cause any deadlocks and async usage in every caller method (3rd snippet)?
Using HttpClient synchronously is unsupported and deadlock prone, and there's nothing you can do (including using Task.Wait) to change that fact. You have 2 options:
Support async only.
Use the older WebRequest APIs instead and support synchronous calls that way.
I would opt for option 1. There's a reason that the latest and greatest HTTP libraries don't even support synchronous I/O anymore. The newer wave of multi-core processors and distributed architectures have triggered a paradigm shift in the programming world, where tying up threads while waiting on I/O (especially longer-running network calls like HTTP) is a total waste of resources. And when languages like C# provide incredible support for async programming out of the box, there's virtually no good reason to do synchronous HTTP anymore. Most developers understand this I don't think you should be concerned about abandoning users by going async only. Instead, encourage them to get up to speed on doing it the right way.
Using async all the way down is the right way, and you can return results from a Task method (in other words -- as your own code shows -- it isn't right to say they don't return anything other than Task):
public async Task<string> GetString(int value)
{
return value.ToString();
}
Obviously that doesn't need to be async, it doesn't need to await anything, but the point is Task can return anything thanks to generics. You can even use the fancy new C# 7 value-tuples:
public async Task<(string name, int age)> GetUserInfo(int userId) { ... }

best practice for using async await in webapi

I have .NET core Web API which as service layer. Service layer has all EF code.
If have basecontroller with this code
protected Task<IActionResult> NewTask(Func<IActionResult> callback)
{
return Task.Factory.StartNew(() =>
{
try
{
return callback();
}
catch (Exception ex)
{
Logger.LogError(ex.ToString());
throw;
}
});
}
In controller action I wrap all calls to service in above method e.g. :
[HttpGet("something")]
public async Task<IActionResult> GetSomething(int somethingId)
{
return await NewTask(() =>
{
var result = _somethingService.GetSomething(somethingId);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
});
}
Is this correct pattern considering tomorrow I may have more than one service calls in action or making calls to other webservice. Please advise.
i want my api to benefit from async await thing.does above pattern will serve these needs
No, it does not. Running synchronous work on the thread pool gives you the drawbacks of synchronous and asynchronous code, with the benefits of neither.
something service has some crud operations which use entityframework core
Currently, your action method is what I call "fake asynchronous" - it looks asynchronous (e.g., using await), but in fact is just running blocking code on a background thread. On ASP.NET, you want true asynchrony, whicn means you must be async all the way. For more about why this is bad on ASP.NET, see the first half of my intro to async on ASP.NET article (it mostly deals with ASP.NET non-core, but the first part talking about synchronous vs asynchronous requests is valid for any kind of server).
To make this truly asynchronous, you should start at the lowest level - in this case, your EFCore calls. They all support asynchrony. So, replace API calls like x.FirstOrDefault() with await x.FirstOrDefaultAsync() (and the same for all your creates/updates/deletes, etc).
Then allow async/await to grow naturally from there; the compiler will guide you. You'll end up with asynchronous methods on your somethingService which can be consumed as such:
[HttpGet("something")]
public async Task<IActionResult> GetSomething(int somethingId)
{
var result = await _somethingService.GetSomethingAsync(somethingId);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
}
Okay, first of all, you should stop using Task.Factory.StartNew and use Task.Run only when you have heavy CPU-bound work that you want to run on a thread pool thread. In you case you don't really need that at all. Also you should remember that you should only use Task.Run when calling a method and not in the implementation of the method. You can read more about that here.
What you really want in your case is to have asynchronous work inside your service (I'm not really sure you even need a service in your case) when you are actually making a call to the database and you want to use async/await and not just run some stuff on a background thread.
Basically your service should look something like this (if you are sure you need a service):
class PeopleService
{
public async Task<Person> GetPersonByIdAsync(int id)
{
Person randomPerson = await DataContext.People.FirstOrDefaultAsync(x => x.Id == id);
return randomPerson;
}
}
As you can see your service now makes async calls to the database and that's basically what your pattern should be. You can apply this to all your operations(add/delete/ etc..)
After making your service asynchronous you should be easily able to consume the data in the action.
Your actions should look something like this:
[HttpGet("something")]
public async Task<IActionResult> GetPerson(int id)
{
var result = await PeopleService.GetPersonByIdAsync(id);
if (result != null)
return Ok(result);
else
return NotFound("Role not found");
}

Should a repository return Task<SomeEntity>?

I'm designing a repository, but I have this doubt.
Should I design it to be blocking operations or async?
I tend to think that blocking is more elegant, since users can wrap calls to be async when needed with something like
Task.Run( () => repository.Get(...));
What do you think?
Since underlying data source is naturally asynchronous in most cases (web service, database, file), async API is a preferred way.
blocking is more elegant, since users can wrap calls to be async when needed
Actually, vice versa.
User (not you!) can wrap async call into synchronous one, if needed:
Task<MyObj> DoSomethingAsync() { ... }
MyObj DoSomething()
{
return DoSomethingAsync().Result;
}
while this:
Task.Run( () => repository.Get(...));
is called "async over sync" and must be avoided:
should we expose an asynchronous entry point for a method that’s
actually synchronous? The stance we’ve taken in .NET 4.5 with the
Task-based Async Pattern is a staunch “no.”

Wraping sync API into Async method

My MVC application consumes a library and some methods of this library call WCF service internally. All methods exposed from this DLL are sync (none of them return Task or Task) and since we don't own that assembly, it is not possible to convert them into Async API.
However, because these methods call WCF service, they are network bound (so ideally they should be async).
I want to use async controller actions in my MVC application to make it more scalable. My question is how to make the entire method pipeline await able when one method is sync in nature.
Async action --> await async method --> await async method 2 --> sync method from library?
Should I use TaskCompletionSource or Task.FromResult to wrap the library method call?
Also, if I use above approach, will my code more scalable than sync version?
My question is how to make the entire method pipeline await able when one method is sync in nature.
You can't. The only solution is to rewrite the dll.
Should I use TaskCompletionSource or Task.FromResult to wrap the library method call?
Neither.
Also, if I use above approach, will my code more scalable than sync version?
No. It will be slightly less scalable.
TaskCompletionSource<T> is a way to create a puppet Task, which can complete at any point you like, and can make it fault at any point you like. This means, this would ideal in your case since you have no control over the API method, which you are trying to consume. Following example will give you a head start.
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
ViewBag.Message = await ProcessRequest();
return View();
}
//TResult -> can be of any built-in or custom type that you should decide.
Task<TResult> ProcessRequest()
{
// Make a TaskCompletionSource so we can return a puppet Task
TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
// Call your sync API method
SyncAPI syncApi = new SyncAPI();
// Call api method and set the result or exception based on the output from the API //method.
tcs.SetResult(TResult);
// Return the puppet Task, which isn't completed yet
return tcs.Task;
}
}

Categories