Want to build a .NET Application? Check SSW's Web Application / API consulting page.
.NET Core works on multiple platforms like MacOS, Linux and Windows. So developers can code on their operating system of choice using Visual Studio, Visual Studio for Mac or Visual Studio Code, working on the same code base as developers on a different operating system, and best of all they can also deploy to Linux.
.NET Core is fast, and you get that performance out of the box.
Long Term Support (LTS) versions of .NET Core / .NET 6+ are officially supported by Microsoft for 3 years following release. So when considering which version to target for your application, the “Latest LTS when we first deploy to Production” is often the safest choice. Non-LTS versions have much shorter support lifetimes.
Developers understand the importance of the F5 experience. Sadly, lots of projects are missing key details that are needed to make setup easy.
Let's look at the ways to optimize the experience. There are 4 levels of experience that can be delivered to new developers on a project:
When developing software, we implement a dependency injection centric architecture.
The traditional .sln format has served developers well for years, but it comes with significant limitations that impact productivity and collaboration, especially as projects grow larger and teams expand. The modern SLNX format solves these problems with a clean XML-based structure.
All the DLL references and files needed to create a setup.exe should be included in your solution. However, just including them as solution items is not enough, they will look very disordered (especially when you have a lot of solution items). And from the screenshot below, you might be wondering what the _Instructions.docx is used for...
Without a global.json, the dotnet CLI silently uses the latest SDK installed on the machine. That means a teammate who just installed a newer SDK (or a CI image that updated overnight) can build your repo with a different compiler, different analyzers, and different language version than everyone else - and you find out via a broken build or, worse, subtly different output.
A one-file fix makes the SDK version part of the repository.
When working on large enterprise scale projects .NET Solutions can often become unwieldy and difficult to maintain. This is particularly true of .csproj files which end up repeating configuration across all projects. How can one file save you hours of maintenance by keeping project configuration DRY?
In a solution with many projects, NuGet package versions end up scattered across every .csproj file. Sooner or later 2 projects reference different versions of the same package, and you start seeing version drift, NU1605 package downgrade errors, and runtime binding failures. Upgrading a package means hunting through dozens of files and hoping you didn't miss one.
Central Package Management (CPM) fixes this by declaring every package version once, in a single Directory.Packages.props file.
If your repository has no nuget.config, package restore depends on whatever sources happen to be configured on each machine - a recipe for "restores fine for me" surprises. It gets worse when you add a private feed: if an internal package name also exists on nuget.org, NuGet may happily pull the public one. Attackers exploit exactly this with dependency confusion attacks - publishing malicious packages under names they guess companies use internally.
The fix is to make package sources part of the repository, not the machine.
JavaScript developers commit package-lock.json without thinking about it - yet most .NET teams run dotnet restore with no lock file at all. That means the exact packages your build uses can change between restores without any code change: floating versions (8.*) resolve to something new, or a transitive dependency publishes a new version that shifts your whole graph. The build that passed yesterday and the one deployed today may not be running the same bytes.
NuGet has lock files too - they're just off by default.
Some build failures are easy - the error tells you exactly what to fix. Then there are the others: a property that mysteriously has the wrong value, a stale DLL being copied from who-knows-where, a build that works locally but fails in CI, or a multi-targeted project that behaves differently per framework. Staring at console output (or a 200 MB diagnostic text log) is a slow way to solve these.
MSBuild binary logs (binlogs) capture everything the build did - every project, property, item, task, and environment variable - in a compact, searchable file.
Most systems will have variables that need to be stored securely; OpenId shared secret keys, connection strings, and API tokens to name a few.
These secrets must not be stored in source control. It is insecure and means they are sitting out in the open, wherever code has been downloaded, for anyone to see.
You may be asking what's a secret for a development environment? A developer secret is any value that would be considered sensitive.
Most systems will have variables that need to be stored securely; OpenId shared secret keys, connection strings, and API tokens to name a few. These secrets must not be stored in source control. It's not secure and means they are sitting out in the open, wherever code has been downloaded, for anyone to see.
There are different ways to store your secrets securely. When you use .NET User Secrets, you can store your secrets in a JSON file on your local machine. This is great for development, but how do you share those secrets securely with other developers in your organization?
With .NET Core, we've got a new, extensible configuration system for our projects. This is easily extended and has out-of-the-box support for many configuration sources including JSON files, per-environment overrides, command-line parameters, and environment variables.
A common source of pain when working in a team is when different team members require different connection strings in order to run the project locally. If the developer modifies settings and then accidentally pushes that change into source control, the app might break for other developers.
Starting a new .NET project often means chasing down local.settings.json files, environment variables, and secrets shared via chat or password managers. These files quickly drift out of date, are hard to rotate, and create friction for new developers who just want to press F5 and be productive.
There are 2 types of connection strings. The first contains only address type information without authorization secrets. These can use all of the simpler methods of storing configuration as none of this data is secret.
Developers love the feeling of getting a new project going for the first time. Unfortunately, the process of making things work is often a painful experience. Every developer has a different setup on their PC so it is common for a project to require slightly different steps.
The old proverb is "Works on my machine!"
Luckily, there is a way to make all development environments 100% consistent.
Often, developers jump onto a new project only to realize they can't get the SQL Server instance running, or the SQL Server setup doesn't work with their machine.
Even if they are able to install SQL Server, developers have a better option with a smaller footprint on their dev machine. Containers give them the ability to work on multiple projects with different clients. In a word "Isolation" baby!
Using Docker to run SQL Server in a container resolves common problems and provides numerous benefits:
It's common for .NET solutions to have multiple projects, for example an API and a UI. Did you know Microsoft Visual Studio and Jetbrains Rider allow you to start as many projects as you want with a single click?