Configuring Errors and Warnings in C#

Configuring Errors and Warnings in C#

I recently stumbled upon some code that was making an awaitable method call but was not being awaited. I noticed the issue because it was a compiler warning CS4014 and was highlighted in code. I immediately fixed the issue, however, my second action was configuring errors and warnings in C#.

YouTube

Make sure to check out my YouTube channel where I often post related content that accompanies my blog posts.

WarningAsError

You can have a .NET build fail by having the compitler producing errors for normally what are considered warnings. Such as as 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.

The code in question looked something similar to this as I seen within Rider

There are very few cases where I would not want to await. Because of that, I wanted this to cause a compiler error so going forward it was impossible to do this by accident and not notice.

The fix is really simple, in your SDK style csproj file, specify an element called WarningAsError inside a PropertyGroup. The value is a comma-separated list of warning numbers to treat as errors.

Now when you look or build it produces an error instead of a warning.

The great thing about Roslyn analyzers is they are also helpful in finding possible code issues. One of my favorites is the Microsoft.VisualStudio.Threading.Analyzers that is available as a NuGet package. Simply add it to your project and you’ll immediately get over a dozen analyzer rules applied to your codebase. The package is best for detecting Sync over Async which I’ve written about before.

One of them is VSTHRD103 that finds any code that synchronously blocks. using Wait() on Task is a good example.

We can also turn this into an error by adding VSTHRD103 in our WarningAsErrors list.

NoWarn

However, when you start adding some Roslyn analyzers you may not like some of the warnings they provide. One for me, which is highly debated, is the use of the Async suffix. Since our entire codebase is Async, we do not follow this convention. This is rule VSTHRD200 which I did not want to be warned about. This is also pretty simple by adding a NoWarn element.

Directory.Build.props

The last tip is instead of specifying all of these in each project file (csproj) definition, you can create a file called Directory.Build.props and place it at the root of where your solution is located. This file will then apply to every project.

Configuring Errors and Warnings in C#

Do you have any preferred Roslyn analyzers or warnings you like to treat as errors? Let me know in the comments or on Twitter.

Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Roundup #72: Succinct C#, IHostedService Shutdown Timeout, try-convert, Coupling, Cohesion, and Microservices

Writing More Succinct C#

When looking at a lot of C# code nowadays, I find myself thinking “wow, that code could be made SO MUCH SMALLER!”. C# is a very flexible language, allowing you to write clean and functional code, but also very bloated code.

Link: https://www.danclarke.com/2020-more-succinct-csharp

Extending the shutdown timeout setting to ensure graceful IHostedService shutdown

I was seeing an issue recently where our application wasn’t running the StopAsync method in our IHostedService implementations when the app was shutting down. It turns out that this was due to some services taking too long to respond to the shutdown signal. In this post I show an example of the problem, discuss why it happens, and how to avoid it.

Link: https://andrewlock.net/extending-the-shutdown-timeout-setting-to-ensure-graceful-ihostedservice-shutdown/

try-convert

This is a simple tool that will help in migrating .NET Framework projects to .NET Core.

This tool is for anyone looking to get a little help migrating their projects to .NET Core (or .NET SDK-style projects).

As the name suggests, this tool is not guaranteed to fully convert a project into a 100% working state. The tool is conservative and does as good of a job as it can to ensure that a converted project can still be loaded into Visual Studio and build. However, there are an enormous amount of factors that can result in a project that may not load or build that this tool explicitly does not cover. These include:

Complex, custom builds that you may have in your solution

API usage that is incompatible with .NET Core

Unsupported project types (such as Xamarin, WebForms, or WCF projects)

If the bulk of your codebase is generally capable of moving to .NET Core (such as lots of class libraries with no platform-specific code), then this tool should help quite a bit.

Link: https://github.com/dotnet/try-convert

Build Stuff #6 e-Meetup – Sam Newman – Coupling, Cohesion, and Microservices

The terms coupling and cohesion come from the world of structured programming, but they are also thrown about in the context of microservices. In this session, I look at the applicability of these terms to a microservice architecture and also do a deep dive into the different types of coupling to explore how ideas from the 1970s still have a lot of relevance to the types of systems we build today.

Link: https://www.youtube.com/watch?v=s_bAC_X57MA

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Why use DTOs (Data Transfer Objects)?

Data Transfer Objects

Should you really use DTOs (Data Transfer Objects)? Seem like a lot of work mapping your database entities to another object? Why Bother? The simple answer is coupling.

Data Transfer Objects

First, what are DTOs? When people refer to Data Transfer Objects, what they mean are objects that represent data structures that generally do not contain any business logic or behavior. If they do contain behavior, it’s generally trivial.

Data Transfer Objects are often used to be serialized by the producer and then deserialized by the consumer. Often times these consumers may live in another process being used by an entirely different language and/or platform.

YouTube

I’ve recorded a short video explaining this with some sample code. Check out the video and make sure to subscribe to my YouTube Channel.

Crossing Boundaries

The most common example of this is creating an HTTP API using ASP.NET Core that returns an object from its Controller actions that are ultimately serialized to JSON. The consumer is oftentimes JavaScript that uses those JSON responses in displaying the browser using a Component or SPA Framework.

Internals

If you’re not using DTOs, then you’re likely exposing internal data structures.

The biggest culprit of this is simple TODO demo applications that expose the database entities directly. Meaning they output a serialized list of TODOs to the javascript frontend. And when you want to create a new record, they often times take the TODO object to insert directly into the database. This is leaking internals.

This is my biggest complaint with simple demo applications are they often don’t implement or follow some practices, because rightly so, they aren’t applicable to a simple TODO application. However, people take the example of a simple TODO and use the same patterns into a much large application.

The problem is when internal data objects are serialized and consumed by a client you either down own or cannot change easily. Or, which happens more often, the application itself gets very large.

Contracts

The moment you want change internal data objects, you now have to update the clients.

Take this simple example of a Customer that is an internal data structure we use through the system and likely use to persist using an ORM.

If we are serializing this structure and clients are consuming this, if we change this structure, we’re likely going to break out clients.

This change would require a change to all of our clients. We could easily make this change in our own codebase and have all our own usages be correct, but we would be breaking all of our decoupled clients that get a serialized representation.

Representation

When creating an HTTP API, it’s all about representations. Most often times clients need a rich representation of a resource, not a just serialized version of a database entity. They often times need related data.

Having your API return rich representations means you must do some level of composition to create an object, not just a database entity, that will get serialized. This is where a DTO comes into play.

I actually don’t often use the term DTO, but rather use the word Representation or ViewModel. The purpose is still the same, it’s a data structure that is a contract between the producer and the consumer. That contract should remain stable (through backwards compatibility) or have a versioning strategy.

Coupling

The reason you want to use DTOs is that you want clients to couple to that contract, not to your internal data structures. This allows you to modify and evolve your internals freely without breaking clients.

Links

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.