Stuck with Async Task and Await - c#

I don't know whats wrong with this code, but still it doesn't respond the needed value.
Here is my sample code:
WebAPI 2:
KOTController.cs
[HttpGet]
[Route("testasync")]
public IHttpActionResult TestAsync()
{
try
{
return Ok(_iKOTManager.TestAsync());
}
catch (Exception ex)
{
logger.Error(ex);
return null;
}
}
Interface
IKOTManager.cs
Task<int> TestAsync();
KOTManager.cs
public async Task<int> TestAsync()
{
return await Task.Run<int>(() =>
{
return 999 + 23;
});
}
When I send a request to this API, it returns something like this not the number
<TaskOfint xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/System.Threading.Tasks"/>
Any advice would be really helpful. Thank you.

You get that response because you are return the Task and not actually executing it. The framework is just serializing the task object and returning that.
Refactor the action to return Task and then await the method on interface
[HttpGet]
[Route("testasync")]
public async Task<IHttpActionResult> TestAsync() {
try {
return Ok(await _iKOTManager.TestAsync());
} catch (Exception ex) {
logger.Error(ex);
return InternalServerError();
}
}
Reference: Async/Await - Best Practices in Asynchronous Programming
Additionally, in the case of the exception you should return an appropriate result instead of null. This should eventually be refactored out as handling errors within the controller is considered a cross-cutting concern. Controllers should as lean as possible.
[HttpGet]
[Route("testasync")]
public async Task<IHttpActionResult> TestAsync() {
return Ok(await _iKOTManager.TestAsync());
}

You need to change your controller to be async and then await the task. i.e.
public async Task<IHttpActionResult> TestAsync()
...
return Ok(await _iKOTManager.TestAsync());
See the documentation for async/await here.

Your action method is consuming/calling async method, you need to make your action method as well async to return Task<T> as return type like:
[HttpGet]
[Route("testasync")]
public async Task<IHttpActionResult> TestAsync()
{
try
{
return Ok( await _iKOTManager.TestAsync());
}
catch (Exception ex)
{
logger.Error(ex);
return null;
}
}
If we are calling an async method, if possible we should make the calling side method as well async and return Task<T> in all call chains.
Hope it helps!

Related

How do I overload function to accept both async and synchronized version of callback parameter

public static T SyncVer<T>(Func<T> callback)
{
using (new LogContext("new logging context"))
{
try
{
return callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
public static async Task<T> AsyncVer<T>(Func<Task<T>> callback)
{
using (new LogContext("new logging context"))
{
try
{
return await callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
Please consider the code above. You may see most of the code in both functions is the same. I am searching for a way to group them up by overloading them into one so that I don't need to duplicate the content.
Is there a way to take out the similar part of both functions?
Any help provided will be appreciated. Thanks in advance.
Note that Task.FromResult will allocate, and GetAwaiter().GetResult() may dead lock
Personally I would just create two methods and not worry about it.
However, another (and slightly safer) approach is to wrap your callbacks in a ValueTask. ValueTasks work best if they execute synchronously, however they have a few subtle limitations and should never be awaited more than once.
The assumption is, this is all about creation an awaitable and non awaitable delegate overload, code reuse, and awaiting the sync version of this call is not a problem for you.
Given
public static async ValueTask<T> SomethingAsync<T>(Func<T> callback)
=> await SomethingAsync(() => new ValueTask<T>(callback()));
public static async ValueTask<T> SomethingAsync<T>(Func<Task<T>> callback)
=> await SomethingAsync(() => new ValueTask<T>(callback()));
public static async ValueTask<T> SomethingAsync<T>(Func<ValueTask<T>> callback)
{
using (new LogContext("new logging context"))
{
try
{
return await callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
Usage
public static string DoSomething()
{
Console.WriteLine("execute sync");
return "sync result";
}
public static async Task<string> DoSomethingAsync()
{
Console.WriteLine("Execute async");
await Task.Delay(100);
return "async result";
}
...
Console.WriteLine(await SomethingAsync(DoSomething));
Console.WriteLine(await SomethingAsync(DoSomethingAsync));
Output
Create
execute sync
Dispose
sync result
Create
Execute async
Dispose
async result
To add some more efficiencies you can elide wrappers
Exmaple
public static ValueTask<T> SomethingAsync<T>(Func<T> callback)
{
try
{
return SomethingAsync(() => new ValueTask<T>(callback()));
}
catch (Exception e)
{
return ValueTask.FromException<T>(e);
}
}
public static ValueTask<T> SomethingAsync<T>(Func<Task<T>> callback)
{
try
{
return SomethingAsync(() => new ValueTask<T>(callback()));
}
catch (Exception e)
{
return ValueTask.FromException<T>(e);
}
}
Note : ValueTask.FromException is only available for .NET 5.0+
The benefits of this approach :
Less allocations for the sync version of this method.
There is no chance of a deadlock
It doesn't block on async method
It gives you a Value Task overload
The downsides are
You need to wrap the async task in a ValueTask, though it's only a stack allocation
You will need to create two overloads per method (in total three signatures)
Neither version will can be awaited twice.
The sync version is slightly slower as it creates a statemachine
Note : I personally have never had a need to do this, I would just create the two methods ¯\_(ツ)_/¯.
Additional resources
Don't Block on Async Code
Prefer ValueTask to Task, always; and don't await twice
I would try something like this:
public static T SyncVer<T>(Func<T> callback)
{
return AsyncVer(() => Task.FromResult(callback())).GetAwaiter().GetResult();
}

SaveChangesAsync not working inside PUT method

I am Using ODataController to insert and Update Entries to Database
I am hitting the PUT method , using .UpdateEntryAsync()
Here is my Put Method.
public async Task<IHttpActionResult> Put([FromODataUri] string key, Delta<KYCBtnDetails> patch)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
KYCBtnDetails KYCBtnDetails = await _KYCDBModel.KYCBtnDetails.FindAsync(key);
if (KYCBtnDetails == null)
{
return NotFound();
}
patch.Put(KYCBtnDetails);
KYCBtnDetails.id = key;
try
{
await _KYCDBModel.SaveChangesAsync();
}
catch (Exception e)
{
}
return Updated(KYCBtnDetails);
}
catch (Exception ex)
{
}
return null;
}
on await _KYCDBModel.SaveChangesAsync() it give me error as
"New Transaction is not allowed because there are other threads running in the session"
"An error occurred while starting a transaction on the provider connection. See the inner exception for details."
Sometimes it runs and sometimes it gives error
Please Help me on this,
Thank You.
By convention, here's how the Put controller action signature is expected to look like:
public async Task<IHttpActionResult> Put([FromODataUri] string key, [FromBody]KYCBtnDetails kycBtnDetails)
{
// ...
}
If you decide to use Patch, here is how the controller action signature is expected to look like:
public async Task<IHttpActionResult> Patch([FromODataUri] string key, [FromBody]Delta<KYCBtnDetails> patch)
{
// ...
}
Take specific note of FromBody attribute

How to return an action result of async Task<IEnumerable<SomeClass>>?

I have this code but the controller is expecting a return type of ActionResult.
Why is the controller is accepting a Task> like this return await _context.Users.ToListAsync();(the default code when a controller is generated)?
//controller
public async Task<ActionResult<IEnumerable<User>>> GetUsers()
{
return await _userService.GetAll();
}
//service method
public async Task<IEnumerable<User>> GetAll()
{
return await _db.Users.ToListAsync();
}
I believe you need something like:
public async Task<ActionResult<IEnumerable<User>>> MyController()
{
var res = await _userService.GetAll();
if (res == null)
{
return NotFound();
}
return Ok(res);
}
As a side note, I recommend changing IEnumerable<> to IList<>. It's not strictly correct to return a enumerable here and you can also run into "multiple enumeration" issues.

Call Async method inside Rest API method not returns at all

I need a function to be executed in the background after the request is completed.
My code is something like:
[HttpPost]
public HttpResponseMessage Post([FromBody] List<JObject> lstData)
{
return PostMethod(lstData);
}
HttpResponseMessage PostMethod(List<JObject> lstData)
{
//do somework
Method1();
return myResult;
}
void Method1()
{
Method2();
}
async void Method2()
{
//do some work
await Task.Delay(25);
Method2();
}
When this scenario run, Post doesn't return at all.
I was handling it by creating a task that executes Method2(), but I an trying to make use of the Asynchronous Programming
When using async-await it is really best to let the async-await syntax flow from top to bottom of your application. Also, do not ever return async void unless it is a front-end event handler, you want to at least return async Task. async void will cause you to have undesired side effects such as losing the current context, and current methods could end up deadlocked/blocked at those calls.
I suggest you re-write your method stack to async Task and async Task<.Type>, you will be in a much better place that way :).
Example:
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody] List<JObject> lstData)
{
return await PostMethod(lstData);
}
async Task<HttpResponseMessage> PostMethod(List<JObject> lstData)
{
//do somework
await Method1();
return myResult;
}
async Task Method1()
{
await Method2();
}
async Task Method2()
{
//do some work
await Task.Delay(25);
}
And follow this the whole method chain down.

Convert void into async return in C#

I read that returning void from a C# async call is not good. But I have the following scenario:
public async void MainFunction()
{
await DoSomething()
await DoSomethingMore()
}
public void DoSomething()
{
//some code that I want to execute (fire and forget)
}
public void DoSomethingMore()
{
//some code that I want to execute (fire and forget)
}
Since I just want that function be executed with no return at all. Should i keep it like this, or should I return Task from DoSomething()? If I change it to return Task, since my code doesn't need to return anything at all, what should I return?
If i change it to return Task, since my code need return nothing at
all, what should i return?
Your current code wouldn't compile, as you can't await on a void returning method (because it doesn't return an awaitable, which is a type which exposes a GetAwaiter method).
Any void method in the synchronous world should return a Task in the asynchronous world. This allows for anyone who wishes to asynchronously wait on the async operation, and also gets a chance to handle exceptions properly. using async void means that the exception will either be swallowed, or if set to in the configuration, will be rethrown on an arbitrary threadpool thread. Async should be propagated properly all the way.
Note that when you await both operations in MainFunctionAsync, you're not firing and forgetting, you're asynchronously waiting for each of them to complete, sequentially.
public async Task MainFunctionAsync()
{
await DoSomethingAsync();
await DoSomethingMoreAsync();
}
public Task DoSomethingAsync()
{
// Do meaningful async stuff
}
public Task DoSomethingMoreAsync()
{
// Do more meaningful async stuff
}
you can return either of these
Task.FromCompleted;
Task.FromException(ex);
so your method would be like this:
public void MainFunction()
{
await DoSomething()
await DoSomethingMore()
}
public Task DoSomething()
{
try{
//some code that I want to execute (fire and forget)
return Task.FromCompleted;
}
catch(Exception ex){
return Task.FromException(ex);
}
}
//some code that I want to execute (fire and forget)
}
public Task DoSomethingMore()
{
try{
//some code that I want to execute (fire and forget)
return Task.FromCompleted;
}
catch(Exception ex){
return Task.FromException(ex);
}
}

Categories

Resources