[2023] Sites
Those are the sites mosr visited –data obtained from https://takeout.google.com/?pli=1
Those are the sites mosr visited –data obtained from https://takeout.google.com/?pli=1
Layoffs in IT | https:/www.cnbc.com/2023/01/20/google-to-lay-off-12000-people-memo-from-ceo-sundar-pichai-says.html |
TypeScript 5.x | https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html |
Angular v1x | https://angular.dev/ |
CHAT GPT and others | https://chat.openai.com/ |
No new VS for MAC | https://devblogs.microsoft.com/visualstudio/visual-studio-for-mac-retirement-announcement/ |
VSCODE C# DevKit | https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit |
MSFT OpenJDK21 | https://devblogs.microsoft.com/java/announcing-microsoft-build-of-openjdk-21/ |
General Motors API for Cars | https://www.theverge.com/2023/10/12/23914060/gm-uservices-api-software-apps-car-sdv |
.NET 8 | https://learn.microsoft.com/ro-ro/dotnet/core/whats-new/dotnet-8 |
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
Core8: https://ignatandrei.github.io/Presentations/Net8WhatsNewprez.html#1
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
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/
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
}
}
}
}}
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
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 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
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 => { 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 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 –no–hot–reload
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 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
You can find the presentation about .NET 8 at https://ignatandrei.github.io/Presentations/Net8WhatsNewprez.html#1 . Also, the code is at https://ignatandrei.github.io/Presentations/Net8WhatsNew.zip