Previously, when I started implementing action methods within controllers, I took a standard approach that seemed to work. However, my curiosity drove me to investigate various ways, and what I discovered was a wide world of coding styles. It became clear that the way I developed my code was only one option among several. As I compared my methods to those used by other developers, I began to wonder if there were major disparities in logic, performance, or other factors.

In this post, we will delve into the complexities of MVC controller methods, investigating the influence of asynchronous design decisions and throwing light on the rationale for seemingly complex async patterns.

As you can see below.

In MVC controllers, one function gets users regularly, while another adds 'async' but not 'await.'

1. Normal action method in the controller
[HttpGet]
public IActionResult GetUsers()
{
    // Retrieve a list of all user objects synchronously.
    List<User> userList = _dbService.ReadAllUsers();
    return View(userList);
}
2) Action method contains async keyword without await keyword[HttpGet]
public async Task<IActionResult> GetUsers()
{
  //Do some work and get a list of all user-objects.
  List<User> userList = _dbService.ReadAllUsers();
  return View(userList);
}

In terms of functionality, the first and second methods will act similarly because the 'async' method does not contain the 'await' keyword. Both techniques will execute simultaneously, and the distinction is not relevant in this case. However, it's worth noting that the second function is declared as an asynchronous method (async Task<IActionResult>), although there are no asynchronous operations.

The method is declared as asynchronous (async Task<IActionResult>), but there are no actual asynchronous actions with the await keyword. The ReadAllUsers() method is called synchronously, with no asynchronous operations awaiting it.

3) The Action method contains async and await keyword
[HttpGet]
public async Task<IActionResult> GetUsers()
{
    // Do some work and get a list of all user-objects.
    List<User> userList = await _dbService.ReadAllUsersAsync();
    return View(userList);
}


When you use 'await' with an asynchronous operation, like _dbService.ReadAllUsersAsync(), the method will pause and wait for the asynchronous operation to complete. Importantly, the thread is not blocked during this waiting period, allowing other tasks or operations to proceed concurrently. However, in this specific case, where there is no additional asynchronous work to be performed while waiting for the _dbService.ReadAllLinesAsync() operation, the asynchronous version doesn't offer any noticeable advantages. Consequently, there wouldn't be a significant difference between the two methods.

Summary
All three of the approaches listed above will work the same way. Why write in such a sophisticated way? In a web application, using async and await might be useful, especially when dealing with many requests. It is regarded best practice to utilize async and await when there are true asynchronous operations to run or when they are expected to be introduced in the future.