I recently worked on my own project implementing a Roslyn generator of read-only interfaces for existing classes. When I decided it was time to share my results with the community in the form of NuGet package, I wanted to implement a build pipeline. I have already solved a similar problem using AppVeyor. But this time there were some differences. First of all, in my previous projects I used Cake for building pipeline tasks. This time I decided to try Nuke. It promises better integration with Visual Studio. I also wanted to use the Russian equivalent of GitHub - GitVerse. Here I'll tell you how it went.
Tuesday, April 15, 2025
Friday, December 29, 2023
Log volume problem
When a problem occurs in our production system, we want to have in our logs all the information necessary to find the cause of the error. In rather complex systems, this leads to the collection of a large amount of data: which processing stages were completed, what were the arguments of some functions when called, what results were returned by calls to external services, etc. The problem here is that we have to collect all this information, even if there is no error. And this leads to an increase in the volume of our log storage, for which we have to pay.
Log levels (error, warning, information, ...) don't help much here. Usually the application has some target log level (for example, information). This means that all records with the level equal to or higher than this target level are logged, and all other records are discarded. But at the moment when an error occurs, it is these debug level entries that we are interested in, which are usually discarded. If the problem repeats frequently, we can temporarily lower the target level, collect all the necessary information, and then return the target level back. In this case, the rate of increase in the volume of the log storage increases only temporarily. But if the error is rare, this approach (although possible) is not very convenient because it leads to the collection of a large amount of data.
Can we improve the situation? I think we can. But here I have to say that in this article I will not offer a ready-made solution. This is just some idea that should be implemented in existing logging systems, as it requires changes to their source code.
Ok. Let's begin.
Thursday, November 2, 2023
Comparison of HTTP libraries
In .NET applications, we often need to make HTTP calls. In these cases, we can use the standard HttpClient class or some other library. For example, I have already used Refit and RestSharp. But I have never decided which one to use. Always the library was already utilized in the project I was working with. Therefore, I decided to compare these libraries to form my own meaningful opinion, which one is better and why. This is what I will do in this article.
But how should I compare these libraries? I have no doubt that they all can send HTTP requests and receive responses. After all, these libraries wouldn't have become so popular if they couldn't do that. Therefore, I'm more interested in additional features that are in demand in large corporative applications.
Ok, let's start.
Monday, February 27, 2023
Testing of dependency tree
Today, the use of dependency containers is widespread. The constructor of your classes accepts instances of other classes, they depend on other classes, etc. And the dependency container manages the construction of the entire instance tree.
This system has its price. For example, during testing, you must create instances of all the dependencies of a class in order to test this class. You can use something like Moq for this task. But in this case, there is a problem with class changes. If you want to add or remove any constructor parameter, you will also have to change the tests, even if this parameter does not affect them.
There is another task that we want to solve during testing. Let's say we want to test the work of not one isolated class, but the joint work of several classes in some part of our system. Our dependency container creates a whole tree of instances of various classes. And you want to test the whole tree. Let's see how we can do this, what obstacles we will face and how we can overcome them.
Monday, November 21, 2022
My experience with OData
OData is very interesting technology. Using several lines of code you can support filtering, paging, partial selection, ... for your data. Today GraphQL is replacing it, but OData is still very attractive.
Nevertheless, there are several pitfalls I had to deal with. Here I want to share my experience with OData.
Thursday, October 27, 2022
Web request sequence visualization
Modern requests to web services are very complex. The service you are calling can call other services, they are other services, etc. All these requests can be executed in parallel. Of course, the logging system stores information from all participants in the request. But the clocks on different services can be slightly out of sync, so it is not easy to recreate the correct picture. And if we add message queues here (Azure EventHub, RabbitMQ, ...), the task becomes even more difficult.
Here I'll try to create a system that will allow us to quickly plot the sequence diagram of events during my request.
Ok, let's start.
Friday, September 23, 2022
Drag and Drop in WPF TreeView
Today I want to describe the implementation of drag and drop functionality inside WPF TreeView control. It sounds like a simple task, but took surprisingly a lot of time from me. So let's start.
Tuesday, July 12, 2022
My work with LiteDB
Recently I was looking for a storage system for my program. This is a desktop application that creates many objects and searches for text in them. So I thought: "Why don't I try something new." Instead of an SQL database, I could use some kind of document database. But I didn't want to have a separate server, I wanted this database to work with a simple file. Search of the Internet for this kind of databases for .NET applications quickly led me to LiteDB. And here I want to share my experience with this database.
Friday, June 3, 2022
Single database for multiple microservices with FluentMigrator
If you have multiple microservices, it is common to use a separate database for each of them. But recently we faced the following problem. Our price plan on database hosting provider includes only limited number of databases. We can't create new database for each microservice as it is too expensive. How can we solve this problem?
Thursday, June 2, 2022
Calling Thread.Abort and Thread.ResetAbort several times
In this short article I want to analyze a situation when we want to call Thread.Abort several times for a thread which uses Thread.ResetAbort to control cancellation process.
Monday, March 28, 2022
About trust in software systems
I recently heard about the following situation. The Ukrainian side has created some kind of video message. They claimed that the message was created on a certain date. But the Russian side stated that it was recorded in advance. So I started thinking if it was possible for ordinary people to check when the video was created.
Monday, February 28, 2022
How to use Telepresence in Windows
Recently I came across Telepresence. It allow you to quickly replace a deployment in your Kubernetes cluster with some application running on your machine. It means that all requests inside the cluster to the pods of this deployment will actually go to your developer machine. It allows you, for example, to debug your application in real environment. For other use cases please consult with the documentation.
Here I want to show how you can install and use it on your Windows machine.
Tuesday, November 16, 2021
How to use BenchmarkDotNet
If you want to measure the performance of your .NET code, you can use the BenchmarkDotNet NuGet package. Let's see what you can do with it.
Friday, November 12, 2021
Why do we need MediatR?
Recently I came across using the MediatR package in our source code. This interested me. Why should I use MediatR? What advantages can it give me? Here we'll discuss these topics.
Friday, October 1, 2021
How to use certificates in ASP.NET Core
In the simplest case, a certificate allows you to establish protected connection between client and server. But this is not all it is capable of. For example, I saw an online course on Pluralsight called Microservices Security. And there was one thing mentioned there, which is called Mutual Transport Layer Security. It not only allows client to make sure that it is interacting with the correct server, but also allows the server to authenticate the client.
This is why developers must know how to work with certificates. And it is for this reason that I decided to write this article. I want it to be a place where one can find basic knowledge about certificates. I don't think that experts can find something interesting here, but I hope that it will be useful for beginners and those who want to refresh their knowledge.
How to use dependency injection in any .NET application
If you work with ASP.NET applications, you know that it uses dependency injection mechanism. It is very convenient in many cases. But you may want to use the same mechanism in other types of applications: console, desktop, ... Here I'll show you how you can do it.
Thursday, April 15, 2021
Description of the enumeration members in Swashbuckle
Swagger is a great thing! It allows us to easily see the API of our service, generate a client for it in different languages and even work with the service through the UI. In ASP.NET Core we have NuGet package Swashbuckle.AspNetCore for the support of Swagger.
But there is one thing I don't like about this implementation. Swashbuckle can show me descriptions of methods, parameters, and classes based on XML comments in the .NET code. But it does not show the descriptions of the enum members.
Let me show you what I mean.
Wednesday, January 22, 2020
Constant reservation and Git hooks using C#
That was a time for Sam and Bob to make changes in the database. And Sam obediently went to the Web application and reserved number 333. But Bob forgot to do it. He just used 333 for his new step file. It happened that Bob was the first who committed his changes into the version control system. When Sam was ready to commit it appeared that step333.sql already existed. He contacted Bob, explained to him that step 333 was already reserved and asked Bob to fix the collision. But Bob answered:
- Hey, man. You know, my code is already in the 'master' branch, many developers already took it. And also it is already on production. Could you just fix your code instead?
Have you noticed it? The person who followed all the rules was the one who was punished. Sam had to change his files, modify his local database, etc. Personally, I hate such situations. Let's see how we can avoid it.