During the execution, there were no unwanted consequences whatsoever.
I disagree. The resulting code is dangerous. ASP.NET pre-Core was able to detect similar situations and throw an exception ("An asynchronous module or handler completed while an asynchronous operation was still pending"). For technical reasons, ASP.NET Core cannot detect this situation so you don't get that "safety net" exception, but the situation itself is still just as bad.
The thing is, Visual Studio generates no warning message either when such thing happens
You don't get CS4014 ("Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the await operator to the result of the call.")?
is there actually any danger present of lefting out the await in such cases? I know that await should be applied on every async method naturally, but I don't really understand the reasons behind this when caller practically has no return value to use. Perhaps something with catching exceptions?
Yes, there are dangers. Task
(even without a result type) is used for two things: for the caller to know when the operation completes, and for the caller to detect exceptions from that operation.
So, the one issue is that exceptions are silently swallowed. More specifically, exceptions from the async
method are captured by the async
state machine and placed on the returned Task
, which is then ignored.
if I handle the exceptions in the said methods themselves (the ones not properly awaited), could we then say that all is fine and well?
No, because the other issue still exists: the caller doesn't know when the asynchronous operation completes. This is particularly important to know in ASP.NET, because the result should not be sent until the operation is complete. Any kind of "fire and forget" code on ASP.NET lives outside the request/response lifetime; i.e., it's request-extrinsic code.
I go into some detail on my blog about why request-extrinsic code is dangerous. In summary, your ASP.NET handler may complete too soon, and in that case, the request-extrinsic code may get "lost". At the very least, whatever it's doing won't be done by the time the response is sent; and in the case of a regular shutdown (e.g., rolling upgrades), it might not get done at all.