Security
I've gone to the most obvious and complicated issue first, because I personally find it to be the most interesting. Writing software in a professional context will, across the board, require you to code your applications to be secure. Even if your job doesn't explicitly require it, I would argue until I'm blue in the face that, as an engineer, you have an ethical obligation to write secure software regardless. That can be a daunting task. Especially since having secured software is always a moving target. It's important that you keep this in mind, though, because making your software useful as a resource to a wide variety of benevolent consumers inherently opens you up to malicious intent.
This is where device-agnosticism and open communication become hugely important. Device-agnosticism means you can't reasonably be sure that a malicious actor hasn't gained access to a network that you may have assumed was secured upstream from your hosting environment. You will only ever see and process requests on the access points to your software. And open communication means you may end up getting a number of requests that are malformed that you'll attempt to parse initially, before determining that you can't, and disposing of them. This need to first read the messages you're given, in order to know, if they're something you care about, as that ultimately exposes you to malicious commands or code.
Thankfully, as we'll explore later, the .NET Core libraries provide a wide array of strong security components right out of the box, and the leg-work of getting and leveraging the encryption libraries and request sanitizing algorithms is just a matter of knowing what using statements to include at the top of your source files.