<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: .NET</title>
    <description>The latest articles on DEV Community by .NET (@dotnet).</description>
    <link>https://dev.to/dotnet</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F965%2F34c9d14a-16d0-4ab1-9dca-1c75e6b627f7.png</url>
      <title>DEV Community: .NET</title>
      <link>https://dev.to/dotnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dotnet"/>
    <language>en</language>
    <item>
      <title>Making AI smarter with an MCP server that manages short URLs</title>
      <dc:creator>Frank Boucher ☁</dc:creator>
      <pubDate>Tue, 15 Apr 2025 14:09:00 +0000</pubDate>
      <link>https://dev.to/dotnet/making-ai-smarter-with-an-mcp-server-that-manages-short-urls-4kd4</link>
      <guid>https://dev.to/dotnet/making-ai-smarter-with-an-mcp-server-that-manages-short-urls-4kd4</guid>
      <description>&lt;p&gt;Have you ever wanted to give your AI assistants access to your own custom tools and data? That's exactly what Model Context Protocol (MCP) allows us to do, and I've been experimenting with it lately.&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://www.cloudenfrancais.com/posts/2025-04-15-serveur-mcp-urls-courtes.html" rel="noopener noreferrer"&gt;&lt;em&gt;Version française ici&lt;/em&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;I read a lot recently about Model Context Protocol (MCP) and how it is changing the way AI interacts with external systems. I was curious to see how it works and how I can use it in my own projects. There are many tutorial available online but one of my favorite was written by James Montemagno &lt;a href="https://dev.to/dotnetblogger/build-a-model-context-protocol-mcp-server-in-c-5gn8-temp-slug-4803311"&gt;Build a Model Context Protocol (MCP) server in C#&lt;/a&gt;. This post isn't a tutorial, but rather a summary of my experience and what I learned along the way while building a real MCP server that manages short URLs.&lt;/p&gt;

&lt;p&gt;MCP doesn't change AI itself, it's a protocol that helps your AI model to interact with external resources: API, databases, etc. The protocol simplifies the way AI can access an external system, and it allows the AI to discover the available tools from those resources. Recently I was working on a project that manages short URLs, and I thought it would be a great opportunity to build an MCP server that manages short URLs. I wanted to see how easy it is to build and then use it in VSCode with GitHub Copilot Chat.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Code: All the code of this post is available in the branch &lt;strong&gt;exp/mcp-server&lt;/strong&gt; of the &lt;a href="https://github.com/microsoft/AzUrlShortener/tree/exp/mcp-server" rel="noopener noreferrer"&gt;AzUrlShortener&lt;/a&gt; repo on GitHub.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setting Up: Adding an MCP Server to a .NET Aspire Solution
&lt;/h2&gt;

&lt;p&gt;The AzUrlShortener is a web solution that uses .NET Aspire, so the first thing I did was create a new project using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="n"&gt;Cloud5mins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShortenerTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MCPServer&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="p"&gt;./&lt;/span&gt;&lt;span class="n"&gt;mcpserver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Required Dependencies
&lt;/h3&gt;

&lt;p&gt;To transform this into an MCP server, I added these essential NuGet packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Microsoft.Extensions.Hosting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ModelContextProtocol.AspNetCore&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since this project is part of a .NET Aspire solution, I also added references to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;ServiceDefaults&lt;/code&gt; project (for consistent service configuration)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ShortenerTools.Core&lt;/code&gt; project (where the business logic lives)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Integrating with Aspire
&lt;/h3&gt;

&lt;p&gt;Next, I needed to integrate the MCP server into the &lt;code&gt;AppHost&lt;/code&gt; project, which defines all services in our solution. Here's how I added it to the existing services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;manAPI&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddProject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cloud5mins_ShortenerTools_Api&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strTables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WaitFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strTables&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CustomDomain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;customDomain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DefaultRedirectUrl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;defaultRedirectUrl&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddProject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cloud5mins_ShortenerTools_TinyBlazorAdmin&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithExternalHttpEndpoints&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manAPI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 👇👇👇 new code for MCP Server&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddProject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Projects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cloud5mins_ShortenerTools_MCPServer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;manAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithExternalHttpEndpoints&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how I added the MCP server with a reference to the &lt;code&gt;manAPI&lt;/code&gt; - this is crucial as it needs access to the URL management API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring the MCP Server
&lt;/h3&gt;

&lt;p&gt;To complete the setup, I needed to configure the dependency injection in the &lt;code&gt;program.cs&lt;/code&gt; file of the MCPServer project. The key part was specifying the BaseAddress of the httpClient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddConsole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consoleLogOptions&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Configure all logs to go to stderr&lt;/span&gt;
    &lt;span class="n"&gt;consoleLogOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LogToStandardErrorThreshold&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddMcpServer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithTools&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UrlShortenerTool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddServiceDefaults&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UrlManagerClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https+http://api"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapMcp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's all that was needed! Thanks to .NET Aspire, integrating the MCP server was straightforward. When you run the solution, the MCP server starts alongside other projects and will be available at &lt;code&gt;http://localhost:{some port}/sse&lt;/code&gt;. The &lt;code&gt;/sse&lt;/code&gt; part of the endpoint means (Server-Sent Events) and is critical - it's the URL that AI assistants will use to discover available tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the MCP Server Tools
&lt;/h2&gt;

&lt;p&gt;Looking at the code above, two key lines make everything work:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;builder.Services.AddMcpServer().WithTools&amp;lt;UrlShortenerTool&amp;gt;();&lt;/code&gt; - registers the MCP server and specifies which tools will be available&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app.MapMcp();&lt;/code&gt; - maps the MCP server to the ASP.NET Core pipeline&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Defining Tools with Attributes
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;UrlShortenerTool&lt;/code&gt; class contains all the methods that will be exposed to AI assistants. Let's examine the &lt;code&gt;ListUrl&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;McpServerTool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Provide a list of all short URLs."&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShortUrlEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ListUrl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;urlList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_urlManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetUrls&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShortUrlEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;urlList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[McpServerTool]&lt;/code&gt; attribute marks this method as a tool the AI can use. I prefer keeping tool definitions simple, delegating the actual implementation to the &lt;code&gt;UrlManager&lt;/code&gt; class that's injected in the constructor: &lt;code&gt;UrlShortenerTool(UrlManagerClient urlManager)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The URL Manager Client
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;UrlManagerClient&lt;/code&gt; follows standard HttpClient patterns. It receives the pre-configured httpClient in its constructor and uses it to communicate with the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UrlManagerClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShortUrlEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;?&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetUrls&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShortUrlEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;urlList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/UrlList"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadFromJsonAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ListResponse&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
                &lt;span class="n"&gt;urlList&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;!.&lt;/span&gt;&lt;span class="n"&gt;UrlList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ShortUrlEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;urlList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// other methods to manage short URLs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation of concerns keeps the code clean - tools handle the MCP interface, while the client handles the API communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the MCP Server with GitHub Copilot Chat
&lt;/h2&gt;

&lt;p&gt;Now for the exciting part - connecting your MCP server to GitHub Copilot Chat! This is where you'll see your custom tools in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring Copilot to Use Your MCP Server
&lt;/h3&gt;

&lt;p&gt;Once the server is running (either deployed in Azure or locally), follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open GitHub Copilot Chat in VS Code&lt;/li&gt;
&lt;li&gt;Change the mode to &lt;strong&gt;Agent&lt;/strong&gt; by clicking the dropdown in the chat panel&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Select Tools...&lt;/strong&gt; button, then &lt;strong&gt;Add More Tools&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Qp9TbTXCdBDEiFUidVFbh-VBvgVSHXVRbCrOLDI5StV9XJN_9nuJjesZHxLL-dPn2NC3L9VJ_3fFru5n69CRqBuEAu8CQ-y-uWbqqG5744tyX0DJrSootnqI_3-rVOH_QXeCas9xQBbkdxMWqPSdSKSNiaO3wEtJ1fXst9f2UK597RONeFE95Kv7-6g/s495/set-agent-mode.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fux2y5o1xpczfje43fjyk.png" alt="Set GitHub Copilot mode to Agent" width="400" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Selecting the Connection Type
&lt;/h3&gt;

&lt;p&gt;GitHub Copilot supports several ways to connect to MCP servers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhglvHm1tjbE4qxYRVT1xHaOBI43qW-SoZL4_rMKOPtcxmhxSpo3Grf8Mn-byUeLuLiGq8uzPjogrdgMoQ9LMTRMCiFDWbLsfNLR_plTRtxNEUghk_qWR0VEmaN1SsF4O8EoJU8cxWnrkVRxxPqNjuxLeTwcBXcxXFoo9PcJdEGqRmSF3hvFUDVY_-xd3Q/s818/select-mcp-type.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbnujbhmtf9pkfnfrfz55.png" alt="All MCP Server types" width="398" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are multiple options available - you could have your server in a container or run it via command line. For our scenario, we'll use HTTP.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; At the time of writing this post, I needed to use the HTTP URL of the MCP server rather than HTTPS. You can get this URL from the Aspire dashboard by clicking on the resource and checking the available &lt;strong&gt;Endpoints&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After selecting your connection type, Copilot will display the configuration file, which you can modify anytime.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm8HbdxOKFmHto8WY5NWTacMG8VcF4d2BFAV5ebESNpN9ngKEXDpCTk_XaOGJRMR_ODwTBgwy0Q-R56FmriEncYFkO3obqwt6h1Dr_upzfKYc-aJjo-NgEgavpJa37EuPJ4GAZwbnuitzUhti-5_Dz9XzI-ohOSBuBXY33BLbKCIi2K4kQZGHxpg0pU2A/s643/mcp-config.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fro1ll6vy04oarbgfg6rk.png" alt="GitHub Copilot Chat Configuration" width="399" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interacting with Your Custom Tools
&lt;/h3&gt;

&lt;p&gt;Now comes the fun part! You can interact with your MCP server in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Natural language queries&lt;/strong&gt; : Ask questions like "How many short URLs do I have?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct tool references&lt;/strong&gt; : Use the pound sign to call specific tools: "With #azShortURL list all URLs"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;azShortURL&lt;/code&gt; is the name we gave to our MCP server in the configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh87qIHmGma4cVHuGXA3jtt1lvZz4xxmd2JyB8hVtMAyK6PboHkIPrdoMO_rv1Qvy62d1u73sn2fdy9_O3L16Pv-cvnc-Ya8zn_7bsBB7OaqPq0F6V6FjQYcIbwtQ3JLNoOaL6-80lTAElL1Xv1AIheJJt_vn4QRPw_qyURT6OHpX2uHtWULuwkNj0DpbY/s1032/chat-example.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdwjfjoz8t00nn00whpke.png" alt="GitHub Copilot question and response example" width="261" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learnings and Future Directions
&lt;/h2&gt;

&lt;p&gt;Building this MCP server for AzUrlShortener taught me several valuable lessons:&lt;/p&gt;

&lt;h3&gt;
  
  
  What Worked Well
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Integration with .NET Aspire was remarkably straightforward&lt;/li&gt;
&lt;li&gt;The attribute-based approach to defining tools is clean and intuitive&lt;/li&gt;
&lt;li&gt;The separation of tool definitions from implementation logic keeps the code maintainable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Challenges and Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href="https://github.com/modelcontextprotocol/csharp-sdk" rel="noopener noreferrer"&gt;csharp-SDK&lt;/a&gt; is only a few weeks old and still in preview&lt;/li&gt;
&lt;li&gt;OAuth authentication isn't defined yet (though it's being actively worked on)&lt;/li&gt;
&lt;li&gt;Documentation is present but evolving rapidly as the technology matures, so some features may not be fully documented yet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the AzUrlShortener project specifically, I'm keeping this MCP server implementation in the experimental branch &lt;code&gt;mcp-server&lt;/code&gt; until I can properly secure it. However, I'm already envisioning numerous other scenarios where MCP servers could add great value.&lt;/p&gt;

&lt;p&gt;If you're interested in exploring this technology, I encourage you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check out the &lt;a href="https://github.com/microsoft/AzUrlShortener/tree/exp/mcp-server" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fork it and create your own MCP server&lt;/li&gt;
&lt;li&gt;Experiment with different tools and capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Join the Community
&lt;/h3&gt;

&lt;p&gt;If you have questions or want to share your experiences with others, I invite you to join the Azure AI Community Discord server:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://discord.gg/kzRShWzttr" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foacup3hf849lseud9qk4.png" alt="Join the AI Community Discord" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The MCP ecosystem is growing rapidly, and it's an exciting time to be part of this community!&lt;/p&gt;

&lt;p&gt;~Frank&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aspire</category>
      <category>dotnet</category>
      <category>mcp</category>
    </item>
    <item>
      <title>.NET Updates February 2025 - .NET 10 Preview, Visual Studio 2022 v17.13, Gen AI for Beginners and more!</title>
      <dc:creator>Frank Boucher ☁</dc:creator>
      <pubDate>Mon, 03 Mar 2025 22:11:21 +0000</pubDate>
      <link>https://dev.to/dotnet/net-updates-february-2025-net-10-preview-visual-studio-2022-v1713-gen-ai-for-beginners-and-438p</link>
      <guid>https://dev.to/dotnet/net-updates-february-2025-net-10-preview-visual-studio-2022-v1713-gen-ai-for-beginners-and-438p</guid>
      <description>&lt;p&gt;This month, Jon Galloway and Frank Boucher bring us the latest updates in the .NET world! In their February .NET news video, they cover exciting developments, including the release of Visual Studio 2022 v17.13, improvements in .NET 9 networking, new features for enhanced Razor productivity, and much more. &lt;br&gt;
This blog post contains all the links mentioned in the video, so you can dive deeper into each topic and explore the community's insights. Enjoy!&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/0QvPmz4GY-s"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;h2&gt;
  
  
  Links shared during the video
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-v17-13-is-now-available/" rel="noopener noreferrer"&gt;Visual Studio 2022 v17.13 is Now Available!&lt;/a&gt;&lt;/strong&gt; (Mads Kristensen) - Many new features related to productivity, who doesn't love that? There are more with Copilot, Debugging &amp;amp; diagnostics, Git tooling, and more!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/csharp-on-visual-studio-code-just-got-better-with-enhancements-to-csharp-dev-kit/" rel="noopener noreferrer"&gt;C# Dev Kit Updates: .NET Aspire, Hot Reload, and More!&lt;/a&gt;&lt;/strong&gt; (Wendy Breiding (SHE/HER)) - Our beloved C# Dev Kit extension for VSCode just got even better! It can now support projects wihthout a csproj. There are debugging, testing enhancements, and now you can add .NET Aspire Orchestration to your solution with one click. The post has a video where Katie Savage shows all the new features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-9-networking-improvements/" rel="noopener noreferrer"&gt;.NET 9 Networking Improvements&lt;/a&gt;&lt;/strong&gt; (Máňa, Natalia, Anton) - Everyone will benefit from the improvements, but if you want to know all the details, this post goes in-depth on all the new features and improvements in .NET 9 related to networking.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-9-performance-improvements-in-dotnet-maui/" rel="noopener noreferrer"&gt;.NET MAUI Performance Features in .NET 9&lt;/a&gt;&lt;/strong&gt; (Jonathan, Simon) - This post goes over the improvements iving some comparisons before and after. Really interesting to see the impact of the changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/enhancing-razor-productivity-with-new-features/" rel="noopener noreferrer"&gt;New Features for Enhanced Razor Productivity&lt;/a&gt;&lt;/strong&gt; (Leslie Richardson) - I love the new "Extract to Component" feature, it will save me so much time. There is also some pretty amazing work done around the Roslyn C# Tokenizer. A must read for Web developers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-10-preview-1/" rel="noopener noreferrer"&gt;.NET 10 Preview 1&lt;/a&gt;&lt;/strong&gt; (.NET Team) - This is it! This is a great post that goes over the version Preview. There also a great 75-minutes &lt;a href="https://www.youtube.com/watch?v=VncMk8ryxV8" rel="noopener noreferrer"&gt;unboxing video: .NET Previews Unboxed - .NET 10 Preview 1, C# 14, HybridCache, &amp;amp; More&lt;/a&gt; with all the team.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-aspire-9-1/" rel="noopener noreferrer"&gt;.NET Aspire 9.1&lt;/a&gt;&lt;/strong&gt; (Maddy Montaquila) - Our dashboard got a new version! Clearer UI with grouping resources, different themes, Localization, improvement in the logs management, and more! To get all that goodness, we only have to change the version to 9.1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://aka.ms/genainet/blog" rel="noopener noreferrer"&gt;Announcing Generative AI for Beginners – .NET&lt;/a&gt;&lt;/strong&gt; (Pablo Lopes) - This post announces the perfect course to get started with Generative AI. It's only 5 short lessons, it is a free course, and material is available in multiple languages: Chinese (Simplified), Chinese (Traditional), French, Japanese, Korean, Portuguese, Spanish, and German. There is a &lt;a href="https://aka.ms/genainet/discord" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;, jump in!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Share Your Thoughts
&lt;/h2&gt;

&lt;p&gt;We hope you found this month's .NET updates informative and engaging. We're always looking to improve and would love to hear your feedback on this new format. Do you find it useful? How can we make it better? Please leave your comments below or reach out to &lt;a href="https://bsky.app/profile/jongalloway.bsky.social" rel="noopener noreferrer"&gt;Jon Galloway&lt;/a&gt; or &lt;a href="https://bsky.app/profile/fboucheros.bsky.social" rel="noopener noreferrer"&gt;Frank Boucher&lt;/a&gt; directly. Your insights are invaluable to us!&lt;/p&gt;

&lt;p&gt;Thank you for being a part of the .NET community!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>programming</category>
      <category>csharp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Different Containerising Options for .NET Developers</title>
      <dc:creator>Justin Yoo</dc:creator>
      <pubDate>Mon, 12 Aug 2024 13:00:59 +0000</pubDate>
      <link>https://dev.to/dotnet/different-containerising-options-for-net-developers-cne</link>
      <guid>https://dev.to/dotnet/different-containerising-options-for-net-developers-cne</guid>
      <description>&lt;p&gt;As a .NET developer, if you want to containerise your .NET apps, you know you need a &lt;code&gt;Dockerfile&lt;/code&gt; first. &lt;code&gt;Dockerfile&lt;/code&gt; is a spec that describes which OS is used, where the .NET code is located, how the .NET code is compiled and how the .NET app is executed. Once your Dockerfile is ready, you can build your container image. But is the Dockerfile the only option for building your .NET apps in a container? How about the container orchestration? Is there any way to orchestrate containers other than running the &lt;code&gt;docker compose up&lt;/code&gt; command? Throughout this post, I'm going to discuss which options are available for .NET developers to containerise your .NET apps.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find a sample code from:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/devkimchi" rel="noopener noreferrer"&gt;
        devkimchi
      &lt;/a&gt; / &lt;a href="https://github.com/devkimchi/msbuild-for-containers" rel="noopener noreferrer"&gt;
        msbuild-for-containers
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This provides sample .NET apps using container images with Dockerfile, with MSBuild, and with .NET Aspire support on Docker Desktop.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;MSBuild for Containers&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;As a .NET developer, when you build a container image for your app, you can use the &lt;code&gt;Dockerfile&lt;/code&gt; to define the container image. However, you can also use the &lt;code&gt;dotnet publish&lt;/code&gt; command to build and publish the container image without a &lt;code&gt;Dockerfile&lt;/code&gt;. This repository provides sample .NET apps using container images with &lt;code&gt;Dockerfile&lt;/code&gt; and with &lt;code&gt;dotnet publish&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In addition to that, if you want to orchestrate containers Docker Compose is usually the first approach. However, you can also use the .NET Aspire to generate the Docker Compose file from the .NET Aspire manifest JSON file. This repository also provides a sample .NET app using the .NET Aspire to orchestrate containers.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Prerequisites&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dotnet.microsoft.com/download/dotnet/8.0?WT.mc_id=dotnet-144884-juyoo" rel="nofollow noopener noreferrer"&gt;.NET SDK 8.0+&lt;/a&gt; with &lt;a href="https://learn.microsoft.com/dotnet/aspire/fundamentals/setup-tooling?WT.mc_id=dotnet-144884-juyoo" rel="nofollow noopener noreferrer"&gt;.NET Aspire workload&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://visualstudio.microsoft.com/?WT.mc_id=dotnet-144884-juyoo" rel="nofollow noopener noreferrer"&gt;Visual Studio&lt;/a&gt; or &lt;a href="https://code.visualstudio.com/?WT.mc_id=dotnet-144884-juyoo" rel="nofollow noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; + &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit" rel="nofollow noopener noreferrer"&gt;C# Dev Kit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prom3theu5/aspirational-manifests" rel="noopener noreferrer"&gt;Aspirate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/products/docker-desktop" rel="nofollow noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Run with &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h3&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Run &lt;code&gt;docker init&lt;/code&gt; to create a new Dockerfile for…&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/devkimchi/msbuild-for-containers" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;There are a few prerequisites to containerise .NET apps effectively.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dotnet.microsoft.com/download/dotnet/8.0?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;.NET SDK 8.0+&lt;/a&gt; with &lt;a href="https://learn.microsoft.com/dotnet/aspire/fundamentals/setup-tooling?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;.NET Aspire workload&lt;/a&gt; and &lt;a href="https://github.com/prom3theu5/aspirational-manifests" rel="noopener noreferrer"&gt;Aspirate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Containerise with &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In the sample code repository, there are two .NET apps, &lt;code&gt;ApiApp&lt;/code&gt; and &lt;code&gt;WebApp&lt;/code&gt;. When you run both apps locally, it communicates with each other by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/MSBuildForContainers.ApiApp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/MSBuildForContainers.WebApp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you want to containerise both apps. How can you do that? The first option is to write a &lt;code&gt;Dockerfile&lt;/code&gt; for each app. You can either manually write &lt;code&gt;Dockerfile&lt;/code&gt; or run the command, &lt;code&gt;docker init&lt;/code&gt;. Once you have &lt;code&gt;Dockerfile&lt;/code&gt; files for both apps, run the following commands to build the container images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For ApiApp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;apiapp:latest&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# For WebApp&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;webapp:latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We all know how &lt;code&gt;Dockerfile&lt;/code&gt; is useful to build container images. However, &lt;code&gt;Dockerfile&lt;/code&gt; is yet another code and should be maintained. If you have many apps to containerise, you need to write &lt;code&gt;Dockerfile&lt;/code&gt; files respectively. This is a bit cumbersome. Is there any other way to containerise .NET apps, without writing &lt;code&gt;Dockerfile&lt;/code&gt; files?&lt;/p&gt;

&lt;h2&gt;
  
  
  Containerise with &lt;code&gt;dotnet publish&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;MSBuild supports containerisation by itself. It uses the &lt;code&gt;dotnet publish&lt;/code&gt; command to build the container image for each app. To do this, you might need to update your &lt;code&gt;.csproj&lt;/code&gt; file to include the containerisation settings. The following is the &lt;code&gt;MSBuildForContainers.ApiApp.csproj&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ContainerRepository&amp;gt;&lt;/span&gt;apiapp&lt;span class="nt"&gt;&amp;lt;/ContainerRepository&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ContainerImageTag&amp;gt;&lt;/span&gt;latest&lt;span class="nt"&gt;&amp;lt;/ContainerImageTag&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two properties replaces the &lt;code&gt;--tag&lt;/code&gt; option in the &lt;code&gt;docker build&lt;/code&gt; command. Once you have these properties in the &lt;code&gt;.csproj&lt;/code&gt; file, run the following command. Note that the &lt;code&gt;-t:PublishContainer&lt;/code&gt; indicates the containerisation and the &lt;code&gt;--os&lt;/code&gt; and &lt;code&gt;--arch&lt;/code&gt; options specify the target OS and architecture.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;publish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/MSBuildForContainers.ApiApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PublishContainer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--arch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x64&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, you'll have the container image. If you want to change the base image to the &lt;a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-chiseled-containers/?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;chiseled container one&lt;/a&gt;, add another property to the &lt;code&gt;.csproj&lt;/code&gt; file. The following property sets the chiseled Ubuntu 24.04 image as the base image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ContainerBaseImage&amp;gt;&lt;/span&gt;mcr.microsoft.com/dotnet/aspnet:8.0-noble-chiseled&lt;span class="nt"&gt;&amp;lt;/ContainerBaseImage&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, run the &lt;code&gt;dotnet publish&lt;/code&gt; command above again. This time, the container image is built based on the chiseled image. Let's do the same thing against the &lt;code&gt;MSBuildForContainers.WebApp.csproj&lt;/code&gt; file. This way, you can containerise your .NET apps without writing &lt;code&gt;Dockerfile&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;Alternatively, you don't even need those properties in the &lt;code&gt;.csproj&lt;/code&gt; file. You can run the following command to build the container image directly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;publish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/MSBuildForContainers.ApiApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;PublishContainer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--arch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x64&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ContainerBaseImage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mcr.microsoft.com/dotnet/aspnet:8.0-noble-chiseled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ContainerRepository&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;apiapp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ContainerImageTag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have the same development experience as building the container image with the &lt;code&gt;docker build&lt;/code&gt; command, without having to rely on &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, you've got chiseled container images for both API app and web app. How to let them talk to each other?&lt;/p&gt;

&lt;h2&gt;
  
  
  Container orchestration with &lt;code&gt;docker compose&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The existing web app container image can't talk to the API app container image because it doesn't know where the API app container is. To make the web app container talk to the API app container, you need to slightly modify the web app and build the container image again. Open the &lt;code&gt;MSBuildForContainers.WebApp/Program.cs&lt;/code&gt; file and update the base address value as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IApiAppClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApiAppClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://localhost:5051/"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IApiAppClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApiAppClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://apiapp:8080/"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the &lt;code&gt;dotnet publish&lt;/code&gt; command again to build the web app container image. Now, you can manually run the &lt;code&gt;docker run&lt;/code&gt; command to run both containers by attaching the same network. But for the container orchestration, the &lt;code&gt;docker compose up&lt;/code&gt; command is much easier to use. The &lt;code&gt;docker-compose.yml&lt;/code&gt; file is already prepared in the sample code repository. Run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/docker-compose.yaml&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;up&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, both containers are up and running. The web app container can talk to the API app container. This is how you can orchestrate containers with &lt;code&gt;docker compose up&lt;/code&gt;. Again, this Docker Compose file is yet another code and should be maintained. If you have many apps to orchestrate, how would you manage them?&lt;/p&gt;

&lt;h2&gt;
  
  
  Container orchestration with .NET Aspire and Aspirate
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/dotnet/aspire/get-started/aspire-overview?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;.NET Aspire&lt;/a&gt; is to orchestrate .NET apps in containers. For this Docker Compose orchestration purpose, &lt;a href="https://github.com/prom3theu5/aspirational-manifests" rel="noopener noreferrer"&gt;Aspirate&lt;/a&gt; is used, which is a tool that generates the Docker Compose file, a &lt;a href="https://kustomize.io/" rel="noopener noreferrer"&gt;Kustomize file&lt;/a&gt; or &lt;a href="https://helm.sh/" rel="noopener noreferrer"&gt;helm file&lt;/a&gt; for the container orchestration. To use Aspirate, you need to install it first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;aspirate&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the sample code repository, Both web app and API app are orchestrated with .NET Aspire in another branch. Switch to the &lt;code&gt;aspire&lt;/code&gt; branch with the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;aspire&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's generate the Docker Compose file with Aspirate. Run the following command to generate the .NET Aspire manifest file first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;/MSBuildForContainers.AppHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--publisher&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--output-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;/aspire-manifest.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, generate the Docker Compose file with the Aspirate command. Note that it intentionally excludes the .NET Aspire dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;aspirate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--project-path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;/MSBuildForContainers.AppHost&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--aspire-manifest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;/aspire-manifest.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--output-format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;compose&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;\&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nt"&gt;--disable-secrets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--include-dashboard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you have the Docker Compose file generated. Run the &lt;code&gt;docker compose up&lt;/code&gt; command to orchestrate the containers. This way, you can orchestrate your .NET apps in containers without manually writing the Docker Compose file.&lt;/p&gt;




&lt;p&gt;So far, I've walked through how .NET developers can containerise their .NET apps with different options. You can either write &lt;code&gt;Dockerfile&lt;/code&gt; files or use &lt;code&gt;dotnet publish&lt;/code&gt; to build container images. You can orchestrate containers by writing the Docker Compose file by hand or letting .NET Aspire and Aspirate generate it automatically. Which one do you prefer?&lt;/p&gt;

&lt;h2&gt;
  
  
  More about MSBuild for Containers?
&lt;/h2&gt;

&lt;p&gt;If you want to learn more options about containers with MSBuild, the following links might be helpful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/dotnet/aspire/get-started/aspire-overview?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;.NET Aspire&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/dotnet/core/docker/publish-as-container?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;Containerise a .NET app with &lt;code&gt;dotnet publish&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/dotnet/core/docker/container-images?WT.mc_id=dotnet-147226-juyoo" rel="noopener noreferrer"&gt;.NET container images&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>containers</category>
      <category>docker</category>
      <category>msbuild</category>
    </item>
    <item>
      <title>How use a Blazor QuickGrid with GraphQL</title>
      <dc:creator>.NET Guest Blogger</dc:creator>
      <pubDate>Wed, 24 Jul 2024 17:05:00 +0000</pubDate>
      <link>https://dev.to/dotnet/how-use-a-blazor-quickgrid-with-graphql-3l50</link>
      <guid>https://dev.to/dotnet/how-use-a-blazor-quickgrid-with-graphql-3l50</guid>
      <description>&lt;p&gt;This is the second post in a series of posts about GraphQL and .NET. In the &lt;a href="https://devblogs.microsoft.com/dotnet/why-and-how-to-execute-graph-ql-queries-in-dotnet" rel="noopener noreferrer"&gt;first post&lt;/a&gt;, we saw how to query a GraphQL API in .NET using Strawberry Shake from a console application. In this post, we will see how to fill a Blazor QuickGrid component with data fetched with GraphQL. We will also use the virtualization feature of the QuickGrid to improve performance.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Get the code!&lt;br&gt;
You can find the code for this post in the &lt;a href="https://github.com/fboucher/startrek-demo" rel="noopener noreferrer"&gt;startrek-demo&lt;/a&gt; GitHub repo. Once more we will be using the StarTrek GraphQL API that was created with Data API Builder (DAB) and is running locally in a Docker container, and accessible at &lt;code&gt;http://localhost:5000/graphql&lt;/code&gt;. If you really want to follow along you can find the &lt;a href="https://github.com/FBoucher/startrek-demo#database-and-apis-in-containers" rel="noopener noreferrer"&gt;setup steps and T-SQL script in the repo&lt;/a&gt;. But the important part is that this will work with any data source that you want to expose through GraphQL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Adding a GraphQL query to Blazor
&lt;/h2&gt;

&lt;p&gt;Once more we will use &lt;a href="https://www.nuget.org/packages/StrawberryShake.Blazor" rel="noopener noreferrer"&gt;StrawberryShake&lt;/a&gt; to generate a client for us based on the schema. Using your favourite method, add the &lt;code&gt;StrawberryShake.Blazor&lt;/code&gt; package to the project.&lt;/p&gt;

&lt;p&gt;Let’s create a dotnet-tools manifest, add the GraphQL tool, and download the GraphQL schema to generate the client code specifying the client name “StartrekClient”, using the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet new tool-manifest

dotnet tool install StrawberryShake.Tools --local

dotnet graphql init http://localhost:5000/graphql -n StartrekClient
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this post demo, we will list all the actors from the StarTrek series. Using the GraphQL IDE for Developers &lt;a href="https://chillicream.com/products/bananacakepop" rel="noopener noreferrer"&gt;Banana Cake Pop&lt;/a&gt; we can build a query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query GetActors() {
  actors{
    items {
      id
      name
      birthYear
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then save this query in a file named &lt;code&gt;GetActors.graphql&lt;/code&gt; in the subfolder name ‘Queries’ to keep things clean. Once the project is built the client &lt;code&gt;StartrekClient&lt;/code&gt; will be generated and contains &lt;code&gt;GetActors&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the QuickGrid component
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/aspnet/core/blazor/components/quickgrid" rel="noopener noreferrer"&gt;QuickGrid&lt;/a&gt; is a recent Razor component that provides a simple and convenient data grid component for common grid rendering scenarios. It is highly optimized and uses advanced techniques to achieve optimal rendering performance. Add the package &lt;code&gt;Microsoft.AspNetCore.Components.QuickGrid&lt;/code&gt; to the project.&lt;/p&gt;

&lt;p&gt;Adding a QuickGrid to a Blazor page is straightforward. Assuming that &lt;code&gt;result&lt;/code&gt; contains our list of &lt;code&gt;Actor&lt;/code&gt;, here is an example of how to use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;QuickGrid Items="result.Actors!.Items.AsQueryable()"&amp;gt;
    &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Id)" Sortable="true" /&amp;gt;
    &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Name)" Sortable="true" /&amp;gt;
    &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.BirthYear)" Sortable="true" /&amp;gt;
&amp;lt;/QuickGrid&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is simple and only shows three simple columns mapped directly on properties, but note that much more customization is possible. The &lt;code&gt;Items&lt;/code&gt; property is an &lt;code&gt;IQueryable&lt;/code&gt; that allows the QuickGrid to improve performance and the user experience, like being able to sort columns easily, and so much more. One of the differences between &lt;code&gt;IQueryable&lt;/code&gt; and &lt;code&gt;IEnumerable&lt;/code&gt; is that &lt;code&gt;IQueryable&lt;/code&gt; will retrieve all the rows of the tables and apply the WHERE clause in memory but &lt;code&gt;IQueryable&lt;/code&gt; will apply the WHERE clause in the source and only retrieve the requested rows.&lt;/p&gt;

&lt;p&gt;To bind the QuickGrid &lt;code&gt;Items&lt;/code&gt; property to the GraphQL query, we can use the &lt;code&gt;&amp;lt;UseGetActors&amp;gt;&lt;/code&gt; component that was generated by StrawberryShake. &lt;code&gt;&amp;lt;UseGetActors&amp;gt;&lt;/code&gt; has a few child components: &lt;code&gt;&amp;lt;ChildContent&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;ErrorContent&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;LoadingContent&amp;gt;&lt;/code&gt; that will be displayed based on the state of the query. Let’s have a look at a page that uses this component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page "/graphql"
@using Microsoft.AspNetCore.Components.QuickGrid

@inject IStartrekClient startrekClient

&amp;lt;PageTitle&amp;gt;Actors by GraphQL&amp;lt;/PageTitle&amp;gt;

&amp;lt;h1&amp;gt;Actors by GraphQL&amp;lt;/h1&amp;gt;

&amp;lt;UseGetActors Context="result"&amp;gt;
    &amp;lt;ChildContent&amp;gt;
        &amp;lt;div class="grid"&amp;gt;
            &amp;lt;QuickGrid Items="result.Actors!.Items.AsQueryable()"&amp;gt;
                &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Id)" Sortable="true" /&amp;gt;
                &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Name)" Sortable="true" /&amp;gt;
                &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.BirthYear)" Sortable="true" /&amp;gt;
            &amp;lt;/QuickGrid&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/ChildContent&amp;gt;
    &amp;lt;ErrorContent&amp;gt;
        Something went wrong ...&amp;lt;br /&amp;gt;
        @result.First().Message
    &amp;lt;/ErrorContent&amp;gt;
    &amp;lt;LoadingContent&amp;gt;
        Loading ...
    &amp;lt;/LoadingContent&amp;gt;
&amp;lt;/UseGetActors&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The component will automatically fetch the data using the query and make it available in the context. We can add the QuickGrid component to the &lt;code&gt;&amp;lt;ChildContent&amp;gt;&lt;/code&gt; and bind the &lt;code&gt;Items&lt;/code&gt; using the context &lt;code&gt;result&lt;/code&gt;, provided by the &lt;code&gt;&amp;lt;UseGetActors&amp;gt;&lt;/code&gt; component. The &lt;code&gt;&amp;lt;ErrorContent&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;LoadingContent&amp;gt;&lt;/code&gt; are very convenient to display messages based on the state of the query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iWNsIL5g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/simple_quickgrid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iWNsIL5g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/simple_quickgrid.png" alt="Simple QuickGrid displaying Actors information" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  QuickGrid virtualization
&lt;/h2&gt;

&lt;p&gt;The QuickGrid component supports &lt;a href="https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.components.quickgrid.quickgrid-1.virtualize" rel="noopener noreferrer"&gt;virtualization&lt;/a&gt;, which is a technique that only renders the rows that are visible in the viewport. This can greatly improve the performance of the grid when dealing with a large number of rows. To be able to use virtualization, your data source must support the parameters &lt;code&gt;StartIndex&lt;/code&gt; (aka skip) and &lt;code&gt;Count&lt;/code&gt; (aka limit or take). If your data source only uses tokens like a cursor, you can use the pagination feature of the QuickGrid, but not the virtualization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customizing the GraphQL API to support virtualization&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;For the first part of this post and the previous one, we used Data API Builder (DAB) to create a GraphQL API. Unfortunately, it doesn’t support the required parameters, so we cannot be used for the virtualization. However we can use the pagination and all the other features of the QuickGrid. To make it work with virtualization, we used &lt;code&gt;HotChocolate&lt;/code&gt;, the same package used by DAB to create a custom GraphQL API. If you are interested, the &lt;a href="https://github.com/FBoucher/startrek-demo?tab=readme-ov-file#chocospock-is-a-custom-graphql-endpoint" rel="noopener noreferrer"&gt;&lt;code&gt;code and setup steps&lt;/code&gt;&lt;/a&gt; are available in GitHub repo.&lt;/p&gt;

&lt;p&gt;To enable virtualization, we need to set the &lt;code&gt;Virtualize&lt;/code&gt; property to &lt;code&gt;true&lt;/code&gt; on the QuickGrid component. The QuickGrid will require an &lt;code&gt;ItemsProvider&lt;/code&gt; that will be used to fetch the data. Here is what the QuickGrid looks like with virtualization enabled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="grid" tabindex="-1"&amp;gt;
    &amp;lt;QuickGrid ItemsProvider="@actorProvider" Virtualize="true"&amp;gt;
        &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Id)" Sortable="false" /&amp;gt;
        &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.Name)" Sortable="true" 
                                                    IsDefaultSortColumn="true" 
                                                    InitialSortDirection="SortDirection.Ascending"/&amp;gt;
        &amp;lt;PropertyColumn Property="@(a =&amp;gt; a.BirthYear)" Sortable="false" /&amp;gt;
    &amp;lt;/QuickGrid&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;div class="my-2"
    &amp;lt;div class="inline-block my-1"&amp;gt;
        Total: &amp;lt;strong&amp;gt;@numResults results&amp;lt;/strong&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create an ItemsProvider
&lt;/h3&gt;

&lt;p&gt;Now we need to set &lt;code&gt;actorProvider&lt;/code&gt; so it can be called by the QuickGrid with &lt;code&gt;StartIndex&lt;/code&gt; and &lt;code&gt;Count&lt;/code&gt; parameters to fetch the data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@code {
    GridItemsProvider&amp;lt;IGetActors_Actors_Items&amp;gt; actorProvider;

    int numResults = 0;

    protected override async Task OnInitializedAsync()
    {
        actorProvider = async request =&amp;gt;
        {
            var response = await startrekClient.GetActors.ExecuteAsync(request.StartIndex, request.Count, request.CancellationToken);           

            if (numResults == 0 &amp;amp;&amp;amp; !request.CancellationToken.IsCancellationRequested)
            {
                numResults = response!.Data.Actors.TotalCount;
                StateHasChanged();
            }

            return GridItemsProviderResult.From(
                    items: new List&amp;lt;IGetActors_Actors_Items&amp;gt;(response!.Data.Actors.Items),
                    totalItemCount: response!.Data.Actors.TotalCount
            );
        };

    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the first call, we update the &lt;code&gt;numResults&lt;/code&gt; with the total number of items and call &lt;code&gt;StateHasChanged()&lt;/code&gt; to update the UI. This is optional but it shows that there is more actors than what is displayed.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;actorProvider&lt;/code&gt; is defined as &lt;code&gt;GridItemsProvider&amp;lt;IGetActors_Actors_Items&amp;gt;&lt;/code&gt; where the interface was once more generated for us. The provider needs to return two properties: &lt;code&gt;items&lt;/code&gt; that contains the subset of &lt;code&gt;Actor&lt;/code&gt; returned by query and &lt;code&gt;totalItemCount&lt;/code&gt;. The &lt;code&gt;totalItemCount&lt;/code&gt; is used by the QuickGrid to know how many items are available and to display the scrollbar correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Query with parameters
&lt;/h3&gt;

&lt;p&gt;The last step is to modify the GraphQL query to accept the &lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;take&lt;/code&gt; parameters. This way the QuickGrid could ask to return the next 20 Actor after the skipping the first 100 ones. Here is the modified query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query GetActors($skip: Int, $take: Int) {
  actors(skip: $skip, take: $take, sortBy: "name") {
    items {
      id
      name
      birthYear
    }
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    totalCount
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a good idea to test your query in Banana Cake Pop to make sure it works as expected. Here as an example when the query is called without any parameters all actors are returned.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ETfVhEwh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/graphql-query-no-param.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ETfVhEwh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/graphql-query-no-param.png" alt="GraphQL query without parameters" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is the result of the same query with the parameters &lt;code&gt;skip: 5&lt;/code&gt; and &lt;code&gt;take: 20&lt;/code&gt;. Notice that the sixth actor of the first return is now the first one as the first five has been skipped.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JtuDYMSX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/graphql-query-param.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JtuDYMSX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/graphql-query-param.png" alt="GraphQL skipping actors" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The final result
&lt;/h3&gt;

&lt;p&gt;Here is the final result of the QuickGrid with virtualization enabled. The QuickGrid will only render the rows that are visible, in our case 20 actors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XJWKUdmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/quickgrid_virtualized.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XJWKUdmH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/quickgrid_virtualized.gif" alt="QuickGrid in action" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the animation above &lt;code&gt;...&lt;/code&gt; is used as a place holder when scrolling. Once you stop scrolling the &lt;code&gt;actorProvider&lt;/code&gt; will then fetch the actors using the parameters &lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;take&lt;/code&gt; and update the QuickGrid with the new data. We look at the Network tab of the browser’s Developer Tools, we can see the all the different calls to the GraphQL API with the parameters used.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ax6V0bIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/quickgrid_calls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ax6V0bIs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://devblogs.microsoft.com/dotnet/wp-content/uploads/sites/10/2024/07/quickgrid_calls.png" alt="QuickGrid http calls" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we saw how to bind a Blazor QuickGrid component to a GraphQL query using Strawberry Shake. We also saw how to enable virtualization to improve the performance of the grid when dealing with a large number of rows. The QuickGrid component is very powerful and can be customized in many ways. Let us know in the comments what you would like to see next about the QuickGrid component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video demo
&lt;/h2&gt;

&lt;p&gt;During the &lt;a href="https://www.youtube.com/live/ubX-a6_V_ao" rel="noopener noreferrer"&gt;ASP.NET Community Standup – Using GraphQL to enhance Blazor apps&lt;/a&gt; I did a demo of the QuickGrid with GraphQL in a Blazor application. You can watch the video below.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/aspnet/core/blazor/components/quickgrid?view=aspnetcore-8.0" rel="noopener noreferrer"&gt;ASP.NET Core Blazor QuickGrid component&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chillicream.com/docs/strawberryshake" rel="noopener noreferrer"&gt;ChilliCream: Strawberry Shake, Banana Cake Pop, Hot Chocolate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The post &lt;a href="https://devblogs.microsoft.com/dotnet/how-use-a-blazor-quickgrid-with-graphql/" rel="noopener noreferrer"&gt;How use a Blazor QuickGrid with GraphQL&lt;/a&gt; appeared first on &lt;a href="https://devblogs.microsoft.com/dotnet" rel="noopener noreferrer"&gt;.NET Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>aspnetcore</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Join us for Azure Developers - .NET Day on April 30!</title>
      <dc:creator>Jon Galloway</dc:creator>
      <pubDate>Wed, 24 Apr 2024 19:46:15 +0000</pubDate>
      <link>https://dev.to/dotnet/join-us-for-azure-developers-net-day-on-april-30-1pj8</link>
      <guid>https://dev.to/dotnet/join-us-for-azure-developers-net-day-on-april-30-1pj8</guid>
      <description>&lt;p&gt;We’re excited to announce the upcoming Azure Developers – .NET Day! Join us on April 30th for a full day dedicated to .NET developers and the Azure ecosystem. This online event is packed with expert-led sessions that delve into AI advancements, app development efficiencies, cloud-native capabilities, and much more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Date:&lt;/strong&gt; April 30, 2024&lt;br&gt;
&lt;strong&gt;Time:&lt;/strong&gt; Starting at 8:00 AM PST / 16:00 UTC&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.microsoft.com/en-us/reactor/events/22265/" rel="noopener noreferrer"&gt;&lt;br&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdabuttonfactory.com%2Fbutton.png%3Ft%3DSave%2520the%2520Date%21%26f%3DOpen%2BSans-Bold%26ts%3D26%26tc%3Dfff%26hp%3D45%26vp%3D20%26c%3D11%26bgt%3Dunicolored%26bgc%3D0078D4" alt="Save the Date!"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Attend?
&lt;/h3&gt;

&lt;p&gt;Azure Developers – .NET Day 2024 is an essential event for .NET developers aiming to elevate their cloud development capabilities. This day-long online event offers an unparalleled opportunity to discover the latest and greatest Azure features tailored for .NET applications. You'll engage with cutting-edge cloud development techniques that not only save time and money but also optimize customer experiences.&lt;/p&gt;

&lt;p&gt;Hear directly from the experts behind Azure's most sought-after services for developers, covering key areas such as AI, app development, data services, serverless computing, cloud-native computing, and boosting developer productivity. Don’t miss out on this chance to interact and engage with the team throughout the day, taking your cloud development skills to the next level.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-D9lFxMORVM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Speaker Lineup and Sessions
&lt;/h3&gt;

&lt;p&gt;This year’s event features a diverse lineup of topics and speakers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI Coding Techniques&lt;/strong&gt; with Bruno Capuano: Dive into practical AI coding sessions that add intelligence to your .NET applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Copilot for SQL Development&lt;/strong&gt; by Subhojit Basak: Learn how to integrate AI into your database development processes for faster, more reliable outputs.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redis &amp;amp; .NET Apps&lt;/strong&gt; with Catherine Wang: Enhance your applications' consistency and smart capabilities using Redis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change Data Streams with Azure SQL&lt;/strong&gt; by Brian Spendolini: Quickly set up change data streams with .NET, showcasing real-time data manipulation and analysis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data API Builders on Azure&lt;/strong&gt; with Frank Boucher and Jerry Nixon: Auto-generate and deploy data APIs on Azure Static Web Apps effortlessly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;gRPC on App Service&lt;/strong&gt; by Jeff Martinez and Byron Tardif: Host your gRPC workloads efficiently using .NET on Windows-based Azure App Services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event-Driven Architectures&lt;/strong&gt; by Davide Mauri: Implement event-driven solutions with .NET and Azure Functions for responsive, scalable applications.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enhancing Developer Productivity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure API Center&lt;/strong&gt; by Justin Yoo: Unlock new levels of productivity with Azure API management tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code Project Setups&lt;/strong&gt; by Ori Bar-ilan: Master your project setups and streamline your development workflow using Visual Studio Code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Learn and Connect
&lt;/h3&gt;

&lt;p&gt;Join us online via the Azure Developers &lt;a href="https://youtube.com/@AzureDevelopers" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; and &lt;a href="https://twitch.tv/azuredevelopers" rel="noopener noreferrer"&gt;Twitch&lt;/a&gt; channels to transform your ideas into exceptional solutions with .NET and Azure.&lt;/p&gt;

&lt;p&gt;We look forward to seeing you there. Let’s build something amazing together!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>dotnet</category>
      <category>github</category>
      <category>vscode</category>
    </item>
    <item>
      <title>.NET Monthly Roundup - March 2024 - .NET 9 Preview 2, Smart Components, AI fun, and more!</title>
      <dc:creator>Jon Galloway</dc:creator>
      <pubDate>Tue, 09 Apr 2024 18:19:48 +0000</pubDate>
      <link>https://dev.to/dotnet/net-monthly-roundup-march-2024-net-9-preview-2-smart-components-ai-fun-and-more-2iha</link>
      <guid>https://dev.to/dotnet/net-monthly-roundup-march-2024-net-9-preview-2-smart-components-ai-fun-and-more-2iha</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/h9f3wlbFKbQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;📆Welcome to our March .NET Monthly Roundup with Jon Galloway! In just 3 minutes, Jon breaks down the latest news from the month of March 2024 that .NET developers need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top links
&lt;/h3&gt;

&lt;p&gt;📚&lt;a href="http://aka.ms/dnmr-2403"&gt;All the links&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟.NET 9 Preview 2&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/core/discussions/9217"&gt;.NET 9 Preview 2 Discussion&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/aspnetcore/discussions/54503"&gt;ASP.NET Core updates in .NET 9 Preview 2&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/preview2/aspnetcore.md"&gt;ASP.NET Core updates in .NET 9 Preview 2 Release Notes&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/core/blob/main/release-notes/9.0/preview/preview2/efcoreanddata.md"&gt;EF Core updates in .NET 9 Preview 2&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/preview-4"&gt;.NET Aspire preview 4 - .NET Aspire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧪Smart Components🧪&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/introducing-dotnet-smart-components/"&gt;Introducing .NET Smart Components - AI-powered UI controls&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🤖AI Fun&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/get-started-with-dotnet-ai-quickstarts/"&gt;Get started with .NET 8 and AI using new quickstart tutorials&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/get-started-milvus-vector-db-dotnet/"&gt;Get Started with Milvus Vector DB in .NET&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚙️Visual Studio and Tools Updates&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/unity-extension-for-visual-studio-code-now-generally-available/"&gt;Unity extension for Visual Studio Code - Now Generally Available&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/experimental-msbuild-editor/"&gt;A new MSBuild editing experience&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️.NET 7 End of Support&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-7-end-of-support/"&gt;.NET 7 will reach End of Support on May 14, 2024&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📺Top Video Recommendation&lt;br&gt;
➡️&lt;a href="https://www.youtube.com/watch?v=R-z2Hv-7nxk"&gt;Writing async/await from scratch in C# with Stephen Toub&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What did you think?
&lt;/h3&gt;

&lt;p&gt;With so much new information coming at you each month, we're looking at ways to bring you the highlights. Let us know if this helps, and how we can do it better next month!&lt;/p&gt;

&lt;p&gt;Jon&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>aspire</category>
      <category>blazor</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Earn your C# Certification with new Learning Series</title>
      <dc:creator>Katie Savage</dc:creator>
      <pubDate>Mon, 01 Apr 2024 17:09:40 +0000</pubDate>
      <link>https://dev.to/dotnet/earn-your-c-certification-with-new-learning-series-1eka</link>
      <guid>https://dev.to/dotnet/earn-your-c-certification-with-new-learning-series-1eka</guid>
      <description>&lt;p&gt;We are excited to announce our new C# for Certification email learning series.&lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Sign up for the learning series: &lt;a href="https://aka.ms/learningseries/csharp/signup"&gt;https://aka.ms/learningseries/csharp/signup&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;This eight-week email series is intended to provide you with all the resources you need to complete the Foundational C# Certification training and take the exam. The learning series will give you a structured learning path and new content to learn each week.  &lt;/p&gt;

&lt;h2&gt;
  
  
  How does the C# Certification learning series work?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up for the learning series: &lt;a href="https://aka.ms/learningseries/csharp/signup"&gt;https://aka.ms/learningseries/csharp/signup&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Check your inbox each week to find a new lesson with a structured learning path, and additional resources. &lt;/li&gt;
&lt;li&gt;Complete the learning path and hands-on projects.&lt;/li&gt;
&lt;li&gt;Take the exam and earn your certification!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is C#?
&lt;/h2&gt;

&lt;p&gt;C# (pronounced "See Sharp") is a modern, object-oriented, and type-safe programming language. C# enables developers to build many types of secure and robust applications that run in .NET. With C#, you can build... &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business applications to capture, analyze, and process data &lt;/li&gt;
&lt;li&gt;Dynamic web applications that can be accessed from a web browser &lt;/li&gt;
&lt;li&gt;Games, both 2D and 3D &lt;/li&gt;
&lt;li&gt;Financial and scientific applications &lt;/li&gt;
&lt;li&gt;Cloud-based applications &lt;/li&gt;
&lt;li&gt;Mobile applications &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...and more!  &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/9THmGiSPjBQ"&gt;
&lt;/iframe&gt;
 &lt;/p&gt;

&lt;h2&gt;
  
  
  The C# Roadmap
&lt;/h2&gt;

&lt;p&gt;As a C# beginner, it can be difficult to know where to start. The C# Roadmap below was created by experts at Microsoft.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get started! &lt;/li&gt;
&lt;li&gt;Write your first code using C#
&lt;/li&gt;
&lt;li&gt;Create and run simple C# console applications
&lt;/li&gt;
&lt;li&gt;Add logic to C# console applications &lt;/li&gt;
&lt;li&gt;Work with variable data in C# console applications &lt;/li&gt;
&lt;li&gt;Create methods in C# console applications &lt;/li&gt;
&lt;li&gt;Debug C# console applications &lt;/li&gt;
&lt;li&gt;Wrap up and additional learning resources &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🚀 &lt;strong&gt;Begin earning your C# Certification today: &lt;a href="https://aka.ms/learningseries/csharp/signup"&gt;https://aka.ms/learningseries/csharp/signup&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not ready to sign up for the series?&lt;/em&gt; Get access to the content through the Foundational C# Certification page: &lt;a href="https://aka.ms/csharp/certification"&gt;https://aka.ms/csharp/certification&lt;/a&gt;  &lt;/p&gt;

</description>
      <category>csharp</category>
      <category>programming</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>.NET Monthly Roundup - February 2024 - Top blog posts, VS News, .NET 9 Vision, and more!</title>
      <dc:creator>Jon Galloway</dc:creator>
      <pubDate>Thu, 07 Mar 2024 21:44:44 +0000</pubDate>
      <link>https://dev.to/dotnet/net-monthly-roundup-february-2024-top-blog-posts-vs-news-net-9-vision-and-more-3h6n</link>
      <guid>https://dev.to/dotnet/net-monthly-roundup-february-2024-top-blog-posts-vs-news-net-9-vision-and-more-3h6n</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_eO-1zPdB-U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Welcome to our February .NET Monthly Roundup with Jon Galloway! In just 3 minutes, Jon breaks down the latest news from the month of February 2024 that .NET developers need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top links
&lt;/h3&gt;

&lt;p&gt;📚&lt;a href="http://aka.ms/dnmr-2402"&gt;All the links&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟Featured Blog Posts&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/introducing-aspnetcore-metrics-and-grafana-dashboards-in-dotnet-8/"&gt;Introducing ASP.NET Core metrics and Grafana dashboards in .NET 8&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/winforms-designer-64-bit-path-forward/"&gt;WinForms in a 64-Bit world - our strategy going forward&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚙️Visual Studio and Tools Updates&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-9-now-available/"&gt;Visual Studio 2022 17.9 Now Available&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studios-full-year-in-review-2023/"&gt;Visual Studio's Full Year in Review (2023)&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/my-top-10-new-visual-studio-features-of-2023-for-dotnet-developers/"&gt;My Top 10 NEW Visual Studio Features of 2023 for .NET Developers&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/nuget/announcing-nuget-6-9/"&gt;Announcing NuGet 6.9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👁️.NET 9 Vision&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/our-vision-for-dotnet-9/"&gt;Our Vision for .NET 9&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/core/discussions/9167"&gt;.NET 9 Preview 1 · dotnet/core · Discussion #9167&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://github.com/dotnet/core/discussions/9131"&gt;Welcome to .NET Release News on GitHub Discussions! · dotnet/core · Discussion #9131&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🗼.NET Aspire Preview 3&lt;br&gt;
➡️&lt;a href="https://learn.microsoft.com/en-us/dotnet/aspire/whats-new/preview-3"&gt;.NET Aspire preview 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💞Community News&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-maui-community-toolkit-2023-highlights/"&gt;.NET MAUI Community Toolkit 2023 Highlights&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://marketplace.visualstudio.com/items?itemName=GiorgiDalakishvili.EFCoreVisualizer"&gt;EFCore.Visualizer&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What did you think?
&lt;/h3&gt;

&lt;p&gt;With so much new information coming at you each month, we're looking at ways to bring you the highlights. Let us know if this helps, and how we can do it better next month!&lt;/p&gt;

&lt;p&gt;Jon&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>aspire</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>An Introduction to the World of Containers with .NET 8</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Fri, 16 Feb 2024 19:19:47 +0000</pubDate>
      <link>https://dev.to/dotnet/an-introduction-to-the-world-of-containers-with-net-8-4elf</link>
      <guid>https://dev.to/dotnet/an-introduction-to-the-world-of-containers-with-net-8-4elf</guid>
      <description>&lt;p&gt;Containers are a popular way of packaging and distributing applications in today’s Cloud Native landscape – but what are they, and how can .NET developers integrate them into their workflows? Today, let's talk about what containers are, how they relate to Docker, and how the .NET tooling makes it easy for developers to easily streamline the process of creating containers with .NET.&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers with .NET For Beginners
&lt;/h2&gt;

&lt;p&gt;Follow along with this blog and our new &lt;a href="https://dotnet.microsoft.com/learn/videos" rel="noopener noreferrer"&gt;Beginner's series&lt;/a&gt; on containers and Docker for .NET.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/HA8rpDWMRq0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Containers?
&lt;/h2&gt;

&lt;p&gt;A container is a standard unit of software that packages up code and all its dependencies. It allows applications to run consistently across different computing environments. You'll find containers supported by all major cloud providers with various ways to run your containers, ranging from serverless options to fully managed Kubernetes services.&lt;/p&gt;

&lt;p&gt;Containers provide a flexible choice for application packaging, making it a valuable skill to master. That's why .NET invests in making containers easy to use for developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benefits of Containers
&lt;/h2&gt;

&lt;p&gt;So why should you use containers? The answer lies in a uniform deployment and uniform execution of applications. Containers make the job of maintaining and operating your services much easier in the long term. In addition, the whole world of automated DevOps, tooling, alerting, and monitoring can be integrated into your solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Setup
&lt;/h2&gt;

&lt;p&gt;The first step is to install the &lt;a href="https://dotnet.microsoft.com/dotnet" rel="noopener noreferrer"&gt;.NET SDK&lt;/a&gt;. You can use the .NET CLI to create containers which by default creates Linux containers. You can create these containers on any operating system; Windows, Mac, Linux, or the &lt;a href="https://learn.microsoft.com/windows/wsl/install" rel="noopener noreferrer"&gt;Windows Subsystem for Linux&lt;/a&gt;. The choice is yours however you enjoy developing. Additionally, having &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; installed will enable you to run your containers after you create them with the .NET SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Containers with .NET
&lt;/h2&gt;

&lt;p&gt;Now, let's take a look at just how easy it can be to create containers with .NET. To start, let's first create a new web app with the following .NET CLI command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet new web &lt;span class="nt"&gt;-o&lt;/span&gt; container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can navigate to the new directory that it was created in:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can now run the application locally with &lt;code&gt;dotnet run&lt;/code&gt;, but let's go ahead and create a container by publishing the app with the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

dotnet publish &lt;span class="nt"&gt;-t&lt;/span&gt;:PublishContainer


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By running a single command, you can create a container of your web app. This is the same &lt;code&gt;publish&lt;/code&gt; command you're already familiar with for publishing your web application, but now it's being used for containerization. The .NET SDK will provide you with information about the container it just created, such as the container name, the tag, and the base image it chose.&lt;/p&gt;

&lt;p&gt;Speaking of the base image, it's like the operating system and software configuration that your application will be deployed onto. In this example, as a web app targeting .NET 8, the SDK chose an ASP.NET image from Microsoft with the 8.0 tag. You will see output from the command similar to the following that highlights this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

Building image &lt;span class="s1"&gt;'conainer-webapp'&lt;/span&gt; with tag &lt;span class="s1"&gt;'latest'&lt;/span&gt; on top of the base image &lt;span class="s1"&gt;'mcr.microsoft.com/dotnet/aspnet:8.0'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Pushed image &lt;span class="s1"&gt;'conainer-webapp:latest'&lt;/span&gt; to &lt;span class="nb"&gt;local &lt;/span&gt;registry via &lt;span class="s1"&gt;'docker'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To get a closer look at the image we just built, we can use Docker Desktop. It's fascinating to see how the image is composed of different layers, each representing a portion of the file system or a change to the operating environment. These layers come together to create a runnable container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2y3fvpbglus147q1raz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo2y3fvpbglus147q1raz.png" alt="Layer of the container in Docker Desktop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's run the container with a docker &lt;code&gt;run&lt;/code&gt; command that specifies the container name:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

docker run &lt;span class="nt"&gt;-P&lt;/span&gt; container-webapp


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Optionally, we could run the container directly from Docker Desktop instead of using the command. If we open Docker Desktop, we can access our running application by clicking on the port link next to our container:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvstdf21hu1j3nnymz3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvstdf21hu1j3nnymz3d.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And there you have it, a browser will open up with our new web app running in a container!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpvk5jbo7018vfmavftd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpvk5jbo7018vfmavftd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps: Deep Dive into Tooling &amp;amp; Publishing to the cloud
&lt;/h2&gt;

&lt;p&gt;That wraps up our quick taste of containers and how .NET makes it easy to get started with them. This is only the first step, and I have a full beginner's series that dives deeper into the &lt;a href="https://www.youtube.com/watch?v=qCxSYymD0ug&amp;amp;list=PLdo4fOcmZ0oXss45l49Q8h-Omuwo2FD-U&amp;amp;index=2&amp;amp;pp=gAQBiAQB" rel="noopener noreferrer"&gt;tooling experiences available on the command line as well as in Visual Studio and Visual Studio Code&lt;/a&gt;. Then I go into how you can take your containers and &lt;a href="https://www.youtube.com/watch?v=21zduERRS3M&amp;amp;list=PLdo4fOcmZ0oXss45l49Q8h-Omuwo2FD-U&amp;amp;index=3&amp;amp;pp=gAQBiAQB" rel="noopener noreferrer"&gt;publish them to container registries&lt;/a&gt;. In addition, we have &lt;a href="https://aka.ms/learn-microservices" rel="noopener noreferrer"&gt;full training on Microsoft Learn&lt;/a&gt; for containers, microservices, and cloud-native development with .NET that I highly recommend you checkout.&lt;/p&gt;

&lt;p&gt;Thanks for joining me on this quick introduction to containers with .NET.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI-assisted content. This article was partially created with the help of AI. An author reviewed and revised the content as needed.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>docker</category>
      <category>aspnet</category>
    </item>
    <item>
      <title>.NET Monthly Roundup - August 2023 - .NET 8 Preview 7, Visual Studio releases, perf and GC fun!</title>
      <dc:creator>Jon Galloway</dc:creator>
      <pubDate>Fri, 08 Sep 2023 21:22:43 +0000</pubDate>
      <link>https://dev.to/dotnet/net-monthly-roundup-august-2023-net-8-preview-7-visual-studio-releases-perf-and-gc-fun-112</link>
      <guid>https://dev.to/dotnet/net-monthly-roundup-august-2023-net-8-preview-7-visual-studio-releases-perf-and-gc-fun-112</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/I1jGQH_VWKk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Welcome to our August .NET Monthly Roundup with Jon Galloway! In just 3 minutes, Jon breaks down the latest news from the month of August 2023 that .NET developers need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top links
&lt;/h3&gt;

&lt;p&gt;📚&lt;a href="http://aka.ms/dnmr-2308"&gt;All the links&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⭐.NET 8 Preview 5&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-7/"&gt;Announcing .NET 8 Preview 7&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-7/"&gt;ASP.NET Core updates in .NET 8 Preview 7&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://maoni0.medium.com/dynamically-adapting-to-application-sizes-2d72fcb6f1ea"&gt;Dynamically Adapting To Application Sizes | by Maoni0 | Aug, 2023 | Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💻Visual Studio and Tools&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-7-now-available/"&gt;Visual Studio 2022 – 17.7 Now Available &lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-8-preview-1-has-arrived/"&gt;Visual Studio 2022 17.8 Preview 1 has arrived! &lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/safely-use-secrets-in-http-requests-in-visual-studio-2022/"&gt;Safely use secrets in HTTP requests in Visual Studio 2022 &lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-for-mac-retirement-announcement/"&gt;Visual Studio for Mac Retirement Announcement &lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/announcing-the-unity-extension-for-visual-studio-code/"&gt;Announcing the Unity extension for Visual Studio Code &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❤️Community Links and Events&lt;br&gt;
➡️&lt;a href="https://khalidabuhakmeh.com/dotnet-8-interceptors"&gt;.NET 8 Interceptors | Khalid Abuhakmeh&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://www.jimmybogard.com/tales-from-the-net-migration-trenches/"&gt;Tales from the .NET Migration Trenches - Intro&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://andrewlock.net/exploring-the-dotnet-8-preview-keyed-services-dependency-injection-support/"&gt;Keyed service dependency injection container support&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-conf-2023-celebrating-the-release-of-dotnet-8-save-the-date/"&gt;.NET Conf 2023 - Celebrating the Release of .NET 8! - Save the Date!&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://www.dotnetconf.net/"&gt;.NET Conf 2023&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What did you think?
&lt;/h3&gt;

&lt;p&gt;With so much new information coming at you each month, we're looking at ways to bring you the highlights. Let us know if this helps, and how we can do it better next month!&lt;/p&gt;

&lt;p&gt;Jon&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>visualstudio</category>
      <category>aspnet</category>
    </item>
    <item>
      <title>Leveraging Existing Web Content to Build Hybrid Apps with .NET MAUI</title>
      <dc:creator>James Montemagno</dc:creator>
      <pubDate>Fri, 04 Aug 2023 16:20:55 +0000</pubDate>
      <link>https://dev.to/dotnet/leveraging-existing-web-content-to-build-hybrid-apps-with-net-maui-48me</link>
      <guid>https://dev.to/dotnet/leveraging-existing-web-content-to-build-hybrid-apps-with-net-maui-48me</guid>
      <description>&lt;p&gt;Are you a web developer intrigued by the idea of building native mobile &amp;amp; desktop applications? If you've been developing with Angular, React, or even just HTML and JavaScript, there's good news for you! In this post, we'll explore how you can leverage your existing web content to build native iOS, Android, Mac, and Windows apps using .NET MAUI and the experimental &lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KAU9SLm1nn0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Reuse Web Content?
&lt;/h2&gt;

&lt;p&gt;Imagine being able to reuse all the goodness you've created with your chosen web frameworks in your native mobile apps. By leveraging your existing web development skills, you can save time and effort by not starting from scratch with native mobile development. Plus, you can bring the power of your web components, designs, and functionality to the native world.&lt;/p&gt;

&lt;p&gt;Additionally, building native apps with .NET MAUI enables you to access native APIs and controls, giving you the best of both worlds. You can mix and match UI components, create a seamless user experience, and even access platform-specific features. The possibilities are practically endless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing .NET MAUI
&lt;/h2&gt;

&lt;p&gt;.NET MAUI is a powerful framework that builds on top of .NET for iOS, Android, Mac, and Windows (WinUI3), allowing you to create native apps with a unified API. I provides a single robust framework to make cross-platform app development easier than ever before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1185nqzbsoj7vv37tng9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1185nqzbsoj7vv37tng9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of the box, .NET MAUI enables you to use C# and XAML to build native UIs from shared code and access the underlying native APIs from C#. You have the flexibility to create apps that run on multiple platforms without sacrificing the performance and user experience provided by native controls and APIs.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/DuNLR_NJv8U"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Hybrid Apps with Blazor Hybrid
&lt;/h2&gt;

&lt;p&gt;If you're a Blazor developer, you're in luck! Blazor developers can easily reuse their Blazor components between their web applications and .NET MAUI applications. This powerful capability is included "in the box" which allows you to blend native and web UI components seamlessly.&lt;/p&gt;

&lt;p&gt;You can mix Blazor and native controls to create a unified and consistent user interface. This means you can build your UIs once and use them across different platforms, reducing development effort and ensuring a consistent user experience. The hybrid web view experiment offers great potential for Blazor developers looking to extend their apps to the native mobile world.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lqLfY9zNKNY"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Hybrid Apps with HTML, JavaScript, Angular, or React
&lt;/h2&gt;

&lt;p&gt;.NET MAUI doesn't limit you to just Blazor. You can also leverage your skills in HTML, JavaScript, Angular, or React to build hybrid apps with .NET Maui. This is made possible by the introduction of the experimental &lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;, which enables you to incorporate web content into your native apps seamlessly.&lt;/p&gt;

&lt;p&gt;To get started, you'll need to add the &lt;code&gt;Ejl.MauiHybridWebView&lt;/code&gt; NuGet package to your MAUI app. This package provides all the necessary functionality for integrating web content. Once added, you can create your HTML, JavaScript, and CSS files to define the web user interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lf5j4fhpt47yjocq11k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lf5j4fhpt47yjocq11k.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hybrid web view works by embedding a native web view control into your app, allowing it to display your web content using the platform's native rendering capabilities. This ensures a consistent look and feel across different platforms, while still giving you the freedom to use your preferred web technologies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take It Further - Full React Application
&lt;/h2&gt;

&lt;p&gt;If you want to take it a step further, you can even embed an entire React application within your .NET MAUI app. This is made possible by the flexibility and power of the HybridWebView to incorporate complex web applications into native apps seamlessly and communicate between JavaScript and C#.&lt;/p&gt;

&lt;p&gt;By embedding a React application, you can bring the full power of React's component-centric approach to your native app development. This allows you to create highly interactive and dynamic user interfaces, leveraging the extensive React ecosystem of libraries and components. All while access native APIs and business logic written in C#.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkvotuqrzu25n8aftrlb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkvotuqrzu25n8aftrlb.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the capability to integrate web technology like React into your .NET MAUI apps, the possibilities for creating rich, engaging, and performant mobile experiences are virtually limitless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building native apps doesn't have to mean starting from scratch. With .NET MAUI, you can leverage your existing web development skills and components to create powerful and feature-rich native apps. Whether you're using Blazor, Angular, React, or just HTML and JavaScript, .NET MAUI provides a unified platform to build cross-platform apps that deliver native performance and access to native features.&lt;/p&gt;

&lt;p&gt;So, why not explore the possibilities of reusing your existing web content with .NET MAUI? Start building your native mobile apps today and discover the countless opportunities to create amazing experiences for your users.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/dotnet/maui/" rel="noopener noreferrer"&gt;.NET MAUI official documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/Ejl.MauiHybridWebView" rel="noopener noreferrer"&gt;Ejl.Maui.HybridWebView NuGet package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Eilon/MauiHybridWebView" rel="noopener noreferrer"&gt;HybridWebView&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was partially created with the help of AI. James reviewed and revised the content as needed.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>blazor</category>
      <category>aspnetcore</category>
      <category>dotnetmaui</category>
    </item>
    <item>
      <title>.NET Monthly Roundup - June 2023 - .NET 8 Preview 5, VS News, and more!</title>
      <dc:creator>Jon Galloway</dc:creator>
      <pubDate>Fri, 07 Jul 2023 20:54:39 +0000</pubDate>
      <link>https://dev.to/dotnet/net-monthly-roundup-june-2023-net-8-preview-5-vs-news-and-more-5gpe</link>
      <guid>https://dev.to/dotnet/net-monthly-roundup-june-2023-net-8-preview-5-vs-news-and-more-5gpe</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/r4UmC8AwhUc"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Welcome to our June .NET Monthly Roundup with Jon Galloway! In just 3 minutes, Jon breaks down the latest news from the month of June 2023 that .NET developers need to know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Top links
&lt;/h3&gt;

&lt;p&gt;📚&lt;a href="http://aka.ms/dnmr-2306"&gt;All the links&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⭐.NET 8 Preview 5&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-preview-5/"&gt;Announcing .NET 8 Preview 5&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-preview-5/"&gt;ASP.NET Core updates in .NET 8 Preview 5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💻Visual Studio and Tools&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/vs-toolbox-accelerate-your-builds-of-sdk-style-net-projects/"&gt;Visual Studio Toolbox: Accelerate your builds of SDK-style .NET projects&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-7-preview-2-is-here/"&gt;Visual Studio 2022 17.7 Preview 2 is here!&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/visualstudio/announcing-csharp-dev-kit-for-visual-studio-code/"&gt;Announcing C# Dev Kit for Visual Studio Code&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://devblogs.microsoft.com/dotnet/upgrade-assistant-cli/"&gt;Announcing an update for .NET Upgrade Assistant with a new CLI tool!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;❤️Community Links and Events&lt;br&gt;
➡️&lt;a href="https://andrewlock.net/exploring-the-dotnet-8-preview-using-the-new-configuration-binder-source-generator/"&gt;Using the new configuration binder source generator&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://fsharpconf.com/"&gt;fsharpConf - The F# Community Virtual Conference&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://www.youtube.com/playlist?list=PLdo4fOcmZ0oX_35CaKKDex9mNiN-tVaBn"&gt;fsharpConf 2023 - YouTube&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://blog.jetbrains.com/dotnet/2023/07/05/net-annotated-monthly-july-2023/"&gt;.NET Annotated Monthly | July 2023 | The .NET Tools Blog&lt;/a&gt;&lt;br&gt;
➡️&lt;a href="https://mailchi.mp/dotnetfoundation/june2023"&gt;.NET Foundation news and updates from June&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What did you think?
&lt;/h3&gt;

&lt;p&gt;With so much new information coming at you each month, we're looking at ways to bring you the highlights. Let us know if this helps, and how we can do it better next month!&lt;/p&gt;

&lt;p&gt;Jon&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>visualstudio</category>
      <category>aspnetcore</category>
    </item>
  </channel>
</rss>
