<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <title>ABP.IO Stories</title>
    <link>https://abp.io/community/articles</link>
    <description>A hub for ABP Framework, .NET, and software development. Access articles, tutorials, news, and contribute to the ABP community.</description>
    <lastBuildDate>Sun, 04 Oct 2026 00:34:48 Z</lastBuildDate>
    <generator>Community - ABP.IO</generator>
    <image>
      <url>https://abp.io/assets/favicon.ico/favicon-32x32.png</url>
      <title>ABP.IO Stories</title>
      <link>https://abp.io/community/articles</link>
    </image>
    <a10:link rel="self" type="application/rss+xml" title="self" href="https://abp.io/community/rss?member=ismcagdas" />
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/.net-aspire-9.0-features-q7nojisw</guid>
      <link>https://abp.io/community/posts/.net-aspire-9.0-features-q7nojisw</link>
      <a10:author>
        <a10:name>ismcagdas</a10:name>
        <a10:uri>https://abp.io/community/members/ismcagdas</a10:uri>
      </a10:author>
      <category>dotnet-9.0</category>
      <title>.NET Aspire 9.0 Features</title>
      <description>.NET Aspire 9.0 is the next major release, supporting both .NET 8 and .NET 9. This version includes new features and improvements.</description>
      <pubDate>Wed, 13 Nov 2024 08:33:31 Z</pubDate>
      <a10:updated>2026-10-03T18:52:53Z</a10:updated>
      <content:encoded><![CDATA[<h1>Aspire 9.0 Features</h1>
<p>Aspire 9.0 is the next major release, supporting both .NET 8 and .NET 9. This version includes new features and improvements.</p>
<h2>Upgrade to Aspire</h2>
<p>Now, you don't need workloads to develop Aspire applications. In your project, you can add an SDK reference to <code>Aspire.AppHost.Sdk</code>.
For more information, you can check out <a href="https://aspire.dev/whats-new/aspire-9/#upgrade-to-aspire-9">https://aspire.dev/whats-new/aspire-9/#upgrade-to-aspire-9</a> which explains upgrading an existing project in details.</p>
<h2>Dashboard</h2>
<p>Aspire offers a nice dashboard for developers to observe the performance and behavior of their applications. In this version, there are some enhancements;</p>
<ul>
<li><strong>Manage resource lifecycle</strong>: You can stop, start, and restart resources.</li>
<li><strong>Mobile and responsive support</strong>: The Aspire dashboard is now mobile-friendly.</li>
<li><strong>Sensitive properties</strong>: Properties can be marked as sensitive, automatically masking them in the dashboard UI.</li>
<li><strong>Volumes</strong>: Configured container volumes are listed in resource details.</li>
<li><strong>Health checks</strong>: Aspire 9 adds support for health checks.</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-05-.NET%20Aspire%209.0%20Features/aspire_resource_lifecycle.jpg" alt="Resource Lifecycle" /></p>
<h2>Telemetry</h2>
<p>Aspire 9 comes with many new features to the Telemetry service.</p>
<ul>
<li><strong>Improve telemetry filtering</strong>: Telemetry data can now be filtered by attribute values.</li>
<li><strong>Combine telemetry from multiple resources</strong>: If a resource has multiple replicas, you can now filter telemetry data to view from all instances.</li>
<li><strong>Browser telemetry support</strong>: The dashboard now supports OpenTelemetry Protocol (OTLP) over HTTP and cross-origin resource sharing (CORS).</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-05-.NET%20Aspire%209.0%20Features/aspire_trace_filter.jpg" alt="Telemetry Filtering" /></p>
<h2>Orchestration</h2>
<p>The .NET App Host is a core component of the .NET runtime that helps launch and execute .NET applications.
Aspire 9 introduces many new features to the app host. Let's take a look;</p>
<ul>
<li><strong>Waiting for dependencies</strong>: You can configure a resource to wait for another resource to start before starting.</li>
<li><strong>Resource health checks</strong>: The <code>Waiting for dependencies</code> feature uses health checks to determine if a resource is ready.</li>
</ul>
<h2>Integrations</h2>
<p>Aspire has integrations with some services and tools that make it easy to get started. New integrations are coming with Aspire 9.</p>
<ul>
<li>Redis Insight</li>
<li>OpenAI (Preview)</li>
<li>MongoDB</li>
<li>Azure</li>
</ul>
<p>For Azure part, it is better to check the official documentation here <a href="https://aspire.dev/whats-new/aspire-9/#important-azure-improvements">https://aspire.dev/whats-new/aspire-9/#important-azure-improvements</a> because it has a very detailed explanation.</p>
<h2>ABP Studio</h2>
<p>Aspire and <a href="https://abp.io/studio">ABP Studio</a> are tools for different purposes with different scopes, and they have different approaches to solving problems; many developers may still be confused since they also have some similar functionalities and solve some common problems. You can check the comparison of Aspire and ABP Studio in this <a href="https://abp.io/community/articles/.net-aspire-vs-abp-studio-side-by-side-t1c73d1l">article</a>.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/images/others/blank-cover-image-150_79.png" />
      <media:content url="https://abp.io/images/others/blank-cover-image-150_79.png" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/.net-8-serialization-improvements-e7j8qk82</guid>
      <link>https://abp.io/community/posts/.net-8-serialization-improvements-e7j8qk82</link>
      <a10:author>
        <a10:name>ismcagdas</a10:name>
        <a10:uri>https://abp.io/community/members/ismcagdas</a10:uri>
      </a10:author>
      <category>dotnet</category>
      <category>net8</category>
      <title>.NET 8: Serialization Improvements</title>
      <description>In this article, I will explain serialization and deserialization improvements come with .NET 8</description>
      <pubDate>Tue, 07 Nov 2023 06:44:39 Z</pubDate>
      <a10:updated>2026-10-03T18:35:54Z</a10:updated>
      <content:encoded><![CDATA[<h1>.NET 8: Serialization Improvements</h1>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json">System.Text.Json</a> namespace provides functionality for serializing to and deserializing from JSON. In .NET 8, there have been many improvements to the System.Text.Json serialization and deserialization functionality.</p>
<h2>Source generator</h2>
<p>.NET 8 includes enhancements of the System.Text.Json source generator that are aimed at making the Native AOT experience on par with the reflection-based serializer. This is important because now you can select the source generator for System.Text.Json. To see a comparison of Reflection versus source generation in System.Text.Json, check out the comparison <a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/reflection-vs-source-generation?pivots=dotnet-8-0#reflection">documentation</a>.</p>
<h2>Interface hierarchies</h2>
<p>.NET 8 adds support for serializing properties from interface hierarchies. Here is a code sample that shows this feature.</p>
<pre><code class="language-csharp">ICar car = new MyCar { Color = &quot;Red&quot;, NumberOfWheels = 4 };
JsonSerializer.Serialize(car); // {&quot;Color&quot;:&quot;Red&quot;,&quot;NumberOfWheels&quot;:4}

public interface IVehicle
{
    public string Color { get; set; }
}

public interface ICar : IVehicle
{
    public int NumberOfWheels { get; set; }
}

public class MyCar : ICar
{
    public string Color { get; set; }
    public int NumberOfWheels { get; set; }
}
</code></pre>
<h2>Naming policies</h2>
<p>Two new naming policies <code>snake_case</code> and <code>kebab-case</code> have been added. You can use them as shown below:</p>
<pre><code class="language-csharp">var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
JsonSerializer.Serialize(new { CreationTime = new DateTime(2023,11,6) }, options); // {&quot;creation_time&quot;:&quot;2023-11-06T00:00:00&quot;}
</code></pre>
<h2>Read-only properties</h2>
<p>With .NET 8, you can deserialize onto read-only fields or properties. This feature can be globally enabled by setting <code>PreferredObjectCreationHandling</code> to <code>JsonObjectCreationHandling.Populate</code>. You can also enable this feature for a class or one of its members by adding the <code>[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]</code> attribute. Here is a sample:</p>
<pre><code class="language-csharp">using System.Text.Json;
using System.Text.Json.Serialization;

var book = JsonSerializer.Deserialize&lt;Book&gt;(&quot;&quot;&quot;{&quot;Contributors&quot;:[&quot;John Doe&quot;],&quot;Author&quot;:{&quot;Name&quot;:&quot;Sample Author&quot;}}&quot;&quot;&quot;)!;
Console.WriteLine(JsonSerializer.Serialize(book));

class Author
{
    public required string Name { get; set; }
}

[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
class Book
{
    // Both of these properties are read-only.
    public List&lt;string&gt; Contributors { get; } = new();
    public Author Author { get; } = new() {Name = &quot;Undefined&quot;};
}
</code></pre>
<p>Before .NET 8, the output was like this:</p>
<pre><code class="language-json">{&quot;Contributors&quot;:[],&quot;Author&quot;:{&quot;Name&quot;:&quot;Undefined&quot;}}
</code></pre>
<p>With .NET 8, the output now looks like this:</p>
<pre><code class="language-json">{&quot;Contributors&quot;:[&quot;John Doe&quot;],&quot;Author&quot;:{&quot;Name&quot;:&quot;Sample Author&quot;}}
</code></pre>
<h2>Disable reflection-based default</h2>
<p>One of the nice features about Serialization is, now you can disable using the reflection-based serializer by default. To disable default reflection-based serialization, set the <code>JsonSerializerIsReflectionEnabledByDefault</code> MSBuild property to <code>false</code> in your project file.</p>
<h2>Streaming deserialization APIs</h2>
<p>.NET 8 includes new <code>IAsyncEnumerable&lt;T&gt;</code> streaming deserialization extension methods. The new extension methods invoke streaming APIs and return <code>IAsyncEnumerable&lt;T&gt;</code>. Here is a sample code that uses this new feature.</p>
<pre><code class="language-csharp">const string RequestUri = &quot;https://yourwebsite.com/api/saas/tenants?skipCount=0&amp;maxResultCount=10&quot;;
using var client = new HttpClient();
IAsyncEnumerable&lt;Tenant&gt; tenants = client.GetFromJsonAsAsyncEnumerable&lt;Tenant&gt;(RequestUri);

await foreach (Tenant tenant in tenants)
{
    Console.WriteLine($&quot;* '{tenant.name}' uses '{tenant.editionName
}' edition&quot;);
}
</code></pre>
<p>I have mentioned some of the items for Serialization Improvements in .NET 8. If you want to check the full list, you can read it in the .NET 8's <a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#serialization">What's new document</a>.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/images/others/blank-cover-image-150_79.png" />
      <media:content url="https://abp.io/images/others/blank-cover-image-150_79.png" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/model-building-conventions-in-entity-framework-core-7.0-vo0hk68e</guid>
      <link>https://abp.io/community/posts/model-building-conventions-in-entity-framework-core-7.0-vo0hk68e</link>
      <a10:author>
        <a10:name>ismcagdas</a10:name>
        <a10:uri>https://abp.io/community/members/ismcagdas</a10:uri>
      </a10:author>
      <category>entity-framework-core</category>
      <category>model-building</category>
      <title>Model building conventions in Entity Framework Core 7.0</title>
      <description>In this article, I will show you one of the new features of EF Core 7 named "Model building conventions".

</description>
      <pubDate>Tue, 29 Nov 2022 05:11:00 Z</pubDate>
      <a10:updated>2026-10-03T18:38:51Z</a10:updated>
      <content:encoded><![CDATA[<h1>Model building conventions in Entity Framework Core 7.0</h1>
<p>In this article, I will show you one of the new features of EF Core 7 named &quot;Model building conventions&quot;.</p>
<p>Entity Framework Core uses a metadata model to describe how entity types are mapped to the database. Before EF Core 7.0, it was not possible to remove or replace existing conventions or add new conventions. With EF Core 7.0, this is now possible. To read more about it, you can visit its <a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/whatsnew#model-building-conventions">documentation</a>.</p>
<p>EF Core uses many built-in conventions. You can see the full list of the conventions on <code>IConvetion</code> Interface API <a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.conventions.iconvention?view=efcore-7.0">documentation</a>.</p>
<p>If you want to add, remove or replace a convention, you need to override <code>ConfigureConventions</code> method of your DbContext as shown below;</p>
<pre><code class="language-csharp">protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ =&gt;  new MyCustomConvention());
}
</code></pre>
<h2>Allowed Operations</h2>
<h3>Removing an existing convention</h3>
<p>Existing conventions provided by EF Core are well thought and useful, but sometimes some of them might not be a good candidate for your application. In such cases, you can remove an existing convention as shown below;</p>
<pre><code class="language-csharp">protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}
</code></pre>
<h3>Adding a new convention</h3>
<p>Just like removing a convention, we can add a completely new convention as well. You can define many different conventions here. For example, you can specify a standard precision for all decimal fields in your entities.</p>
<pre><code class="language-csharp">public class DecimalPrecisionConvention : IModelFinalizingConvention
    {
        public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext&lt;IConventionModelBuilder&gt; context)
        {
            foreach (var property in modelBuilder.Metadata.GetEntityTypes()
                         .SelectMany(
                             entityType =&gt; entityType.GetDeclaredProperties()
                                 .Where(
                                     property =&gt; property.ClrType == typeof(decimal))))
            {
                property.Builder.HasPrecision(2);
            }
        }
    }
</code></pre>
<p>Note that, conventions are executed in the order they are added. So you need to be careful in which order they are added.</p>
<h3>Replacing an existing convention</h3>
<p>Sometimes, a default convention might work slightly different than what your app expects. In such cases, you can create your own implementation by inheriting from that convention and replace the default one. For example, you can create a convention as shown below;</p>
<pre><code class="language-csharp">public class MyCustomConvention : ADefaultEfCoreConvention
{
    public MyCustomConvention(ProviderConventionSetBuilderDependencies dependencies)
            : base(dependencies)
        {
        }    
    // override the methods you want to change.
}
</code></pre>
<p>Then, you can replace the default one with your implementation as shown below;</p>
<pre><code class="language-csharp">protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Replace&lt;ADefaultEfCoreConvention&gt;(
        serviceProvider =&gt; new MyCustomConvention(
            serviceProvider.GetRequiredService&lt;ProviderConventionSetBuilderDependencies&gt;()));
}
</code></pre>
<p>As a final note, conventions never override configuration marked as <strong>DataAnnotation</strong> or <strong>Explicit</strong>. This means that, even if there is a convention, if the property has a <code>DataAnnotation</code> attribute or configuration in <code>OnModelCreating</code>, convetion will not be used. Here are the configuration types EF Core uses;</p>
<ul>
<li><strong>Explicit:</strong> The model element was explicitly configured in OnModelCreating</li>
<li><strong>DataAnnotation:</strong> The model element was configured using a mapping attribute (aka data annotation) on the CLR type</li>
<li><strong>Convention:</strong> The model element was configured by a model building convention</li>
</ul>
<h2>Using in ABP-based solution</h2>
<p>Since ABP uses EF Core, you can use this feature in ABP as well.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/images/others/blank-cover-image-150_79.png" />
      <media:content url="https://abp.io/images/others/blank-cover-image-150_79.png" medium="image" />
    </item>
  </channel>
</rss>