Reputation: 14417
So I have this method in my base controller:
protected async Task<KeyValuePair<bool, string>> ExecuteSimpleQuery(Func<Task<bool>> service)
{
var success = false;
var message = string.Empty;
try
{
success = await service.Invoke();
}
catch (Exception exception)
{
message = exception.Message;
success = false;
}
return new KeyValuePair<bool, string>(success, message);
}
I want to use it like this:
public async Task<ActionResult> Login(RegisterDto register)
{
var objectStore =
await this.ExecuteSimpleQuery(async () => await this.securityService.LoginAsync(register.UserName, register.Password, true));
if (objectStore.Key)
{
return this.RedirectToAction("Index", "Toolbox");
}
this.TempData["error"] = objectStore.Value;
return this.View(register);
}
So what I'm passing through to ExecuteSimpleQuery
is an awaitable
method LoginAsync
, I just want to make sure I'm properly awaiting the method.
My thought process is:
LoginAsync
returns a Task<bool>
therefore the Func
has to return that.await
it, so do.Func
returns a Task<bool>
inside ExecuteSimpleQuery
you can await
it there, so shouldExecuteSimpleQuery
is awaiting a method, therefore has to have the async
keyword and therefore has to return Task<T>
.Login
action, that method returns Task<T>
so it can be awaited, so should.Am I even close?
Upvotes: 2
Views: 1056
Reputation: 171206
This will work. It can be simplified a little bit:
async () => await this.securityService.LoginAsync(register.UserName, register.Password, true)
could be written as
() => this.securityService.LoginAsync(register.UserName, register.Password, true)
because LoginAsync already returns a Task
. That said always awaiting tasks whenever you process them has a certain consistency to it. It isn't really harmful to wrap this task the way you did. I think both ways are reasonable.
If LoginAsync
can not throw any exception (that you care about) you don't need the lambda at all. Exceptions are usually stored in the Task
when you call an async method. You could directly pass a Task
to ExecuteSimpleQuery
. If LoginAsync
does not adhere to this pattern you cannot do this because the exception would be triggered too early.
var loginTask = securityService.LoginAsync(register.UserName, register.Password, true);
var objectStore = await ExecuteSimpleQuery(loginTask);
protected async Task<KeyValuePair<bool, string>> ExecuteSimpleQuery(Task<bool> service)
{
//...
try
{
success = await service;
}
catch (Exception exception)
{
//...
}
//...
}
You can test this by saying:
var loginTask = Task.Run(() => { throw null; });
The catch
will be hit.
Upvotes: 3