Secure & Clean coding .NET Core

How to write code as secure and clean as possible!!!

Abdulmohsen Alenazi
8 min readJan 1, 2021

Is .NET 3.1 Secure?

The short answer is “yes.” The longer answer is that just like with any development framework .NET Core is as safe as the development best practices and maintenance deployed to create the code and keep it updated. But in a way, .NET Core is more safe and secure than previous frameworks. Think about it this way.

How To Build Secure and Clean Layers?

With a .NET Core or any framework, ensure that the layers are designed and that each layer is responsible for a dependent task.

That means we have isolated tasks that work with a different ability, that pattern increases security and performance as well.

In APIs, the first layer receives the requests, It’s responsible for many things. For Example ( Validate the Request, Check the Authentication and Authorization, Handle Exceptions, logging … Etc)

For Best Practices, We design the this first layer to include the Middleware.

So, what should we pay attention to?

I am going to go through the below explanation:

Startup Class and the Service Configuration

In the Startup class, there are two methods: the ConfigureServices method for registering the services and the Configure method for adding the middleware components to the application’s pipeline.

So, the best practice is to keep theConfigureServices method clean and readable as much as possible. Of course, we need to write the code inside that method to register the services, but we can do that in a more readable and maintainable way by using the Extension methods.

For example, let’s look at the wrong way to register CORS:

Even though this way will work just fine, and will register CORS without any problem, imagine the size of this method after registering dozens of services.

That’s not readable at all.

And then just to call this extended method upon the IServiceCollection type:

Project Organization

We should always try to split our application into smaller projects. That way we are getting the best project organization and separation of concerns (SoC). The business logic related to our entities, contracts, accessing the database, logging messages, or sending an email message should always be in a separate .NET Class Library project.

Every small project inside our application should contain a number of folders to organize the business logic.

Here is just one simple example of how a completed project should look like:


The controllers should always be as clean as possible. We shouldn’t place any business logic inside it.

So, our controllers should be responsible for accepting the service instances through the constructor injection and for organizing HTTP action methods (GET, POST, PUT, DELETE, PATCH):


Our actions should always be clean and simple. Their responsibilities include handling HTTP requests, validating models, catching errors, and returning responses:

Our actions should have IActionResult as a return type in most of the cases (sometimes we want to return a specific type or a JsonResult). That way we can use all the methods inside .NET Core which returns results and the status codes as well.

The most used methods are:

OK {returns the 200 status code}
NotFound {returns the 404 status code}
BadRequest {returns the 400 status code}
NoContent {returns the 204 status code}
Created, CreatedAtRoute,
CreatedAtAction {returns the 201 status code}
Unauthorized {returns the 401 status code}
Forbid {returns the 403 status code}
StatusCode returns the status code we provide as input

Using DTOs to Return Results and to Accept Inputs

Even though we can use the same model class to return results or accept parameters from the client, that is not a good practice. A much better practice is to separate entities that communicate with the database from the entities that communicate with the client. Yes, the answer is to use DTOs.

The model class is a full representation of our database table and being like that, we are using it to fetch the data from the database. But once the data is fetched we should map the data to the DTO and return that result to the client. By doing so, if for some reason we have to change the database, we would have to change only the model class but not the DTO because the client may still want to have the same result. You can read more about the DTO’s usage in the fifth part of the .NET Core series.

We shouldn’t be using DTOs only for the GET requests. We should use them for other actions as well. For example, if we have a POST or PUT action, we should use the DTOs as well. To read more about this topic, you can read the sixth part of the .NET Core series.

Additionally, DTOs will prevent circular reference problems as well in our project.


If we plan to publish our application to production, we should have a logging mechanism in place. Log messages are very helpful when figuring out how our software behaves in production.

.NET Core has its own logging implementation by using the ILoggerBuilderinterface. It is very easy to implement it by using the Dependency Injection feature:

Then in our actions, we can utilize various logging levels by using the _loggingBuider object.

.NET Core supports logging API that works with a variety of logging providers. Therefore, we may use different logging providers to implement our own logging logic inside our project.

The NLog is a great library to use for implementing our own custom logging logic. It is extensible, supports structured logging, and very easy to configure. We can log our messages in the console window, files, or even database.

The Serilog is a great library as well. It fits in with the .NET Core built-in logging system.

Using Asynchronous Code

With async programming, we avoid performance bottlenecks and enhance the responsiveness of our application.

The reason for that is that we are not sending requests to the server and blocking it while waiting for the responses anymore (as long as it takes). So, by sending a request to the server, the thread pool delegates a thread to that request. Once the thread finishes its job it returns to the thread pool freeing itself for the next request. At some point, the application fetches the data from the database and it needs to send that data to the requester. Here is where the thread pool provides another thread to handle that work. Once the work is done, a thread is going back to the thread pool.

One important thing to understand is that if we send a request to an endpoint and it takes the application three or more seconds to process that request, we probably won’t be able to execute this request any faster using the async code. It is going to take the same amount of time as the sync request. But the main advantage is that with the async code the thread won’t be blocked for three or more seconds, and thus it will be able to process other requests. This is what makes our solution scalable.

Of course, using the async code for the database fetching operations is just one example. There are a lot of other use cases of using the async code and improving the scalability of our application and preventing the thread pool blockings.

So, for example, instead of having the synchronous action in our controller:

We can have an asynchronous one:

CryptoHelper And Data Protection

We won’t talk about how we shouldn’t store the passwords in a database as plain text and how we need to hash them due to security reasons. That’s out of the scope of this article. There are various hashing algorithms all over the internet, and there are many different and great ways to hash a password.

To register it, all we have to do is to use the AddDataProtection method in the ConfigureServices method. Then it can be injected via Dependency Injection:

Finally, we can use it: _protector.Protect("string to protect");

But if need a library that provides support to the .NET Core’s application and that is easy to use, the CryptoHelper is quite a good library.

Security and Using JWT

JSON Web Tokens (JWT) are becoming more popular by the day in web development. It is very easy to implement JWT Authentication due to the .NET Core’s built-in support. JWT is an open standard and it allows us to transmit the data between a client and a server as a JSON object in a secure way.

We can configure the JWT Authentication in the ConfigureServices method:

In order to use it inside the application, we need to invoke this code in the Configure method:



Testing Our Applications

We should write tests for our applications as much as we can. From our experience, we know there is no always time to do that, but it is very important for checking the quality of the software we are writing. We can discover potential bugs in the development phase and make sure that our app is working as expected before publishing it to production. Of course, there are many additional reasons to write tests for our applications.

In conclusion, Hope I explained well by Mohsen

In this article, my main goal was to familiarize you with the best practices when developing an API project in .NET Core. Some of those could be used in other frameworks as well, therefore, having them in mind is always helpful.

If you find that something is missing from the list, let me know, Please