I'm generally confused about the "why" (not the "how") of using certain C# return types in Razor Pages. In some instances, I understand the "why", but am not clear on when I should use one over the other. My initial confusion began with the Asynchronous types, but I understand that now. It was also compounded by the void
type, which I have a little better grasp of, but am still not fully comprehending.
I am studying several different snippets of code to get a better grasp, and could use some helpful explanations - the Docs and other sources are not really bringing it home for me.
Some of the methods come from some DI's, and aren't necessarily relevant (I think, for all I know it's the reason for using one return type over another, in which case I appreciate an explanation). Here are some various snippets that I am hoping the community can help me come to understand better as to the "why" using one return type over the other (or whether I should just stick with one type as it won't affect the result of what is being done).
First:
public void OnGet()
{
ServicesContainer = _helper
.GetRecentContentItemsByContentTypeAsync("Services")
.GetAwaiter()
.GetResult()
.SingleOrDefault();
ServicesList = _helper
.GetRecentContentItemsByContentTypeAsync("Service")
.GetAwaiter()
.GetResult()
.OrderByDescending(c => c.CreatedUtc)
.Take(3);
}
The code itself I have no problem understanding - it's retrieving a container and list items inside. My Razor Page is just displaying the list items using a repeating foreach
loop. I also understand the code is getting this information and it's the most basic example. So for no problem in my understanding.
Second:
public async Task OnGetAsync(string projectTitle)
{
Project = _helper
.QueryContentItemsAsync(q => q
.Where(c => c.DisplayText == projectTitle))
.GetAwaiter()
.GetResult()
.SingleOrDefault();
var relatedProjects =
(IEnumerable<string>)Project?
.Content
.Project.RelatedProjects?
.ContentItemIds?.ToObject<string[]>();
if (relatedProjects?.Count() > 0)
{
RelatedProjects = await
_helper.GetContentItemsByIdAsync(relatedProjects);
}
}
The above is also retrieving a "container" that may have items (RelatedProjects), but in this case it's doing it a bit differently since there may not be anything to list other than the Project itself. But why is it using Task
instead of just OnGet
?
Third:
public async Task<IActionResult> OnGet()
{
HeaderInfo = await _helper
.GetContentItemByAliasAsync("alias:fullwidth");
return Page();
}
Here it's just a single item. But again, why use Task
and why do an <IActionResult>
to return the page when all the other code doesn't require returning a page? And why isn't it using OnGetAsync
?
There is nothing special about any of the items - they are all stored on a CMS (nothing dynamic about them, for example). The first, a container with list items. The second an item with potentially related items (if they exist in the CMS, which they don't). The third is just a single item.
And why use void
on the first but not the others?
Whenever a request is made to OnGet()
, IIS must wait for the data to be returned before it can handle other requests. By making OnGet()
asynchronous, this allows IIS to perform other tasks while it waits for your data to get returned. This reduces bottlenecks and it makes IIS perform faster and more efficient.
Whenever a method is marked as async
, it must return a Task
object. If your method has nothing to return, then it still must be marked as Task OnGetAsync()
. If your method does return a value, you can specify the return type in the Task
object, as in Task<IActionResult> OnGetAsync()
.
So for your methods, here's what's happening:
public void OnGet()
{
// Synchronous method that returns nothing
// IIS stops handling requests here until your method returns
}
public async Task OnGetAsync(string projectTitle)
{
// Asynchronous method that returns nothing.
// When your code reaches the await keyword,
// IIS resumes handling other tasks while awaiting
// for your method to return
}
public async Task<IActionResult> OnGet()
{
// Asynchronous method that returns an IActionResult value
// When your code reaches the await keyword,
// IIS resumes handling other tasks while awaiting
// for your method to return
}