Category Archives: Code editor

One liner event subscription in C#

Generally an event subscription looks something like this:

// Creating a timer
System.Timers.Timer t = new(1000);
// Subscribing on it's elapsed event
t.Elapsed += T_Elapsed;
// Starting the timer
t.Start();
// Implementing the timers' elapsed event
void T_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine("Tick!");
}
// Not letting the app to exit
Console.ReadLine();

We have an event emitter, the timer, and we are subscribing and implementing a method when that event is emitted.

It is possible to shorten this event implementation in one line:

// Creating a timer
System.Timers.Timer t = new(1000);
// Subscribing and implementing on it's elasped event
t.Elapsed += (_, _) => { Console.WriteLine("Tick!"); };
// Starting the timer
t.Start();
// Not letting the app to exit
Console.ReadLine();

Note: the (_, _) is equal to (sender, e), we just shorten them because we won’t use them.

Although it can be convenient to use this form regularly, but take care and keep the code readable!

Happy coding!

Visualize and test our ASP.NET API

Goal of this post is to show how easy it is to add visualization and testing option to our API using Swagger.

Tool/prerequisites we are going to use: Visual Studio, .NET 6, ASP.NET, Swashbuckle.AspNetCore.SwaggerGen and Swashbuckle.AspNetCore.SwaggerUI as NuGet dependencies.

GitRepo is available here.

Nowadays for a complex web application it is almost always necessary to write a WebAPI. One way to test these endpoints during and after implementation is to manually create our own http clients, which is time consuming and hard to follow the constant changes, which can occur regularly with a new API. There are many tools for this purpose. Probably one of the most well known is Swagger, which we are going to showcase.

Start a new ASP.NET Empty project. We are adding a new folder named Controllers and a controller named HomeController.cs to it. Our structure should look like this:

Project structure

New we are extending the HomeController with our two endpoints:

[Route("api/home")]
public class HomeController : Controller
{
    [HttpGet]
    [Route("getMessage/{message}")]
    public ActionResult<string> Get(string message)
    {
        return $"Your message from get was {message}";
    }


    [HttpPost]
    [Route("postMessage")]
    public ActionResult<string> Post([FromBody] string message)
    {
        return $"Your message from post was {message}";
    }
}

Our endpoints should be available on these two urls:

localhost:port/api/home/getMessage/{message}
localhost:port/api/home/postMessage

Note: at this state the endpoints are not served as we haven’t configured our site to interact with controllers.

Let’s configure our website to serve our endpoints and use Swagger+SwaggerUI. From Nuget we need to add Swashbuckle.AspNetCore.SwaggerGen and Swashbuckle.AspNetCore.SwaggerUI packages. As all of our dependencies are in place we can go to Program.cs and setup these:

var builder = WebApplication.CreateBuilder(args);
// Telling ASP that we want to use the controller feature
builder.Services.AddControllers();
// Adding swagger code generator (and it's dependencies) to the services
builder.Services.AddSwaggerGen();

var app = builder.Build();
// Mapping the endpoints in the controllers to serve them
app.MapControllers();
// Registering swagger middleware
app.UseSwagger();
// Registering the UI service
app.UseSwaggerUI();
// Starting the website
app.Run();

Running our application will fail to load the default page, because we don’t have any. But if we add swagger at the end of our url, the SwaggerUI should appear:

SwaggerUI page

We can click on the endpoint dropdowns and try them out by adding parameters and clicking on the Execute button.

Happy coding!

Don’t open new browser when starting ASP.NET website

I don’t really like the default mechanism of Visual Studio, that it starts a new browser instance every time we start our website. It is quite easy to solve this problem. Look for the launchSettings.json under Properties folder. Search for the profile you are starting and set the launchBrowser to false. Thats all!

Happy coding!

Async entrypoint for C# .NET program

The entrypoint of our C# program is by default a static void Main function, it should look something like that:

internal class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");
    }
}

Modern day C# applications tend to use async…await, which requires to assign async to the function like following:

static async void Main(string[] args)

This would cause an error when running the application:

Important: We should avoid async void and only use it if we really know what we are doing.

The solution is quite straightforward, update void to Task:

internal class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Hello World!");
    }
}

Happy coding!

AWS S3 read and write operations using C#

Goal of this exercise is to show how to read and write files on AWS S3 from a .NET console application.

Tool/prerequisites we are going to use: Visual Studio, .NET 6, AWSSDK.S3 as NuGet dependency.

GitRepo is available here.

AWS S3 is a versatile product, used for many different purposes from logs to big data storages. It’s basic operations are easy to implement using the AWS SDK.

For the first step we need to create an S3 bucket which will hold our files. Go to AWS console, search for S3 product in the search bar:

Search for S3 in the AWS search bar

Click on Create bucket button:

Create bucket button

Choose a name and region, then hit Create bucket at the bottom of the page:

Creating the bucket

Now we are all set on the AWS console, we are going to use it later on for testing.

We can get back to our code editor and add AWSSDK.S3 to our project, which has bunch of S3 related codes to help us out. Let’s write some code:

using Amazon.S3;
using Amazon.S3.Model;
using System.Text;

namespace BlogDavid_S3ReadWrite
{
    internal class Program
    {
        // Note: Running the program will use the local machine's credentials!

        // Store the bucket's name somewhere
        const string s3BucketName = "blogdavid-s3readwrite";
        // Set the client to our bucket's region
        static IAmazonS3 s3Client = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1);

        static async Task Main(string[] args)
        {
            // Generating a random path for our text file
            string randomizedPath = $"{Guid.NewGuid()}/{Guid.NewGuid()}/{Guid.NewGuid()}.txt";

            // Adding some text to save
            string textToSave = $"I am a text generated at {DateTime.UtcNow}";

            // Converting the text into bytes
            byte[] textAsBytes = Encoding.UTF8.GetBytes(textToSave);

            using (MemoryStream ms = new MemoryStream(textAsBytes))
            {
                // Rewinding the stream
                ms.Position = 0;

                PutObjectRequest putRequest = new PutObjectRequest
                {
                    // Name of the bucket
                    BucketName = s3BucketName,
                    // Key as the path under the bucket
                    Key = randomizedPath,
                    // Data we are saving
                    InputStream = ms,
                };

                await s3Client.PutObjectAsync(putRequest);
            }

            // Let's read back the previous file

            // Construction the request object
            GetObjectRequest getRequest = new GetObjectRequest
            {
                BucketName = s3BucketName,
                Key = randomizedPath
            };

            // Sening the request
            using (var getResponse = await s3Client.GetObjectAsync(getRequest))
            using (var sr = new StreamReader(getResponse.ResponseStream))
            {
                // Reading back the response
                var getResponseString = await sr.ReadToEndAsync();
                // Showing the response, which is hopefully the text we just saved
                Console.WriteLine(getResponseString);
            }

            Console.ReadKey();
        }
    }
}

Starting our app, it should write and read a file on S3:

Happy coding!

Calling another process from C# console app

Goal of this post is to show how to call an exe from another program.

Tool/prerequisites we are going to use: Visual Studio, .NET 6.

GitRepo is available here.

Calling another process and capturing it’s output is really straightforward in .NET. We just need to create a new ProcessStartInfo with the needed parameters and pass it to the Process.Start method. That is all.

Here we have a solution with two projects. The first project is receiving two parameters and writes out a number in a loop, then the second project is depending on the first one, calls it and captures it’s output.

“Counter” project’s code:

public class Program
{
    public static void Main(string[] args)
    {
        int start = Convert.ToInt32(args[0]);
        int end = Convert.ToInt32(args[1]);

        for (int current = start; current < end; current++)
        {
            Console.WriteLine(current);
        }
    }
}

Note: there is no safeguarding on the parameters, as it is just an example project.

“Caller” project’s code:

using System.Diagnostics;


var proc = Process.Start(new ProcessStartInfo
{
    // Arguments to pass to another process, separated by a space
    Arguments = "10 20",
    // Name of the exe file. Note: it will be copied by the builder (Visual Studio) to the projects bin folder, as it is dependent on the project "BlodDavid_CounterProject"
    FileName = "BlodDavid_CounterProject.exe",
    // To redirect the output stream, we need to set it to false
    UseShellExecute = false,
    // We want to capture the data written to the output of the other process
    RedirectStandardOutput = true,
    // We don't want to show the users another windows, just the output in our main app
    CreateNoWindow = true
});

// Starting the another process
proc.Start();

// Listening to the output stream
while (!proc.StandardOutput.EndOfStream)
{
    Console.WriteLine($"Message from the other process: {proc.StandardOutput.ReadLine()}");
}
// Don't let our program to exit until the other process finishes
proc.WaitForExit();

// Notifying our user that the other project ended
Console.WriteLine("To exit press enter!");
Console.ReadLine();

Happy coding!

Basic testing in Python using Pytest

Goal of this post is to write a short test using Pytest.

Tool/prerequisites we are going to use: Visual Studio Code (or any file editor), python 3+.

GitRepo is available here.

Testing is and will be essential when coding. To make our life easier, developers created many frameworks and helpers to quickly achieve high code coverage. One well know library for Python is Pytest, which we are going to use in this article.

Start a new project/folder using your favorite editor and create a requirements file for PIP, we are going to use test_requirements.txt. Add our only dependency:

pytest

Install our dependency with the following command (running from the folder where the test_requirements.txt is):

pip install -r test_requirements.txt

Now we can add our code file with the name basic_calculator.py:

def sum(numberOne: int, numberTwo: int):
    return numberOne + numberTwo

It doesn’t do anything fancy, just sums two number.

Now comes the test. Add a new file called test_basic_calculator.py:

import basic_calculator

class TestHandler:
    def test_sum_one(self):
        sum = basic_calculator.sum(2,3)
        assert sum == 5

    def test_sum_two(self):
        sum = basic_calculator.sum(66,55)
        assert sum == 121

We are done with coding, let’s run our test (give the following command from folder):

python -m pytest

The result should be something similar to this:

What happened here? We asked python to run the module called pytest in the working folder. Pytest then searches for filenames which start with “test_” and looks for classes starting with “Test” containing function names starting with “test”.

Narrowing down the test scope

We might want to run test only on one file, to do so we can specify it by name:

python -m pytest ./test_basic_calculator.py

There are further options as well

Run only one class in a file:

python -m pytest ./test_basic_calculator.py -k "Test_Handler"

or

python -m pytest ./test_basic_calculator.py::Test_Handler

If you only want to run one test in a class:

python -m pytest ./test_basic_calculator.py -k "Test_Handler and test_sum_one"

or

python -m pytest ./test_basic_calculator.py::Test_Handler::test_sum_one

Happy coding!

Work with SQLite using C#

Goal of this post is to show some of the capabilities of SQLite with C#.

Tool/prerequisites we are going to use: Visual Studio, .NET 6, Microsoft.Data.Sqlite NuGet package.

GitRepo is available here.

SQLite is a powerful tool to handle data locally. It’s file based solution helps us to quickly test our application with real world data, but without setting up a full SQL server. We are going to create a console application with some basic functionality.

After the project is created, first we need to install our prerequisite called Microsoft.Data.Sqlite using NuGet package manager. From ‘Solution Explorer’ open ‘Dependencies’, right click on ‘Packages’ and choose ‘Manage NuGet Packages…’

Choose the ‘Browse’ tab and copy in the name: Microsoft.Data.Sqlite, select it and click ‘Install’ on the right panel.

New we have all the necessary packages and we can start coding. Reference the just added library at the top of the Program.cs:

using Microsoft.Data.Sqlite;

To use the same connection string, we will have a general provider method:

        private static string CreateSqliteConnectionString(string dbName)
        {
            SqliteConnectionStringBuilder builder = new SqliteConnectionStringBuilder();
            builder.Add("Data Source", dbName);
            return builder.ConnectionString;
        }

Initialize the DB with a ‘person’ table:

        private static void CreatePersonTable(string connectionString)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using(SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = "CREATE TABLE person(id INTEGER PRIMARY KEY, full_name TEXT, age INT)";
                command.ExecuteNonQuery();
            }
        }

Now add some basic functionality methods for CRUD (create, read, update, delete):

 private static void InsertPerson(string connectionString, string fullName, int age)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"INSERT INTO person (full_name, age) VALUES ('{fullName}', {age})";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void DeletePerson(string connectionString, int id)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"DELETE FROM person WHERE id = {id}";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void UpdatePerson(string connectionString, int id, string fullName, int age)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"UPDATE person SET full_name = '{fullName}', age = {age} WHERE id = {id}";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void SelectPerson(string connectionString, int id)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"SELECT id, full_name, age FROM person WHERE id = {id}";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine($"Id: {reader.GetInt32(0)}, full_name: {reader.GetString(1)}, age: {reader.GetInt32(2)}");
                    }
                }
                connection.Close();
            }
        }

        private static void ListPersons(string connectionString)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"SELECT id, full_name, age FROM person ORDER BY id DESC";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine($"Id: {reader.GetInt32(0)}, full_name: {reader.GetString(1)}, age: {reader.GetInt32(2)}");
                    }
                }
                connection.Close();
            }
        }

If we run our code multiple times, the ‘CreatePersonTable’ can run into problem, that the DB already exists, lets delete it if exists. It is easy to do as it is only a file in our file system:

        private static void RemoveDBIfExists(string dbName)
        {
            FileInfo fi = new FileInfo(dbName);
            if (fi.Exists)
            {
                fi.Delete();
            }
        }

Now call our methods one-by-one from ‘Main’:

static void Main(string[] args)
        {
            Console.WriteLine("Initializing db");
            string dbName = "blog.db";
            RemoveDBIfExists(dbName);
            string connectionString = CreateSqliteConnectionString(dbName);
            CreatePersonTable(connectionString);
            Console.WriteLine("Db created with person table");

            Console.WriteLine("Adding initial data");
            InsertPerson(connectionString, "Peter", 35);
            InsertPerson(connectionString, "Anna", 35);
            InsertPerson(connectionString, "David", 38);
            InsertPerson(connectionString, "Lilla", 27);

            Console.WriteLine("Listing persons");
            ListPersons(connectionString);

            Console.WriteLine("Deleting a person");
            DeletePerson(connectionString, 2);

            Console.WriteLine("Listing persons");
            ListPersons(connectionString);

            Console.WriteLine("Selecting person id = 1");
            SelectPerson(connectionString, 1);

            Console.ReadLine();
        }

Running the whole code should output something similar to this:

Putting every piece together we should have the following Program.cs (or see on GitHub):


using Microsoft.Data.Sqlite;

namespace BlogDavid_BasicSqlLite
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Initializing db");
            string dbName = "blog.db";
            RemoveDBIfExists(dbName);
            string connectionString = CreateSqliteConnectionString(dbName);
            CreatePersonTable(connectionString);
            Console.WriteLine("Db created with person table");

            Console.WriteLine("Adding initial data");
            InsertPerson(connectionString, "Peter", 35);
            InsertPerson(connectionString, "Anna", 35);
            InsertPerson(connectionString, "David", 38);
            InsertPerson(connectionString, "Lilla", 27);

            Console.WriteLine("Listing persons");
            ListPersons(connectionString);

            Console.WriteLine("Deleting a person");
            DeletePerson(connectionString, 2);

            Console.WriteLine("Listing persons");
            ListPersons(connectionString);

            Console.WriteLine("Selecting person id = 1");
            SelectPerson(connectionString, 1);

            Console.ReadLine();
        }
        private static void RemoveDBIfExists(string dbName)
        {
            FileInfo fi = new FileInfo(dbName);
            if (fi.Exists)
            {
                fi.Delete();
            }
        }
        private static string CreateSqliteConnectionString(string dbName)
        {
            SqliteConnectionStringBuilder builder = new SqliteConnectionStringBuilder();
            builder.Add("Data Source", dbName);
            return builder.ConnectionString;
        }
        private static void CreatePersonTable(string connectionString)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using(SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = "CREATE TABLE person(id INTEGER PRIMARY KEY, full_name TEXT, age INT)";
                command.ExecuteNonQuery();
            }
        }

        private static void InsertPerson(string connectionString, string fullName, int age)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"INSERT INTO person (full_name, age) VALUES ('{fullName}', {age})";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void DeletePerson(string connectionString, int id)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"DELETE FROM person WHERE id = {id}";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void UpdatePerson(string connectionString, int id, string fullName, int age)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"UPDATE person SET full_name = '{fullName}', age = {age} WHERE id = {id}";
                command.ExecuteNonQuery();
                connection.Close();
            }
        }

        private static void SelectPerson(string connectionString, int id)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"SELECT id, full_name, age FROM person WHERE id = {id}";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine($"Id: {reader.GetInt32(0)}, full_name: {reader.GetString(1)}, age: {reader.GetInt32(2)}");
                    }
                }
                connection.Close();
            }
        }

        private static void ListPersons(string connectionString)
        {
            using (SqliteConnection connection = new SqliteConnection(connectionString))
            using (SqliteCommand command = connection.CreateCommand())
            {
                connection.Open();
                command.CommandText = $"SELECT id, full_name, age FROM person ORDER BY id DESC";
                using (var reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine($"Id: {reader.GetInt32(0)}, full_name: {reader.GetString(1)}, age: {reader.GetInt32(2)}");
                    }
                }
                connection.Close();
            }
        }
    }
}

Happy coding!

Deploying python function as Lambda with API Gateway

Goal of this exercise is to put our previously developed python function behind a REST API.

Tools/prerequisites we are going to use: Visual Studio Code, NPM, python 3, AWS account, AWS credentials configured locally.

GitRepo is available here.

Api Gateways are important infrastructure elements, as a simple Lambda function is only available from inside AWS ecosystem. REST Api is a common, easy to implement standard to share resource.

To make our Lambda function publicly available we are going to update our previous code base with two things: tell the serverless to create the Api Gateway for our stack and upgrade the response of our utc-time-teller.

Let’s start with the python code changes. As we are going to communicate on HTTP channel JSON is a good model structure to respond with. Edit our handler’s code as following:

import datetime
import json

def handler(event, context) -> str:
    dt = datetime.datetime.now(datetime.timezone.utc)
    utc_time = dt.replace(tzinfo=datetime.timezone.utc)

    return {
        "statusCode": 200,
        "headers": {
            "Content-Type": "application/json"
        },
        "body": json.dumps({
            "utc ": str(utc_time)
        })
    }

We are returning a default HTTP response with statusCode of 200 (everything is OK), telling the receiver that the message is in JSON format (“Content-Type”: “application/json”) and of course adding the body itself.

The Lambda is still testable using the previously shown method:

We can continue with the serverless.yml:

Add these few lines to the end of our function:

    events:
      - http:
          path: /{proxy+}
          method: any
      - http:
          path: /
          method: any

This will generate the API Gateway on AWS. The whole serverless.yml looks like this:

service: BlogDavidPythonLambdaDeploy

provider:
  name: aws
  region: eu-west-1

functions:
  utc-time-teller:
    name: utc-time-teller
    handler: src/lambda_handler.handler
    memorySize: 128
    timeout: 30
    runtime: python3.8
    events:
      - http:
          path: /{proxy+}
          method: any
      - http:
          path: /
          method: any

Now call our deployment script from a command line tool:

serverless deploy

Serverless CLI should add new lines to the logs under the category “endpoints”. Copy the one without {proxy+} ending to the browser and enjoy our newly created API gateway response: