[2023] Sites

Those are the sites mosr visited –data obtained from https://takeout.google.com/?pli=1
























































1 https://github.com/
2 https://mail.yahoo.com/
3 https://lichess.org/
4 https://www.google.com/
5 https://learn.microsoft.com/
6 https://www.facebook.com/
7 https://twitter.com/
8 https://docs.google.com/
9 https://www.linkedin.com/
10 https://mail.google.com/
11 http://msprogrammer.serviciipeweb.ro/
12 https://www.meetup.com/
13 https://www.emag.ro/
14 https://portal.azure.com/
15 https://ignatandrei.github.io/
16 https://www.nuget.org/
17 https://zoso.ro/
18 https://trello.com/
19 https://login.microsoftonline.com/
20 https://chat.openai.com/
21 https://calendar.google.com/
22 https://tiltwebapp.azurewebsites.net/
23 https://blocks.githubnext.com/
24 https://devblogs.microsoft.com/
25 https://dev.to/
26 https://stackoverflow.com/
27 https://library.bookster.ro/
28 https://mermaid.live/
29 https://bilete.cfrcalatori.ro/
30 https://web.whatsapp.com/
31 https://www.amazon.com/
32 https://my.enel.ro/
33 https://dilemaveche.ro/
34 https://docusaurus.io/
35 https://www.samsung.com/
36 https://mvp.microsoft.com/
38 https://carbon.now.sh/
39 https://account.samsung.com/
40 https://www.thoughtworks.com/
41 https://angular.io/
42 https://www.youtube.com/
44 https://developers.google.com/
46 https://www.cinemacity.ro/
47 https://www.tripadvisor.com/
48 https://www.blablacar.ro/
49 https://www.lifebox.ro/
50 https://docs.github.com/
51 https://www.quora.com/
52 https://chess-results.com/
53 https://www.thinktecture.com/
54 https://worldtravelling.com/
55 https://javascript.plainenglish.io/
56 https://khalidabuhakmeh.com/
57 https://www.codeproject.com/

[2023]Activities

ADCES Presentations

Caching WebAPI : https://ignatandrei.github.io/Presentations/CachingWebAPIprez.html#1

Database2Rest: https://ignatandrei.github.io/Presentations/Database2Restprez.html#1

Polly: https://ignatandrei.github.io/Presentations/pollyprez.html#1

React: https://ignatandrei.github.io/Presentations/reactprez.html#1

SRE with .NET: https://ignatandrei.github.io/Presentations/SRE_with_NETprez.html#1

UsefullEndpoints : https://ignatandrei.github.io/Presentations/UsefullEndpointsprez.html#1

.NET Core 8: https://ignatandrei.github.io/Presentations/Net8WhatsNewprez.html#1

Open Source Software

Nuget Packages













Nume Link Documentation
RSCG_UtilityTypes https://www.nuget.org/packages/RSCG_UtilityTypes/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_UtilityTypes
RSCG_Templating https://www.nuget.org/packages/RSCG_Templating/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_Templating
rscgutils https://www.nuget.org/packages/rscgutils/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_Utils
RSCG_TimeBombComment https://www.nuget.org/packages/RSCG_TimeBombComment/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_TimeBombComment
RSCG_Static https://www.nuget.org/packages/RSCG_Static/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_Static
RSCG_WebAPIExports https://www.nuget.org/packages/RSCG_WebAPIExports/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_WebAPIExports
RSCG_AMS https://www.nuget.org/packages/RSCG_AMS/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/RSCG_AMS
SkinnyControllersGenerator https://www.nuget.org/packages/SkinnyControllersGenerator/ https://ignatandrei.github.io/RSCG_Examples/v2/docs/SkinnyControllersCommon
NetCoreUsefullEndpoints https://www.nuget.org/packages/netcoreusefullendpoints/ http://msprogrammer.serviciipeweb.ro/category/netcoreusefullendpoints/

Github Repos


















ignatandrei/RSCG_Examples ignatandrei/RSCG_Examples
ignatandrei/BlocklyAutomation ignatandrei/BlocklyAutomation
ignatandrei/QueryViewer ignatandrei/QueryViewer
ignatandrei/Presentations ignatandrei/Presentations
ignatandrei/syncPowershellProfile ignatandrei/syncPowershellProfile
MicroservicesBuffet/directoryBrowser MicroservicesBuffet/directoryBrowser
ignatandrei/PackageAnalyzer ignatandrei/PackageAnalyzer
ignatandrei/TILT ignatandrei/TILT
ignatandrei/TestReplacer ignatandrei/TestReplacer
ignatandrei/RSCG_InterceptorTemplate ignatandrei/RSCG_InterceptorTemplate
ignatandrei/RSCG_Utils ignatandrei/RSCG_Utils
ignatandrei/NetCoreShortLinks ignatandrei/NetCoreShortLinks
ignatandrei/NetCoreUsefullEndpoints ignatandrei/NetCoreUsefullEndpoints
ignatandrei/NETCoreBlockly ignatandrei/NETCoreBlockly
ignatandrei/RSCG_Templating ignatandrei/RSCG_Templating
ignatandrei/RSCG_Static https://github.com/ignatandrei/RSCG_Static
ignatandrei/RSCG_WebAPIExports https://github.com/ignatandrei/RSCG_WebAPIExports
ignatandrei/RSCG_AMS https://github.com/ignatandrei/RSCG_AMS
ignatandrei/SkinnyControllersGenerator https://github.com/ignatandrei/SkinnyControllersGenerator
ignatandrei/TestEFCoreDatabaseProviders https://github.com/ignatandrei/TestEFCoreDatabaseProviders
ignatandrei/RSCG_TimeBombComment https://github.com/ignatandrei/RSCG_TimeBombComment
ignatandrei/VisualAPI_GithubNextBlocks https://github.com/ignatandrei/VisualAPI_GithubNextBlocks
ignatandrei/MicroservicesPortChooser https://github.com/ignatandrei/MicroservicesPortChooser
ignatandrei/RSCG_UtilityTypes https://github.com/ignatandrei/RSCG_UtilityTypes
ignatandrei/RSCG_Decorator https://github.com/ignatandrei/RSCG_Decorator
ignatandrei/AOP_With_Roslyn https://github.com/ignatandrei/AOP_With_Roslyn

Open Applications

List of (92) Roslyn Source Code Generators with IIncrementalSourceGenerator :  List of RSCG | RSCG Examples (ignatandrei.github.io)

DB2Code https://github.com/ignatandrei/queryViewer/

Port Chooser / Registration: https://github.com/ignatandrei/MicroservicesPortChooser

Interests

Roslyn Code Generators https://github.com/ignatandrei/rscg_examples

Blazor Wasm

Open Telemetry

Semantic Kernel

Meetup: https://www.meetup.com/Bucharest-A-D-C-E-S-Meetup/

Tools used for this

github:

Link https://docs.github.com/en/graphql/overview/explorer

query:

query ContributionGraph {
   user(login: “ignatandrei”) {
     contributionsCollection(
       from: “2023-01-01T00:00:00+00:00”
       to: “2023-12-31T00:00:00+00:00”
     ) {
       commitContributionsByRepository(maxRepositories:100){
         repository{
           nameWithOwner
           url
           updatedAt
         }
       }    
     }
   }

}

Excel

https://codebeautify.org/json-to-html-converter#

For the 2024

Semantic Kernel / AI

Blockly Automation / Visual API

Book about Design Patterns in .NET Core

Start examples about Cloud Design Patterns with ASPIRE

video course + Book about Roslyn Code Generators

Blazor and RowNumber in Grid

The data that comes from the backend does not, usually, provide a row number . So how to obtain this ? Create a class, will say any programmer …

public  record DataWithNumber<T>(int number, T data) 
    where T: class
{
}

And the usage

 var data = HttpClient_WebApi.GetFromJsonAsAsyncEnumerable<Order_Details_Extended>(url);
 ArgumentNullException.ThrowIfNull(data);
 int i = 0;

 await foreach (var item in data)
 {
     if (item == null) continue;
     i++;
     dataArr.Add(new DataWithNumber<Order_Details_Extended>(i, item));
     if ((i < 500 && i % 100 == 0) || (i > 500 && i % 1000 == 0))
     {
         Console.WriteLine($"i={i}");
         nrRecordsLoaded = i;

         await InvokeAsync(StateHasChanged);
         await Task.Delay(1000);
     }
 }
 nrRecordsLoaded = i;

And the grid:

<FluentDataGrid Items="@dataForQuery" Virtualize="true" GenerateHeader="GenerateHeaderOption.Sticky">
    <PropertyColumn Property="@(p => p.number)" Sortable="true" />
    <PropertyColumn Property="@(p => p.data.OrderID)" Sortable="true">
        <ColumnOptions>
            <div class="search-box">
                <FluentSearch type="search" Autofocus=true @bind-Value=nameOrderIdFilter @oninput="HandleOrderIdFilter" @bind-Value:after="HandleClearIdFilter" Placeholder="Order Id..." />
            </div>
        </ColumnOptions>
    </PropertyColumn>
    
    <PropertyColumn Property="@(p => p.data.UnitPrice)" Sortable="true" />
    <PropertyColumn Property="@(p => p.data.ExtendedPrice)" Sortable="true" />
    <PropertyColumn Property="@(p => p.data.ProductID)" Sortable="true" />
    <PropertyColumn Property="@(p => p.data.Quantity)" Sortable="true" />
    <PropertyColumn Property="@(p => p.data.Discount)" Sortable="true" />
</FluentDataGrid>

Aspire Blazor WebAssembly and WebAPI

 

Aspire is the new visualizer – see https://github.com/dotnet/aspire

I am very fond of WebAPI  –  it allows for all people to see the functionality of a site , in a programmatic way ( side note: , my nuget package, https://www.nuget.org/packages/NetCore2Blockly , allows to make workflows from your WebAPI)

And Blazor WebAssembly is a nice addition that the WebAPI . I am talking about Interactive WebAssembly (https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?preserve-view=true&view=aspnetcore-8.0  )  . I do want ( for the moment ) to use Interactive Server because

  1. it is easy to forget to add functionality to the WebAPI
  2. it is not separating UI from BL

So I decided to add an Blazor WebAssembly and WebAPI into Aspire to see how they work together.

The first problem that  I have is how to transmit the WebAPI URL to the Blazor WebAssembly . Think that is not Interactive Server or Auto – in order to have the environment or configuration . Blazor Interactive WebAssembly  are just static files that are downloaded to the client. And they are executed in the browser.

But I have tried with adding to the Environment in usual way

builder.AddProject<projects.exampleblazorapp>(nameof(Projects.ExampleBlazorApp))
.WithEnvironment(ctx =&gt;
{
if (api.Resource.TryGetAllocatedEndPoints(out var end))
{
if (end.Any())
	ctx.EnvironmentVariables["HOSTAPI"] = end.First().UriString;
}

 

And no use!

After reading ASP.NET Core Blazor configuration | Microsoft Learn  and aspire/src/Microsoft.Extensions.ServiceDiscovery at main · dotnet/aspire (github.com) and API review for Service Discovery · Issue #789 · dotnet/aspire (github.com) I realized that the ONLY way is to put in wwwroot/appsettings.json

So I came with the following code that tries to write DIRECTLY to wwwroot/appsettings.json file


namespace Aspire.Hosting;
public static class BlazorWebAssemblyProjectExtensions
{
    public static IResourceBuilder<ProjectResource> AddWebAssemblyProject<TProject>(
        this IDistributedApplicationBuilder builder, string name,
        IResourceBuilder<ProjectResource> api) 
        where TProject : IServiceMetadata, new()
    {
        var projectbuilder = builder.AddProject<TProject>(name);
        var p=new TProject();
        string hostApi= p.ProjectPath;
        var dir = Path.GetDirectoryName(hostApi);
        ArgumentNullException.ThrowIfNull(dir);
        var wwwroot = Path.Combine(dir, "wwwroot");
        if (!Directory.Exists(wwwroot)) {
            Directory.CreateDirectory(wwwroot);
        }
        var file = Path.Combine(wwwroot, "appsettings.json");
        if (!File.Exists(file))
            File.WriteAllText(file, "{}");
        projectbuilder =projectbuilder.WithEnvironment(ctx =>
        {
            if (api.Resource.TryGetAllocatedEndPoints(out var end))
            {
                if (end.Any())
                {
                    
                    var fileContent = File.ReadAllText(file);

                    Dictionary<string, object>? dict;
                    if (!string.IsNullOrWhiteSpace(fileContent))
                        dict = new Dictionary<string, object>();
                    else
                        dict = JsonSerializer.Deserialize<Dictionary<string,object>>(fileContent!);

                    ArgumentNullException.ThrowIfNull(dict);
                    dict["HOSTAPI"] = end.First().UriString;                    
                    JsonSerializerOptions opt = new JsonSerializerOptions(JsonSerializerOptions.Default)
                            { WriteIndented=true};
                    File.WriteAllText(file,JsonSerializer.Serialize(dict,opt));
                    ctx.EnvironmentVariables["HOSTAPI"]=end.First().UriString;
                    
                }
                    
            }

        });
        return projectbuilder;

    }
}

And in Aspire

var api = builder.AddProject<Projects.ExampleWebAPI>(nameof(Projects.ExampleWebAPI));
builder.AddWebAssemblyProject<Projects.ExampleBlazorApp>(nameof(Projects.ExampleBlazorApp), api);

And in Blazor Interactive WebAssembly


var hostApi = builder.Configuration["HOSTAPI"];
if (string.IsNullOrEmpty(hostApi))
{
    hostApi = builder.HostEnvironment.BaseAddress;
    var dict = new Dictionary<string, string?> { { "HOSTAPI", hostApi } };
    builder.Configuration.AddInMemoryCollection(dict.ToArray());
}

builder.Services.AddKeyedScoped("db",(sp,_) => new HttpClient { BaseAddress = new Uri(hostApi) });

What about deploying the code to production ? Well, I think that is better to wrote yourself to wwwroot/appsettings.json and remove the data . But I will try to deploy and let you know….

Aspire , containers and dotnet watch

Aspire is the new visualizer – see https://github.com/dotnet/aspire

If you use dotnet run ( or Visual Studio)  with an Aspire host that instantiate some containers  , then , when you stop the project, the container is released.

But, if you use

dotnet watch run –nohotreload

then the containers are not  deleted. The nice solution is to investigate dotnet watch and Aspire . And maybe fill a bug.

The easy ? Delete the containers first !


void DeleteDockerContainers()
{
    var process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = "powershell.exe",
            Arguments = $$"""
-Command "docker rm -f $(docker ps -a -q)"
""",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true,
        }
    };
    process.Start();
    while (!process.StandardOutput.EndOfStream)
    {
        var line = process.StandardOutput.ReadLine();
        Console.WriteLine(line);
    }
}

Aspire, Sql Server Docker Container and multiple Connections strings

Aspire is the new visualizer – see https://github.com/dotnet/aspire

When creating a Docker container with Sql Server , the connection that is returned is without database – means that , usually, is connecting to the master.

That’s not that we usually want, so the following code is means that WebAPI will be connected to master

var builder = DistributedApplication.CreateBuilder(args);
var rb= builder.AddSqlServerContainer("Db2Gui", "<YourStrong@Passw0rd>");
builder.AddProject<Projects.ExampleWebAPI>(nameof(Projects.ExampleWebAPI))
   .WithReference(rb)
    ;

Instead , do what they do – but add the database

var builder = DistributedApplication.CreateBuilder(args);

var rb= builder.AddSqlServerContainer("Db2Gui", "<YourStrong@Passw0rd>");

builder.AddProject<Projects.ExampleWebAPI>(nameof(Projects.ExampleWebAPI))
    .WithEnvironment(ctx=>
    {
        var connectionStringName = $"ConnectionStrings__";
        var res=rb.Resource;
        var cn = res.GetConnectionString();
        ctx.EnvironmentVariables[connectionStringName+ "ApplicationDBContext"] = cn+ $";database=tests;";
        ctx.EnvironmentVariables[connectionStringName+ "NorthwindDBContext"] = cn + $";database=northwind;";
        ctx.EnvironmentVariables[connectionStringName+ "PubsDBContext"] = cn + $";database=pubs;";
    })
    //.WithReference(rb, "")
    ;

It is true that you can make the following :

builder.AddProject<Projects.ExampleWebAPI>(nameof(Projects.ExampleWebAPI))
    .WithReference(rb.AddDatabase("tests"), "ApplicationDBContext")
    .WithReference(rb.AddDatabase("northwind"), "NorthwindDBContext")
    .WithReference(rb.AddDatabase("pubs"), "PubsDBContext")
    .WithReference(rb.AddDatabase("NotCreated"), "NotCreated")

    ;

But it does not CREATE the database ( and it is a good thing …. EF EnsureCreated verifies JUST the existence of the database not of the tables within)
So thats why I prefer WithEnvironment rather than .WithReference(rb.AddDatabase

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.