<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>2024-11 on Funky Si's Test</title><link>https://blog-test.funkysi1701.com/2024/11/</link><description>Recent content in 2024-11 on Funky Si's Test</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><managingEditor>funkysi1701@gmail.com (Simon Foster)</managingEditor><webMaster>funkysi1701@gmail.com (Simon Foster)</webMaster><lastBuildDate>Mon, 25 Nov 2024 20:00:00 +0000</lastBuildDate><atom:link href="https://blog-test.funkysi1701.com/2024/11/index.xml" rel="self" type="application/rss+xml"/><item><title>Getting started with .Net Aspire</title><link>https://blog-test.funkysi1701.com/posts/2024/aspire/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 25 Nov 2024 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2024/aspire/</guid><category term="DotNet">DotNet</category><category term="Blazor">Blazor</category><category term="C-Sharp">C-Sharp</category><category term="VisualStudio">VisualStudio</category><category term="Aspire">Aspire</category><category term="OpenTelemetry">OpenTelemetry</category><category term=".NET9">.NET9</category><category term="Microsoft">Microsoft</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/aspire-ga-what-is-aspire.png"/><description>&lt;h2 id="what-is-net-aspire"&gt;What is .Net Aspire?&lt;a class="anchor ms-1" href="#what-is-net-aspire" aria-label="Permalink: What is .Net Aspire?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;.Net Aspire is a comprehensive set of tools, templates, and packages designed to simplify the development of cloud-native applications using .Net. It focuses on building observable, production-ready apps by providing a consistent and opinionated set of &lt;a href="https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview" target="_blank" rel="noopener noreferrer"&gt;tools and patterns&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;The key features of .Net Aspire:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Orchestration: Enhances the local development experience by simplifying the management of your app&amp;rsquo;s configuration and interconnections. It helps with app composition, service discovery, and connection string management.&lt;/li&gt;
&lt;li&gt;Integrations: Offers NuGet packages for commonly used services like Redis and Postgres, ensuring they connect consistently and seamlessly with your app.&lt;/li&gt;
&lt;li&gt;Tooling: Comes with project templates and tooling experiences for Visual Studio, Visual Studio Code, and the .Net CLI to help you create and interact with .Net Aspire projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall, &lt;a href="https://devblogs.microsoft.com/dotnet/introducing-dotnet-aspire-simplifying-cloud-native-development-with-dotnet-8/" target="_blank" rel="noopener noreferrer"&gt;.Net Aspire&lt;/a&gt;
aims to improve the experience of building .Net cloud-native apps by providing a robust framework for developing distributed applications.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Aspire" src="https://blog-test.funkysi1701.com/images/aspire-ga-what-is-aspire.png" loading="lazy"
width="1400" height="895"
/&gt;
&lt;/p&gt;
&lt;h2 id="getting-started-with-net-aspire"&gt;Getting started with .Net Aspire&lt;a class="anchor ms-1" href="#getting-started-with-net-aspire" aria-label="Permalink: Getting started with .Net Aspire"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I touched on .Net Aspire last week, when I talked about what was new in &lt;a href="https://blog-test.funkysi1701.com/posts/2024/dotnet9"&gt;dotnet 9&lt;/a&gt;
, but let&amp;rsquo;s walk through an example.&lt;/p&gt;
&lt;p&gt;Lets say you have a simple application. It has a Blazor web front end, it communicates with a .Net API and that API retrieves data from a SQL Server database. Before Aspire came along I would create a docker compose file and configure ports so the FE could call the API, and add connection strings so the API could access the database.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-docker-compose.yml" data-lang="docker-compose.yml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Api&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DOCKER_REGISTRY-}api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;12345&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;44338&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;443&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;networks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;my-network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;context&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dockerfile&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;API/Dockerfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;sqlserver&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;Ui&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DOCKER_REGISTRY-}ui&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ui&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;44330&lt;/span&gt;:&lt;span style="color:#ae81ff"&gt;443&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;networks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;my-network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;context&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dockerfile&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;UI/Dockerfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;APIPath=http://Api:80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sqlserver&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DOCKER_REGISTRY-}sql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;sqlvol:/var/opt/mssql&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;5432:1433&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;networks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;my-network&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;context&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;dockerfile&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Database/Dockerfile&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see from this docker compose file, there is a lot of specifying ports and other plumbing to get these three parts of my system to work together.&lt;/p&gt;
&lt;p&gt;Now in Visual Studio, right-click on the API project and select add &lt;strong&gt;.Net Aspire Orchestrator Support&lt;/strong&gt; this will add two new Visual Studio projects to the solution, AppHost and ServiceDefaults.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AppHost is where you configure what service depends on what, you can configure all sorts of different dependencies, like databases (sql server, mysql, postgres etc), rabbitmq, redis and many others.&lt;/li&gt;
&lt;li&gt;ServiceDefaults is where you configure the defaults for your services, like how opentelemetry should be configured, or how logging should work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now right click on the Blazor project and select the same option to get that wired up as well.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-program.cs" data-lang="program.cs"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; builder = DistributedApplication.CreateBuilder(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.AddProject&amp;lt;Projects.UI&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ui&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.AddProject&amp;lt;Projects.API&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;api&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.Build().Run();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Your Program.cs file inside your AppHost project will look something like this now, with both your API and UI/Blazor projects referenced.&lt;/p&gt;
&lt;p&gt;There is one more component we need to wire up, but we don&amp;rsquo;t have a project to right click on for the database. It is fairly straightforward to do, update it to look like the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-program.cs" data-lang="program.cs"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; builder = DistributedApplication.CreateBuilder(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; sqldb = builder.AddSqlServer(&lt;span style="color:#e6db74"&gt;&amp;#34;sql&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithDataVolume(&lt;span style="color:#e6db74"&gt;&amp;#34;sql-data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddDatabase(&lt;span style="color:#e6db74"&gt;&amp;#34;Context&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Project&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; api = builder.AddProject&amp;lt;Projects.API&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;api&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WaitFor(sqldb)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithReference(sqldb);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.AddProject&amp;lt;Projects.UI&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ui&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WaitFor(api)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithReference(api);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; builder.Build().RunAsync();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You also need to install a couple of nuget packages. &lt;strong&gt;Aspire.Hosting.SqlServer&lt;/strong&gt; and &lt;strong&gt;Aspire.Microsoft.EntityFrameworkCore.SqlServer&lt;/strong&gt; the second one is because my project is using Entity Framework. Lets look at what we have, we are defining a SQL Server called sql, with a data volume called sql-data, and a database called Project, which we can refer to as Context. We then configure API to reference the sql server we have just configured, and wait for sql server to be ready before starting the API. Next the Blazor project depends on the API and will wait for that to be ready before starting. Pretty powerful stuff.&lt;/p&gt;
&lt;p&gt;OK lets look at the API project, what do I need to configure in my connectionstrings? Not much, Aspire will fill all of this in for you.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-appsettings.json" data-lang="appsettings.json"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;ConnectionStrings&amp;#34;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;#34;Context&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In your API project, your Program.cs will need a nuget package &lt;strong&gt;Aspire.Microsoft.EntityFrameworkCore.SqlServer&lt;/strong&gt; and the following line, and no need for any pulling config and passing in connection strings.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-program.cs" data-lang="program.cs"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;builder.AddSqlServerDbContext&amp;lt;Context&amp;gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;Context&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One more clever thing we can do with Aspire is seed some data into my database before starting the project. Update the code that sets up your database in the AppHost project as follows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-program.cs" data-lang="program.cs"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; sqldb = builder.AddSqlServer(&lt;span style="color:#e6db74"&gt;&amp;#34;sql&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithBindMount(&lt;span style="color:#e6db74"&gt;&amp;#34;./sqlserverconfig&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/usr/config&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithBindMount(&lt;span style="color:#e6db74"&gt;&amp;#34;../API/data/sqlserver&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;/docker-entrypoint-initdb.d&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithEntrypoint(&lt;span style="color:#e6db74"&gt;&amp;#34;/usr/config/entrypoint.sh&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .WithDataVolume(&lt;span style="color:#e6db74"&gt;&amp;#34;sql-data&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .AddDatabase(&lt;span style="color:#e6db74"&gt;&amp;#34;Context&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;Project&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add a sqlserverconfig folder inside your AppHost project and add the following two files. I have found entrypoint.sh being a bit picky with its line endings (windows vs linux)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-entrypoint.sh" data-lang="entrypoint.sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Adapted from: https://github.com/microsoft/mssql-docker/blob/80e2a51d0eb1693f2de014fb26d4a414f5a5add5/linux/preview/examples/mssql-customize/entrypoint.sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start the script to create the DB and user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/usr/config/configure-db.sh &amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Start SQL Server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;/opt/mssql/bin/sqlservr
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-configure-db.sh" data-lang="configure-db.sh"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# set -x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Adapted from: https://github.com/microsoft/mssql-docker/blob/80e2a51d0eb1693f2de014fb26d4a414f5a5add5/linux/preview/examples/mssql-customize/configure-db.sh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Wait 60 seconds for SQL Server to start up by ensuring that&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# calling SQLCMD does not return an error code, which will ensure that sqlcmd is accessible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# and that system and user databases return &amp;#34;0&amp;#34; which means all databases are in an &amp;#34;online&amp;#34; state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-2017&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;dbstatus&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;errcode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;start_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$SECONDS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;end_by&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$((&lt;/span&gt;start_time &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;60&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Starting check for SQL Server start-up at &lt;/span&gt;$start_time&lt;span style="color:#e6db74"&gt;, will end at &lt;/span&gt;$end_by&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $SECONDS -lt $end_by &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt; $errcode -ne &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt; -z &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$dbstatus&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; $dbstatus -ne &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; dbstatus&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;/opt/mssql-tools18/bin/sqlcmd -h -1 -t &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; -U sa -P &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$MSSQL_SA_PASSWORD&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -C -Q &lt;span style="color:#e6db74"&gt;&amp;#34;SET NOCOUNT ON; Select SUM(state) from sys.databases&amp;#34;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; errcode&lt;span style="color:#f92672"&gt;=&lt;/span&gt;$?
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; sleep &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;elapsed_time&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$((&lt;/span&gt;SECONDS &lt;span style="color:#f92672"&gt;-&lt;/span&gt; start_time&lt;span style="color:#66d9ef"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;echo &lt;span style="color:#e6db74"&gt;&amp;#34;Stopped checking for SQL Server start-up after &lt;/span&gt;$elapsed_time&lt;span style="color:#e6db74"&gt; seconds (dbstatus=&lt;/span&gt;$dbstatus&lt;span style="color:#e6db74"&gt;,errcode=&lt;/span&gt;$errcode&lt;span style="color:#e6db74"&gt;,seconds=&lt;/span&gt;$SECONDS&lt;span style="color:#e6db74"&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $dbstatus -ne &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;]]&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; &lt;span style="color:#f92672"&gt;[[&lt;/span&gt; $errcode -ne &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;]]&lt;/span&gt;; &lt;span style="color:#66d9ef"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;SQL Server took more than 60 seconds to start up or one or more databases are not in an ONLINE state&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;dbstatus = &lt;/span&gt;$dbstatus&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;errcode = &lt;/span&gt;$errcode&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; exit &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# Loop through the .sql files in the /docker-entrypoint-initdb.d and execute them with sqlcmd&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; f in /docker-entrypoint-initdb.d/*.sql
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; echo &lt;span style="color:#e6db74"&gt;&amp;#34;Processing &lt;/span&gt;$f&lt;span style="color:#e6db74"&gt; file...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$MSSQL_SA_PASSWORD&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt; -C -d master -i &lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;$f&lt;span style="color:#e6db74"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The second BindMount line mounts a folder inside your API project, so add a data folder with a subfolder called sqlserver. Inside that add a sql script called init.sql. Put all your CREATE DATABASE and CREATE TABLES sql commands inside this. And if everything works you will have a seeded DB ready to test your application with.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is just a few things I have done with Aspire. Go check out the docs on &lt;a href="https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview" target="_blank" rel="noopener noreferrer"&gt;MS learn&lt;/a&gt;
or the some of the sessions from &lt;a href="https://www.youtube.com/watch?v=fiePiEc1qcU&amp;amp;list=PLdo4fOcmZ0oXeSG8BgCVru3zQtw_K4ANY&amp;amp;index=2" target="_blank" rel="noopener noreferrer"&gt;dotnet conf&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Version 9 of .Net is here</title><link>https://blog-test.funkysi1701.com/posts/2024/dotnet9/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 18 Nov 2024 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2024/dotnet9/</guid><category term="DotNet">DotNet</category><category term="Blazor">Blazor</category><category term="EFCore">EFCore</category><category term="C-Sharp">C-Sharp</category><category term="VisualStudio">VisualStudio</category><category term="Aspire">Aspire</category><category term="AI">AI</category><category term="OpenTelemetry">OpenTelemetry</category><category term=".NET9">.NET9</category><category term="Microsoft">Microsoft</category><media:content medium="image" type="image/png" url="https://blog-test.funkysi1701.com/images/bot-01.png"/><description>&lt;p&gt;Every November it is like Christmas for .NET developers, as Microsoft releases the next version of .NET. This year is no different, and we have version 9 of .NET to play with. This release is packed with new features and improvements across the board.&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t already head on over to the &lt;a href="https://dotnet.microsoft.com/download/dotnet/9.0" target="_blank" rel="noopener noreferrer"&gt;dotnet website&lt;/a&gt;
and download the latest version.&lt;/p&gt;
&lt;p&gt;Also we get a brand new version of Visual Studio, which is always a good thing, so head on over to the Visual Studio &lt;a href="https://visualstudio.microsoft.com/downloads/" target="_blank" rel="noopener noreferrer"&gt;website&lt;/a&gt;
and download the latest version (or the Preview version if you want to test what is coming out next).&lt;/p&gt;
&lt;p&gt;Back when .Net 7 came out I wrote a &lt;a href="https://blog-test.funkysi1701.com/posts/2022/dotnet7/"&gt;post&lt;/a&gt;
about what you needed to fix to get the latest version working with your existing code. However this time around the upgrade is really smooth.&lt;/p&gt;
&lt;h2 id="nuget-audit"&gt;NuGet Audit&lt;a class="anchor ms-1" href="#nuget-audit" aria-label="Permalink: NuGet Audit"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Back in .Net 8 NuGet Audit was introduced which told you if any of your packages had security vulnerabilities. This has been improved in .Net 9, and now defaults to tell you about transitive dependencies. This is a great feature, but if you would prefer to keep .Net 8&amp;rsquo;s functionality you can add the following to your project (*.csproj) file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;NuGetAuditMode&amp;gt;&lt;/span&gt;direct&lt;span style="color:#f92672"&gt;&amp;lt;/NuGetAuditMode&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="net-aspire"&gt;.Net Aspire&lt;a class="anchor ms-1" href="#net-aspire" aria-label="Permalink: .Net Aspire"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Released just after .Net 8 .Net Aspire is a suite of tools to help develop microservices. Gone are the days of specifying ports and connection strings for your services, Aspire can handle this all programmatically.&lt;/p&gt;
&lt;p&gt;Aspire adds two new projects to your solution. AppHost and ServiceDefaults.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AppHost is where you configure what service depends on what, you can configure all sorts of different dependencies, like databases (sql server, mysql, postgres etc), rabbitmq, redis and many others. It is open source so the community are busy adding everything you could possibly need.&lt;/li&gt;
&lt;li&gt;ServiceDefaults is where you configure the defaults for your services, like how opentelemetry should be configured, or how logging should work. Microsoft have thought hard about this and come up with some opinionated defaults, but you can change these to suit your needs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Starting the AppHost project will start up the Aspire Dashboard where you can start/stop containers, view logs and see the health of your services. This is primarily a devlopment tool, but there are some deployment tools, however I have not explored these much yet. More details about Aspire can be found &lt;a href="https://learn.microsoft.com/en-us/dotnet/aspire/get-started/aspire-overview" target="_blank" rel="noopener noreferrer"&gt;here&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="blazor"&gt;Blazor&lt;a class="anchor ms-1" href="#blazor" aria-label="Permalink: Blazor"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have been using Blazor since the first previews in the .Net 3.1 days. It has come a long way since then, and now with .Net 9 it is even better.&lt;/p&gt;
&lt;p&gt;There has been some optimization of the delivery of static assets. To take advantage of this improvement, replace the following line in your Program.cs file.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app.MapStaticAssets(); &lt;span style="color:#75715e"&gt;//Add this line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; app.UseStaticFiles(); &lt;span style="color:#75715e"&gt;//Remove this line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;.Net 9 will then cache your static assets ang give them a unique filename. This will allow the browser to cache the files for longer, and only download them when they have changed. This will speed up your site and reduce the amount of data transferred.&lt;/p&gt;
&lt;p&gt;In your razor pages use code similar to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;@Assets[&amp;#34;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bootstrap&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;bootstrap&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;min&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;css&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;]&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;@Assets[&amp;#34;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;css&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;]&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;&lt;span style="color:#f92672"&gt;link&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;rel&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;stylesheet&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;href&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;@Assets[&amp;#34;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;BlazorSample&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;styles&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;.&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;css&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;&amp;#34;]&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="ai"&gt;AI&lt;a class="anchor ms-1" href="#ai" aria-label="Permalink: AI"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It will have not escaped your notice that AI is everywhere, and it is no different with .Net. I saw some very impressive demos at the &lt;a href="https://www.dotnetconf.net/" target="_blank" rel="noopener noreferrer"&gt;.Net Conf&lt;/a&gt;
online conference. I encourage you to check our the videos. But to summarize Microsoft have added a bunch of abstractions to make it easier to write code to talk to the different AI models, I haven&amp;rsquo;t played about with AI much yet, but I am tempted to give it a go.&lt;/p&gt;
&lt;h2 id="sql-management-studio"&gt;SQL Management Studio&lt;a class="anchor ms-1" href="#sql-management-studio" aria-label="Permalink: SQL Management Studio"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have not used SQL Management Studio for a while as I have trying out Azure Data Studio. However a new Preview of SQL Server Management Studio is now &lt;a href="https://learn.microsoft.com/en-us/ssms/ssms-21/release-notes-21?view=sql-server-ver16" target="_blank" rel="noopener noreferrer"&gt;avaliable&lt;/a&gt;
. This version is 64bit and is based on Visual Studio engine, it even shares the same installer.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is only a small taste of the new features in .Net 9. Go check out .Net Conf to learn more or check out some of the links I have shared above.&lt;/p&gt;</description></item><item><title>Strategy Design Pattern</title><link>https://blog-test.funkysi1701.com/posts/2024/strategy-pattern/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Mon, 11 Nov 2024 20:00:00 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2024/strategy-pattern/</guid><category term="DesignPatterns">DesignPatterns</category><category term="Architecture">Architecture</category><category term="C-Sharp">C-Sharp</category><media:content medium="image" type="image/jpeg" url="https://blog-test.funkysi1701.com/images/flying-machine-blueprint-patent-john-malone.jpg"/><description>&lt;h2 id="understanding-the-strategy-design-pattern"&gt;Understanding the Strategy Design Pattern.&lt;a class="anchor ms-1" href="#understanding-the-strategy-design-pattern" aria-label="Permalink: Understanding the Strategy Design Pattern."&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the world of software development, design patterns are essential tools that help developers solve common problems in a standardized way. One such pattern is the &lt;strong&gt;Strategy Design Pattern&lt;/strong&gt;. This pattern is particularly useful when you need to define a family of algorithms, encapsulate each one, and make them interchangeable. Let&amp;rsquo;s dive into what the Strategy Design Pattern is, why it&amp;rsquo;s useful, and how you can implement it in your projects.&lt;/p&gt;
&lt;h3 id="what-is-the-strategy-design-pattern"&gt;What is the Strategy Design Pattern?&lt;a class="anchor ms-1" href="#what-is-the-strategy-design-pattern" aria-label="Permalink: What is the Strategy Design Pattern?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Strategy Design Pattern falls under the category of behavioural design patterns. It enables an algorithm&amp;rsquo;s behaviour to be selected at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.&lt;/p&gt;
&lt;h3 id="why-use-the-strategy-design-pattern"&gt;Why Use the Strategy Design Pattern?&lt;a class="anchor ms-1" href="#why-use-the-strategy-design-pattern" aria-label="Permalink: Why Use the Strategy Design Pattern?"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The primary benefits of using the Strategy Design Pattern include:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: It allows you to change the algorithm or strategy being used without altering the code that uses the algorithm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reusability&lt;/strong&gt;: By encapsulating algorithms separately, you can reuse them across different parts of your application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: It promotes cleaner code by adhering to the Single Responsibility Principle, making your code easier to maintain and extend.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="how-to-implement-the-strategy-design-pattern"&gt;How to Implement the Strategy Design Pattern&lt;a class="anchor ms-1" href="#how-to-implement-the-strategy-design-pattern" aria-label="Permalink: How to Implement the Strategy Design Pattern"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s break down the implementation of the Strategy Design Pattern with a simple example. Suppose we are developing a flight simulator that supports multiple flying methods (e.g., Flapping like a bird, Jet Engine powered, and Warp Speed).&lt;/p&gt;
&lt;h4 id="step-1-define-the-strategy-interface"&gt;Step 1: Define the Strategy Interface&lt;a class="anchor ms-1" href="#step-1-define-the-strategy-interface" aria-label="Permalink: Step 1: Define the Strategy Interface"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;First, we define an interface that all payment strategies will implement.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;interface&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;IFlyingStrategy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Fly();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-2-implement-concrete-strategies"&gt;Step 2: Implement Concrete Strategies&lt;a class="anchor ms-1" href="#step-2-implement-concrete-strategies" aria-label="Permalink: Step 2: Implement Concrete Strategies"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Next, we create concrete classes that implement the IPaymentStrategy interface.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Bird&lt;/span&gt; : IFlyingStrategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Fly()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Flying like a bird&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Plane&lt;/span&gt; : IFlyingStrategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Fly()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Flying using 21st century aviation fuel&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;StarShip&lt;/span&gt; : IFlyingStrategy
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Fly()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Console.WriteLine(&lt;span style="color:#e6db74"&gt;&amp;#34;Flying using warp engines&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-3-create-the-context-class"&gt;Step 3: Create the Context Class&lt;a class="anchor ms-1" href="#step-3-create-the-context-class" aria-label="Permalink: Step 3: Create the Context Class"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;The context class uses a IFlyingStrategy to perform the payment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;FlyContext&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; IFlyingStrategy _flyingStrategy;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; SetPaymentStrategy(IFlyingStrategy flyingStrategy)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _flyingStrategy = flyingStrategy;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Fly()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; _flyingStrategy.Fly();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-4-use-the-strategy-pattern"&gt;Step 4: Use the Strategy Pattern&lt;a class="anchor ms-1" href="#step-4-use-the-strategy-pattern" aria-label="Permalink: Step 4: Use the Strategy Pattern"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Finally, we use the FlyContext to fly with different strategies.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Program&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;static&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; Main(&lt;span style="color:#66d9ef"&gt;string&lt;/span&gt;[] args)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; FlyContext context = &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; FlyContext();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.SetPaymentStrategy(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; StarShip());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.Fly();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.SetPaymentStrategy(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Plane());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.Fly();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.SetPaymentStrategy(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Bird());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; context.Fly();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="conclusion"&gt;Conclusion&lt;a class="anchor ms-1" href="#conclusion" aria-label="Permalink: Conclusion"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Strategy Design Pattern is a powerful tool that promotes flexibility, reusability, and maintainability in your code. By encapsulating algorithms and making them interchangeable, you can easily extend and modify your application without disrupting existing functionality. Whether you’re dealing with payment processing, flying machines, sorting algorithms, or any other scenario requiring dynamic behaviour, the Strategy Design Pattern can help you write cleaner and more efficient code.&lt;/p&gt;</description></item><item><title>How to start a code club for kids</title><link>https://blog-test.funkysi1701.com/posts/2024/codeclub/</link><author>funkysi1701@gmail.com (funkysi1701)</author><pubDate>Sat, 02 Nov 2024 18:00:45 +0000</pubDate><guid>https://blog-test.funkysi1701.com/posts/2024/codeclub/</guid><category term="youth">youth</category><category term="codeclub">codeclub</category><category term="Community">Community</category><media:content medium="image" type="image/jpeg" url="https://blog-test.funkysi1701.com/images/Pnb-NvNJ_400x400.jpg"/><description>&lt;p&gt;Code Clubs are free, welcoming spaces designed to introduce young people to the exciting world of programming and digital skills. Today, I had the pleasure of taking my son—an absolute coding enthusiast—to one of these sessions, held at Leeds Central Library.&lt;/p&gt;
&lt;p&gt;The club was hosted in a cozy room on the top floor of the library. Walking in, I expected rows of computers set up for traditional coding exercises. Instead, we found mysterious white lines taped onto the floor. Curious to find out what they were for, we soon learned they were meant to guide robots that the children would be programming. The instructor handed out iPads and small spherical robots known as Spheros, and the children were tasked with programming the robots to follow the lines.&lt;/p&gt;
&lt;p&gt;The iPads were preloaded with easy-to-use software that felt familiar to those who&amp;rsquo;ve used Scratch, a popular block-based coding language. By simply dragging and dropping blocks of code, the kids controlled the robots’ movements. Each &amp;ldquo;move&amp;rdquo; block had three variables—direction, speed, and duration—that the children could adjust to guide the robot along the lines.&lt;/p&gt;
&lt;p&gt;It was a great hands-on learning experience. My son and I faced a bit of trial and error to figure out which way the robot saw as &amp;ldquo;forward,&amp;rdquo; but soon enough, our Sphero was gliding smoothly along the first line. As we went along, we added &amp;ldquo;pause&amp;rdquo; blocks between movements, which made the robot stop before changing direction, adding a nice rhythm to its journey along the lines.&lt;/p&gt;
&lt;p&gt;
&lt;img class="img-fluid" alt="Children programming Sphero robots to follow taped lines on the floor at Leeds Central Library Code Club" src="https://blog-test.funkysi1701.com/images/20241102_104220.jpg" loading="lazy"
width="854" height="384"
/&gt;
&lt;/p&gt;
&lt;p&gt;Once the main task was completed, there was time for the kids to explore other features. We experimented with different commands, making a smile or frown appear on the robot’s LED display, while others programmed their Spheros to zip around the room, flashing lights and making playful noises.&lt;/p&gt;
&lt;p&gt;The club meets every two weeks, and both my son and I left feeling thrilled with the experience. We’re already looking forward to the next session!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in finding a Code Club near you check out &lt;a href="https://codeclub.org/en/find" target="_blank" rel="noopener noreferrer"&gt;https://codeclub.org/en/find&lt;/a&gt;
, alternatively, &lt;a href="https://codeclub.org" target="_blank" rel="noopener noreferrer"&gt;https://codeclub.org&lt;/a&gt;
has lots of resources to explain what code clubs are all about.&lt;/p&gt;</description></item></channel></rss>