tag:blogger.com,1999:blog-90490320253422643392024-03-18T21:16:26.898+03:00sadomovalex's blogBlog for software developersAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.comBlogger646125tag:blogger.com,1999:blog-9049032025342264339.post-30183075092888392312024-03-10T19:43:00.000+03:002024-03-10T19:43:01.017+03:00Cinnamon: first thing you may want to install when switched from Windows to LinuxIf you worked in Windows and then switched to Linux it may be painful in beginning since user experience is a bit different (and here we are talking about graphical UX in Linux, not command line). E.g. this is how RHEL8 (Red Hat Enterprise Linux) with default GNOME desktop environment looks like:Yes, there are windows also but no minimize/maximize icons nor taskbar. The good news is that there isAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-66675828673651984382024-02-06T08:54:00.000+03:002024-02-06T08:54:01.854+03:00Fix problem with Git client for Linux which asks for credentials on every push with installed SSH keyRecently I faced with the problem that Git client for Linux (CentOS) always asked for user credentials on every push even though SSH key was installed. In general SSH key is installed exactly for avoiding that. So what went wrong?Let's briefly check whole process. First of all we need to install SSH key pair. On Linux it can be done with ssh-keygen tool. If you don't want to enter passphrase on Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-77805411665996671142024-01-09T13:32:00.001+03:002024-01-09T13:32:26.419+03:00Verify JWT tokens with EdDSA encryption algorithmIn my previous posts of this series I showed how to generate EdDSA private and public keys pair and how to sign JWT tokens using private EdDSA key. In this last post of the series I will show how to verify signed JWT token with public key.Let's remind that EdDSA key pair may look like that in JSON format:
{
"kty": "OKP",
"alg": "EdDSA",
"crv": "Ed25519",
"x": "...",
"d": "..."
}
where "x"Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-35712446729225078362023-12-25T17:37:00.002+03:002024-01-09T13:33:52.075+03:00Sign JWT tokens with EdDSA encryption algorithmIn my previous post of this series I showed how to generate key pair for EdDSA encryption algorithm. Let's now go further and use these keys to sign JWT token. If you remember from previous post "d" property of json object with keys pair belongs to private key. We will use this private key for signing our JWT token.For creating JWT token we need to define claims. They are app/domain specific. We Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-18733298032720549532023-12-12T21:03:00.003+03:002023-12-12T21:03:51.279+03:00Fix Linq 2 NHibernate for MySQLIf you use NHibernate with MySQL and Linq 2 NHibernate to simplify fetching data you may face with problem: queries created by Linq2NH use square brackets by default. That is fine for SQL Server but won't work in MySQL which uses backticks ``.For MySQL we need to instruct NHibernate to use backticks instead of square brackets. It can be done by setting interceptor in NH config:
public class Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-3197954295825721812023-11-18T19:58:00.002+03:002023-11-18T19:58:36.857+03:00Use Obfuscar for obfuscating ASP.Net Core web appsObfuscar is free and open source code obfuscation library for .NET. However if you want to use it in web app (ASP.Net Core) it is not that straightforward. First of all you should be ready that Obfuscar may break many things in runtime quite easily. I.e. project will be still compiled successfully but when you will try to run it may get unclear errors. Second - in web apps it is even more tricky Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-320684343841968392023-11-07T18:01:00.001+03:002023-11-07T18:01:21.798+03:00Bind complex view model objects in ASP.Net Core using ComplexObjectModelBinderThe way how view model objects are bound has been changed in ASP.Net Core. Now we need to create custom model binder class which inherits IModelBinder interface and implement binding logic there (in ASP.Net Core there is no DefaultModelBinder base class anymore which we may inherit in custom binders). However for most cases binding logic itself will be the same still - only custom logic will Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-11415828441684544772023-10-11T12:29:00.006+03:002024-01-09T13:34:27.495+03:00Generate EdDSA key pair in .NET and save it to jsonEdDSA is one of the commonly used encryption algorithms atm. There is a trend to use it instead of older RSA alg. In .Net there are not that many resources about it. E.g. popular nuget package jose-jwt (Javascript Object Signing and Encryption) still doesn't support EdDSA. Fortunately there are another packages which support it:Portable.BouncyCastleScottBrady.IdentityModelbut many basic examples Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-70087252681179604512023-09-27T15:57:00.001+03:002023-09-27T15:57:04.386+03:00Problem with datetime format used in %date% environment variable in Windows scheduled tasksRecently I've faced with interesting problem. Let's say you have Russian datetime format set in Windows (Control panel > Region > Formats) and create new Windows scheduled task which runs the following cmd script:echo %date%It will use Russian datetime as it should. Now we change OS datetime format to English. If we will run the same script manually it will immediately use new format. But Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-74475348941526097272023-09-20T21:56:00.005+03:002023-09-20T21:56:43.920+03:00Use Github secrets to restore nuget packages from private packages source with authentication in Dockerfile via Github actionsIf you use private nuget packages source with authentication and Docker in your project you may need to restore packages from this custom packages source within Docker file. In this post I will show how to use Github secrets for that when you build Docker image via docker/build-push-action Github action.First of all in the yaml file of our Github action we need to pass necessary secrets Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-58468201182995652032023-08-15T17:49:00.004+03:002023-08-15T17:49:51.725+03:00Problem with MissingManifestResourceException for embedded resx files in subfoldersIf you worked with .Net applications you most probably know what is embedded resources:Such resources are embedded directly to output assembly. We may check them e.g. with decompiler: Sometime we may need to change namespace of generated resources: e.g. in above example Foo.resx file is located in Resources sub folder so by default it will generate strongly typed class in namespace Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-86873267332132557012023-08-08T17:20:00.002+03:002023-08-08T17:20:15.221+03:00Camlex and Camlex.Client 5.4.2 releasedNew version 5.4.2 of Camlex library has been released. Starting with this version it became possible to generate CAML queries with string operators BeginsWith and Contains for ContentTypeId field type e.g. the following C# code:
Camlex.Query().Where(x => ((DataTypes.ContentTypeId)x["ContentTypeId"]).StartsWith("0x123")).ToString(true);
will generate the following CAML query:
<Query>
Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-55810315550168143552023-07-04T17:16:00.002+03:002023-07-04T17:16:39.541+03:00Generate database schema for MySQL using NHibernate hbm2ddl toolNHibernate has hbm2ddl tool which allows automatically export database tables schema based on provided mappings. I.e. we may define mapping using C# for some POCO class:
public class User
{
public virtual int Id { get; set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
like that:
public class UserMap : ClassMap<User>
{
Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-85548720404001345162023-06-22T13:15:00.004+03:002023-06-22T13:15:36.496+03:00Implement TAP/multithread friendly logging scopes for Microsoft.Extensions.Logging.ILoggerSome time ago I wrote a post how to implement custom logger which writes logs to Azure storage blob container: Custom logger for .Net Core for writing logs to Azure BLOB storage. This logger implements ILogger interface from Microsoft.Extensions.Logging namespace. It works quite well but doesn't support logging scopes:
public IDisposable BeginScope<TState>(TState state) => default!;
Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-18455299935731036962023-06-17T17:44:00.000+03:002023-06-17T17:44:00.322+03:00Profile MySQL db with Neor Profile SQLIf you need to profile MySQL db you may use builtin MySQL shell profiler (CLI). Also there is free GUI alternative - Neor Profile SQL. There are few things which should be done before to use it.When you launch Profile SQL it asks to establish connection using default parameters for localhost:If you click Test button you may get "Test is failed" error even with correct credentials of the root userAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-37796976806782823732023-06-17T11:04:00.002+03:002023-06-17T11:04:28.904+03:00StackOverflowException when use hierarchical object mapping with AutoMapper and Fluent NHibernate lazy loadingSuppose that we have the following class Category with self-reference (regular parent-child hierarchy):
public class Category
{
public virtual T Id { get; set; }
public virtual string Name { get; set; }
public virtual Category ParentCategory { get; set; }
public virtual IList<Category> ChildCategories { get; set; }
}
(properties are virtual which is required by NHibernateAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-65504519978793098172023-05-29T21:12:00.001+03:002023-05-29T21:12:31.412+03:00Run ASP.Net Core Web API on Kestrel dev web server with https on WindowsIn this post I will describe how to run ASP.Net Core Web API on Kestrel development web server under https. First of all we need to create self-signed SSL certificate. We may generate it with PowerShell (see Use self-signed SSL certificate for web API hosted in Azure App service) or openssl tool:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout test.key -out test.crt -config Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-31092148245890078732023-05-18T10:23:00.002+03:002023-05-18T10:23:16.230+03:00Generate action urls from C# lambda expressions in ASP.Net MVC Core: good news for those who missed it thereIn ASP.Net MVC (on top on .Net Framework) there was useful mechanism for generating actions urls from C# lambda expressions. Let's say we have controller UserController for managing users which has List action with 3 params:page number (in case if users list is large and we need to use pagination)sort by (first name, last name, etc)sort direction (asc or desc)
public enum SortDirection
{
AscAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-39550893583433646222023-05-03T16:46:00.006+03:002023-06-22T13:17:56.829+03:00Custom logger for .Net Core for writing logs to Azure BLOB storageIf you create .Net Core app you may use standard console logger (from Microsoft.Extensions.Logging.Console nuget package). For development it works quite well but if app goes to production you probably want to store logs in some persistent storage in order to be able to check them when needed. In this post I will show how to create custom logger which will write logs to Azure BLOB storage.At Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-74437522378054846272023-04-17T18:14:00.004+03:002023-04-17T18:14:48.086+03:00Add basic authentication to ASP.Net Core Web APIBasic authentication is probably simplest authentication type for Web API when HTTP requests are authenticated using username and passwords provided in HTTP request headers. In this post I will describe how to add basic authentication to ASP.Net Core Web API.At first we need to add reference to idunno.Authentication.Basic nuget package. It contains infrastructure for basic authentication ready toAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-80182240141248728622023-03-29T18:50:00.002+03:002023-03-29T18:50:31.489+03:00Generate strongly-typed C# client for ASP.Net Core Web API with OpenAPI (swagger) support running on localhostSome time ago I wrote how to generate C# client for web api with OpenAPI support using online service https://generator3.swagger.io/api/generate. Limitation of this approach is that web api should be available online as well. But what to do if you develop web api and it is available only on localhost? One of the way is to use https://github.com/swagger-api/swagger-codegen but it is not very easy Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-88922894795203593492023-03-28T13:31:00.005+03:002023-03-29T18:52:56.771+03:00Add OpenAPI (Swagger) support to ASP.Net Core Web APIOpenAPI (swagger) support gives many advantages to your web api. One of them is possibility to generate strongly typed clients for calling web api so instead of developing calls from scratch (with HttpClient, building requests, deserialize response, etc) we get ready for use client with POCO classes for requests and response data. In one of my previous articles I wrote how to generate such clientAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-73307130595772298672023-03-27T21:29:00.001+03:002023-03-27T21:29:11.129+03:00Create modern looking CLI tool with command line verbsMore and more CLI tools (command line interface) or simply console apps use unified approach for processing command line arguments. In this post I will write about one way of creating these apps using CommandLineParser. Like it is said on the project's github page CommandLineParser isAPI for manipulating command line arguments and related tasks, such as defining switches, options and verb Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-83110432959688005612023-02-14T18:23:00.005+03:002023-02-14T18:23:41.346+03:00One reason of "Error response from daemon: Container {id} is not running" error with mongo docker containerIn this post I will write about one possible problem which you may face with when try to run MongoDB docker container. Env used in this article: docker installed on Ubuntu running on WSL2 on Windows 11.Let's start from beginning. If we want to run MongoDB docker container we first need to download it:
docker pull mongo
If everything went well you should see something like that:Then we may wantAlexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0tag:blogger.com,1999:blog-9049032025342264339.post-64363138974473597042023-02-08T22:23:00.003+03:002023-02-08T22:23:44.751+03:00One important difference between MySQL installation on Windows and LinuxMySQL may be installed both on Windows and Linux. However there is one important change which I would like to know before to install it on Linux :) In this post I will share this finding.Under the hood MySQL tables data is stored in files on file system. Windows file system is case insensitive and if you try to create table like that:
create table `UserInfo` (
...
)
this table will be Alexey Sadomovhttp://www.blogger.com/profile/18112105989691733410noreply@blogger.com0