Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async Task<IActionResult> vs Task<T>

I have a controller with one action. In this action method, I have an async method that I call and that is it. This is the code that I am using:

[HttpGet]
public Task<MyObject> Get()
{
    return _task.GetMyObject()
}

This serializes correctly into the JSON I expect from it. Now my manager insists that the signature should be changed to the following:

[HttpGet]
public async Task<IActionResult> Get()
{
    var data = await_task.GetMyObject();
    return Ok(data);
}

I'm of the belief that there is no reason for the code to await in the controller and can just return the Task because nothing afterwards depends on the result. Apart from the extra code generation (creation of state machine etc.) done for the await, are there any implications from a WebApi point of view of these approaches? To clarify, I want to know if returning an IActionResult is better than to just return Task<MyObject> even tho it seems like the results are the same.

like image 780
JohanP Avatar asked Jan 24 '18 04:01

JohanP


3 Answers

Task< T>

Pro

Unit tests do not require any casting,

 Product product = await controller.Get();

Big advantage is, your unit tests become truly independent of underlying HTTP Stack.

Swagger does not need any extra attribute to generate response schema as swagger can easily detect result type.

Another big advantage is, you can reuse your controller in some other controller when the logic remains same.

Also avoiding await before return gives slight improvement in performance as that part of code does not need Task state machine. I think future C# version will omit single await as compiler optimization.

Con

Returning error status code requires throwing exception..

    throw new HttpStatusException(404, "File not found");
    throw new HttpStatusException(409, "Unauthorized");

Task< IAsyncResult>

Pro

You can return HTTP Status code such as

 return NotFound(); // (Status Code = 404)
 return Unauthorized(); // (Status Code = 409)

Con

Unit testing requires extra casting..

 Product productResult = ((await controller.Get()) as OkResult).Result as Product;

Due to such casting, it becomes difficult to reuse your controllers in some other controller, leading to duplication of logic.

Swagger generator requires extra attribute to generate response schema

 [ProducesResponseType(typeof(Product), 200)]

This approach is only recommended when you are dealing with logic that is not part of unit tests, and not part of your business logic such as OAuth integration with third party services where you want to focus more on IActionResult based results such as Challenge, Redirect etc.

like image 198
Akash Kava Avatar answered Sep 20 '22 18:09

Akash Kava


Actions can return anything, mostly they return an instance of IActionResult (or Task<IActionResult> for async methods) that produces a response. The action method is responsible for choosing what kind of response it return and the action result does the responding.

If an action returns an IActionResult implementor and the controller inherits from Controller, developers have many helper methods corresponding to many of the choices. Results from actions that return objects that are not IActionResult types will be serialized using the appropriate IOutputFormatter implementation.

For non-trivial actions with multiple return types or options (for example, different HTTP status codes based on the result of operations performed), prefer IActionResult as the return type.

like image 42
Feiyu Zhou Avatar answered Sep 18 '22 18:09

Feiyu Zhou


ASP.NET MVC is a conventions over configuration framework. This means any future maintainer of your code, including your future self, will expect code to be written a certain way in order to reduce the number of class files you have to inspect to make changes or additions.

While the result may be the same from your two technically different options, the conventional approach is to async/await your results. Anything other than that convention will potentially cause confusion for future maintainers. Additionally, future releases of MVC may break your code in unknown ways as you did not follow the convention.

Good leadership of software development teams includes instilling a desire to reduce overall manpower needs for the organization by simplifying potential future maintenance of the code. Your manager may be trying to promote this concept.

like image 33
Jim Yarbro Avatar answered Sep 21 '22 18:09

Jim Yarbro