<?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>Mon, 02 Mar 2026 18:30:14 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=alper" />
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/ndc-london-2026-from-a-developers-perspective-and-my-personal-notes-about-ai-07wp50yl</guid>
      <link>https://abp.io/community/posts/ndc-london-2026-from-a-developers-perspective-and-my-personal-notes-about-ai-07wp50yl</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>ai</category>
      <category>conference</category>
      <category>.net</category>
      <category>ndc</category>
      <category>ndclondon2026</category>
      <title>NDC London 2026: From a Developer’s Perspective and My Personal Notes about AI</title>
      <description>Insights from NDC London 2026: AI's impact on software development, featuring talks from GitHub's Damian Brady, Steve Sanderson on Copilot agents, Kevlin Henney on modular monoliths, and more.</description>
      <pubDate>Fri, 06 Feb 2026 11:52:53 Z</pubDate>
      <a10:updated>2026-03-02T16:49:35Z</a10:updated>
      <content:encoded><![CDATA[<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/0.png" alt="Cover" /></p>
<p>This year we attended NDC London as a sponsor for <a href="https://abp.io">ABP</a>.  The conference was held at the same place <a href="https://qeiicentre.london/">Queen Elizabeth II</a> as previous years. I guess this is the best conf for .NET developers around the world (thanks to the NDC team). And we attend last 5 years. It was 3 full days started from 28 to 30 January 2026. As an exhibitor we talked a lot with the attendees who stopped by our booth or while we were eating or in the conf rooms.</p>
<p>This is the best opportunity to know what everyone is doing in software society. While I was explaining ABP to the people who first time heard, I also ask about what they do in their work. Developers mostly work on web platforms. And as you know, there's an AI transformation in our sector. That's why I wonder if other people also stick to the latest AI trend! Well... not as I expected. In Volosoft, we are tightly following AI trends, using in our daily development, injecting this new technology to our product and trying to benefit this as much as possible.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/1.png" alt="Our booth" /></p>
<p>This new AI trend is same as the invention of printing (by Johannes Gutenberg in 1450) or it's similar to invention of calculators (by William S. Burroughs in 1886). The countries who benefit these inventions got a huge increase in their welfare level. So, we welcome this new AI invention in software development, design, devops and testing. I also see this as a big wave in the ocean, if you are prepared and develop your skills, you can play with it 🌊 and it's called surfing or you'll die against the AI wave in this ocean.  But not all the companies react this transformation quickly. Many developers use it like ChatGpt conversation (copy-paste from it) or using GitHub Co-Pilot in a limited manner. But as I heard from Steven Sanderson's session and other Microsoft employees, they are already using it to reproduce the bugs reported in the issues or creating even feature PRs via Co-Pilot. That's a good!</p>
<p>Here're some pictures from the conf and that's me on the left side with brown shoes :)</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/2.png" alt="Alper &amp; Halil" /></p>
<p>Another thing I see, there's a decrease in the number of attendees'. I don't know the real reason but probably the IT companies cut the budget for conferences. As you also hear, many companies layoff because of the AI replaces some of the positions.</p>
<p>The food was great during the conference. It was more like eating sessions for me. Lots of good meals from different countries' kitchen. In the second day, there was a party. People grabbed their beers, wines, beverages and did some networking.</p>
<p>I was expecting more AI oriented sessions but it was less then my expectations. Even though I was an exhibitor, I tried to attend some of the session. I'll tell you my notes.</p>
<hr />
<p>Here's a quick video from the exhibitors' area on the 3rd floor and our ABP booth's Xbox raffle:</p>
<p><strong>Video 1: NDC Conference 2026 Environment</strong> 👉 <a href="https://youtu.be/U1kiYG12KgA">https://youtu.be/U1kiYG12KgA</a></p>
<p><a href="https://youtu.be/U1kiYG12KgA"><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/youtube-cover-1.png" alt="Video 1" /></a></p>
<p><strong>Video 2: Our raffle for XBOX</strong> 👉 <a href="https://youtu.be/7o0WX70qYw0">https://youtu.be/7o0WX70qYw0</a>
<a href="https://youtu.be/7o0WX70qYw0"><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/youtube-cover-2.png" alt="Video 2" /></a></p>
<hr />
<h2>Sessions / Talks</h2>
<h3>The Dangers of Probably-Working Software | Damian Brady</h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/3.png" alt="Damian Session" /></p>
<p>The first session and keynote was from Damian Brady. He's part of Developer Advocacy team at GitHub. And the topic was &quot;The dangers of probably-working software&quot;. He started with some negative impact of how generative AI is killing software, and he ended like this a not so bad, we can benefit from the AI transformation. First time I hear &quot;sleepwalking&quot; term for the development. He was telling when we generate code via AI, and if we don't review well-enough, we're sleepwalkers. And that's correct! and good analogy for this case. This talk centers on a powerful lesson: <em>“<strong>Don’t ship code you don’t truly understand.</strong>”</em>
Damian tells a personal story from his early .NET days when he implemented a <strong>Huffman compression algorithm</strong> based largely on Wikipedia. The code <strong>“worked” in small tests</strong> but <strong>failed in production</strong>. The experience forced him to deeply understand the algorithm rather than relying on copied solutions. Through this story, he explores themes of trust, complexity, testing, and mental models in software engineering.</p>
<h4>Notes From This Session</h4>
<ul>
<li>“It seems to work” is not the same as “I understand it.”</li>
<li>Code copied from Wikipedia or StackOverflow or AI platforms is inherently risky in production.</li>
<li>Passing tests on small datasets does not guarantee real-world reliability (happy path ~= unhappy results)</li>
<li>Performance issues often surface only in edge cases.</li>
<li>Delivery pressure can discourage deep understanding — to the detriment of quality.</li>
<li>Always ask: “<strong>When does this fail?</strong>” — not just “<strong>Why does this work?</strong>”</li>
</ul>
<hr />
<h3>Playing The Long Game | Sheena O'Connell</h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/4.png" alt="Sheena Session" /></p>
<p>Sheena is a former software engineer who now trains and supports tech educators. She talks about AI tools...
AI tools are everywhere but poorly understood; there’s hype, risks, and mixed results. The key question is how individuals and organisations should play the long game (long-term strategy) so skilled human engineers—especially juniors—can still grow and thrive.
She showed some statistics about how job postings on Indeed platform dramatically decreasing for software developers. About AI generated-code, she tells, it's less secure, there might be logical problems or interesting bugs, human might not read code very well and understanding/debugging code might sometimes take much longer time.</p>
<p>Being an engineer is about much more than a job title — it requires systems thinking, clear communication, dealing with uncertainty, continuous learning, discipline, and good knowledge management. The job market is shifting: demand for AI-skilled workers is rising quickly and paying premiums, and required skills are changing faster in AI-exposed roles. There’s strength in using a diversity of models instead of locking into one provider, and guardrails improve reliability.</p>
<p>AI is creating new roles (like AI security, observability, and operations) and new kinds of work, while routine attrition also opens opportunities. At the same time, heavy AI use can have negative cognitive effects: people may think less, feel lonelier, and prefer talking to AI over humans.</p>
<p>Organizations are becoming more dynamic and project-based, with shorter planning cycles, higher trust, and more experimentation — but also risk of “shiny new toy” syndrome. Research shows AI can boost productivity by 15–20% in many cases, especially in simpler, greenfield projects and popular languages, but it can actually reduce productivity on very complex work. Overall, the recommendation is to focus on using AI well (not just the newest model), add monitoring and guardrails, keep flexibility, and build tools that allow safe experimentation.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/4_1.png" alt="Sheena Session 2" /></p>
<p>We’re in a messy, fast-moving AI era where LLM tools are everywhere but poorly understood. There’s a lot of hype and marketing noise, making it hard even for technical people to separate reality from fantasy. Different archetypes have emerged — from AI-optimists to skeptics — and both extremes have risks. AI is great for quick prototyping but unreliable for complex work, so teams need guardrails, better practices, and a focus on learning rather than “writing more code faster.” The key question is how individuals and organizations can play the long game so strong human engineers — especially juniors — can still grow and thrive in an AI-driven world.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/4_2.png" alt="Sheena Session 3" /></p>
<hr />
<h3>Crafting Intelligent Agents with Context Engineering | Carly Richmond</h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/5.png" alt="Carly Session" /></p>
<p>Carly is a Developer Advocate Lead at Elastic in London with deep experience in web development and agile delivery from her years in investment banking. A practical UI engineer. She brings a clear, hands-on perspective to building real-world AI systems. In her talk on <strong>“Crafting Intelligent Agents with Context Engineering,”</strong> she argues that prompt engineering isn’t enough — and shows how carefully shaping context across data, tools, and systems is key to creating reliable, useful AI agents. She mentioned about the context of an AI process. The context consists of Instructions, Short Memory, Long Memory, RAG, User Prompts, Tools, Structured Output.</p>
<hr />
<h3>Modular Monoliths | Kevlin Henney</h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/6.png" alt="Kevlin Session" /></p>
<p>Kevlin frames the “microservices vs monolith” debate as a false dichotomy. His core argument is simple but powerful: problems rarely come from <em>being a monolith</em> — they come from being a <strong>poorly structured one</strong>. Modularity is not a deployment choice; it is an architectural discipline.</p>
<h4><strong>Notes from the Talk</strong></h4>
<ul>
<li>A monolith is not inherently bad; a tangled (intertwined, complex) monolith is.</li>
<li>Architecture is mostly about <strong>boundaries</strong>, not boxes.</li>
<li>If you cannot draw clean internal boundaries, you are not ready for microservices.</li>
<li>Dependencies reveal your real architecture better than diagrams.</li>
<li>Teams shape systems more than tools do.</li>
<li>Splitting systems prematurely increases complexity without increasing clarity.</li>
<li>Good modular design makes systems <strong>easier to change, not just easier to scale</strong>.</li>
</ul>
<h4><strong>So As a Developer;</strong></h4>
<ul>
<li>Start with a well-structured modular monolith before considering microservices.</li>
<li>Treat modules as real first-class citizens: clear ownership, clear contracts.</li>
<li>Make dependency direction explicit — no circular graphs.</li>
<li>Use internal architectural tests to prevent boundary violations.</li>
<li>Organize code by <em>capability</em>, not by technical layer.</li>
<li>If your team structure is messy, your architecture will be messy — fix people, not tech.</li>
</ul>
<hr />
<h3>AI Coding Agents &amp; Skills | Steve Sanderson</h3>
<p><strong>Being productive with AI Agents</strong></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk.png" alt="Steve Session" /></p>
<p>In this session, Steve started how Microsoft is excessively using AI tools for PRs, reproducing bug reports etc... He's now working on <strong>GitHub Co-Pilot Coding Agent Runtime Team</strong>. He says, we use brains and hands less then anytime.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_1.png" alt="image-20260206004021726" /></p>
<p><strong>In 1 Week 293 PRs Opened by the help of AI</strong></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_2.png" alt="image-20260206004403643" /></p>
<p><strong>He created a new feature to Copilot with the help of Copilot in minutes</strong></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_3.png" alt="Steve" /></p>
<blockquote>
<p>Code is cheap! Prototypes are almost free!</p>
</blockquote>
<p>And he summarized the AI assisted development into 10 outlines. These are  Subagents, Plan Mode, Skills, Delegate, Memories, Hooks, MCP, Infinite Sessions, Plugins and Git Workflow. Let's see his statements for each of these headings:</p>
<h4><strong>1. Subagents</strong></h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_4.png" alt="image-20260206005620904" /></p>
<ul>
<li>Break big problems into smaller, specialized agents.</li>
<li>Each subagent should have a clear responsibility and limited scope.</li>
<li>Parallel work is better than one “smart but slow” agent.</li>
<li>Reduces hallucination by narrowing context per agent.</li>
<li>Easier to debug: you can inspect each agent’s output separately.</li>
</ul>
<hr />
<h4><strong>2. Plan Mode</strong></h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_6.png" alt="steve-sanderson-talk_6" /></p>
<ul>
<li>Always start with a plan before generating code.</li>
<li>The plan should be explicit, human-readable, and reviewable.</li>
<li>You'll align your expectations with the AI's next steps.</li>
<li>Prevents wasted effort on wrong directions.</li>
<li>Encourages structured thinking instead of trial-and-error coding.</li>
</ul>
<hr />
<h4><strong>3. Skills</strong></h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_7.png" alt="steve-sanderson-talk_7" /></p>
<ul>
<li>These are just Markdown files but (can be also tools, scripts as well)</li>
<li>Skills are reusable capabilities for AI agents.</li>
<li>You cannot just give all the info (as Markdown) to the AI context (limited!), skills are being used when necessary (by their Description field)</li>
<li>Treat skills like APIs: versioned, documented, and shareable.</li>
<li>Prefer many small skills over one big skill set.</li>
<li>Store skills in Git, not in chat history.</li>
<li>Skills should integrate with real tools (CI, GitHub, browsers, etc.).</li>
</ul>
<h4>3.1 Skill &gt; Test Your Project Skill</h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_8.png" alt="steve-sanderson-talk_8" /></p>
<hr />
<h4><strong>4. Delegate</strong></h4>
<blockquote>
<p>didn't mention much about this topic</p>
</blockquote>
<ul>
<li>“Delegate” refers to <strong>offloading local work to the cloud</strong>.</li>
<li>Using remote computers for AI stuff not your local resources (agent continues the task remotely)</li>
</ul>
<h5><strong>Ralph Force Do While Over and Over Until It Finishes</strong></h5>
<p>https://awesomeclaude.ai/ralph-wiggum</p>
<blockquote>
<p>Who knows how much tokens it uses :)</p>
</blockquote>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_5.png" alt="image-20260206010621010" /></p>
<hr />
<h4><strong>5. Memories</strong></h4>
<blockquote>
<p>didn't mention much about this topic</p>
</blockquote>
<ul>
<li><p>It's like don't write tests like this but write like that, and AI will remember it among your team members.</p>
</li>
<li><p>Copilot Memory allows Copilot to learn about your codebase, helping Copilot coding agent, Copilot code review, and Copilot CLI to work more effectively in a repository.</p>
</li>
<li><p>Treat memory like documentation that evolves over time.</p>
</li>
<li><p>Copilot Memory is <strong>turned off by default</strong></p>
</li>
<li><p>https://docs.github.com/en/copilot/how-tos/use-copilot-agents/copilot-memory</p>
</li>
</ul>
<hr />
<h4><strong>6. Hooks</strong></h4>
<blockquote>
<p>didn't mention much about this topic</p>
</blockquote>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_10.png" alt="image-20260206015638169" /></p>
<ul>
<li>Execute custom shell commands at key points during agent execution.</li>
<li>Examples: pre-commit checks, PR reviews, test triggers.</li>
<li>Hooks make AI proactive instead of reactive.</li>
<li>They reduce manual context switching for developers.</li>
<li>https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/use-hooks</li>
</ul>
<hr />
<h4><strong>7. MCP</strong></h4>
<ul>
<li><p>Talk to external tools.</p>
</li>
<li><p>Enables safe, controlled access to systems (files, APIs, databases).</p>
</li>
<li><p>Prevents random tool usage; everything is explicit.</p>
</li>
</ul>
<hr />
<h4><strong>8. Infinite Sessions</strong></h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_11.png" alt="Infinite Sessions" /></p>
<ul>
<li>AI should remember the “project context,” not just the last message.</li>
<li>Reduces repetition and re-explaining.</li>
<li>Enables deeper reasoning over time.</li>
<li>Memory + skills + hooks together make “infinite sessions” possible.</li>
<li>https://docs.github.com/en/copilot/how-tos/copilot-cli/cli-best-practices#3-leverage-infinite-sessions</li>
</ul>
<hr />
<h4><strong>9. Plugins</strong></h4>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_12.png" alt="Plugins" /></p>
<ul>
<li>Extend AI capabilities beyond core model features.</li>
<li>https://github.com/marketplace?type=apps&amp;copilot_app=true</li>
</ul>
<hr />
<h4><strong>10. Git Workflow</strong></h4>
<ul>
<li>AI should operate inside your existing Git process.</li>
<li>Generate small, focused commits — not giant changes.</li>
<li>Use AI for PR descriptions and code reviews.</li>
<li>Keep humans in the loop for design decisions.</li>
<li>Branching strategy still matters; AI doesn’t replace it.</li>
<li>Treat AI like a junior teammate: helpful, but needs supervision.</li>
<li>CI + tests remain your primary safety net, not the model.</li>
<li>Keep feedback loops fast: generate → test → review → refine.</li>
</ul>
<p><strong>Copilot as SDK</strong></p>
<p>You can wrap GitHub CoPilot into your app as below:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/steve-sanderson-talk_9.png" alt="steve-sanderson-talk_9" /></p>
<h4><strong>As a Developer What You Need to Get from Steve's Talk;</strong></h4>
<ul>
<li>Coding agents work best when you treat them like programmable teammates, not autocomplete tools.</li>
<li>“Skills” are the right abstraction for scaling AI assistants across a team.</li>
<li>Treat skills like shared APIs: version them, review them, and store them in source control.</li>
<li>Skills can be installed from Git repos (marketplaces), not just created locally.</li>
<li>Slash commands make skills fast, explicit, and reproducible in daily workflow.</li>
<li>Use skills to bridge AI ↔ real systems (e.g., GitHub Actions, Playwright, build status).</li>
<li>Automation skills are most valuable when they handle end-to-end flows (browser + app + data).</li>
<li>Let the agent <em>discover</em> the right skill rather than hard-coding every step.</li>
<li>Skills reduce hallucination risk by constraining what the agent is allowed to do.</li>
</ul>
<hr />
<h3>My Personal Notes  about AI</h3>
<ul>
<li><p>This is your code tech stack for a basic .NET project:</p>
<ul>
<li><p>Assembly &gt; MSIL &gt; C# &gt; ASP.NET Core &gt; ...ABP... &gt;NuGet + NPM  &gt; Your Handmade Business Code</p>
<p>When we ask a development to an AI assisted IDE,  AI never starts from Assembly or even it's not writing an existing NPM package. It basically uses what's there on the market. So we know frameworks like ASP.NET Core, ABP will always be there after AI evolution.</p>
</li>
</ul>
</li>
<li><p>Software engineer is not just writing correct syntax code to explain a program to computer. As an engineer you need to understand the requirements, design the problem, make proper decisions and fix the uncertainty. Asking AI the right questions is very critical these days.</p>
</li>
<li><p>Tesla cars already started to go autonomous. As a driver, you don't need to care about how the car is driven. You need to choose the right way to go in the shortest time without hussle.</p>
</li>
<li><p>I talk with other software companies owners, they also say their docs website visits are down. I talked to another guy who's making video tutorials to Pluralsight, he's telling learning from video is decreasing nowadays...</p>
</li>
<li><p>Nowadays, <strong>developers big new issue is Reviewing the AI generated-code.</strong> In the future, developers who use AI, who inspect AI generated code well and who tells the AI exactly what's needed will be the most important topics. Others (who's typing only code) will be naturally eliminated. Invest your time for these topics.</p>
</li>
<li><p>We see that our brain is getting lazier, our coding muscles gets weaker day by day. Just like after calculator invention, we stopped calculate big numbers. We'll eventually forget coding. But maybe that's what it needs to be!</p>
</li>
<li><p>Also I don't think AI will replace developers. Think about washing machines. Since they came out, they still need humans to put the clothes in the machine, pick the best program, take out from the machine and iron. From now on, AI is our assistance in every aspect of our life from shopping, medical issues, learning to coding. Let's benefit from it.</p>
</li>
</ul>
<h4>Software and service stocks shed $830 billion in market value in six trading days</h4>
<p>Software stocks fall on AI disruption fears on Feb 4, 2026 in NASDAQ. Software and service stocks shed $830 billion in market value in six trading days. Scramble to shield portfolios as AI muddies valuations, business prospects.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-02-03-Impressions-of-NDC-London-2026/7.png" alt="Reuters" /></p>
<p><strong>We need to be well prepared for this war.</strong></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1f44f9-1a25-595f-c51d-d266aef62b4d" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1f44f9-1a25-595f-c51d-d266aef62b4d" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/which-opensource-pdf-libraries-are-recently-popular-a-datadriven-look-at-pdf-topic-g68q78it</guid>
      <link>https://abp.io/community/posts/which-opensource-pdf-libraries-are-recently-popular-a-datadriven-look-at-pdf-topic-g68q78it</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>pdf-generation</category>
      <category>Scryber.Core</category>
      <category>PDFTron</category>
      <title>Which Open-Source PDF Libraries Are Recently Popular ? A Data-Driven Look At PDF Topic</title>
      <description>Which .NET PDF libraries are actually popular in 2026? Real data on GitHub stars, daily downloads &amp; momentum scores for Playwright, QuestPDF, PDFsharp, iText &amp; more.</description>
      <pubDate>Mon, 19 Jan 2026 16:04:44 Z</pubDate>
      <a10:updated>2026-03-02T16:27:07Z</a10:updated>
      <content:encoded><![CDATA[<h1>Which Open-Source PDF Libraries Are Recently Popular ? A Data-Driven Look At PDF Topic</h1>
<p>So you're looking for a PDF library in .NET, right? Here's the thing - just because something has a million downloads doesn't mean it's what you should use <em>today</em>. I'm looking at <strong>recent download momentum</strong> (how many people are actually using it NOW via NuGet) and <strong>GitHub activity</strong> (are they still maintaining this thing or did they abandon it?).</p>
<p>I pulled data from the last ~90 days for the main players in the .NET PDF space. Here's what's actually happening:</p>
<h2>Popularity Comparison of  .NET PDF Libraries (<em>ordered by score</em>)</h2>
<p>| Library | GitHub Stars | Avg Daily NuGet Downloads | Total NuGet Downloads | <strong>Popularity Score</strong> |
|---------|---------------|-----------------------------|----------------------------|---------------------|
| <strong><a href="https://github.com/microsoft/playwright-dotnet">Microsoft.Playwright</a></strong> | <a href="https://github.com/microsoft/playwright-dotnet">2.9k</a> | <a href="https://www.nuget.org/packages/Microsoft.Playwright">23k</a> | 39M | <strong>71/100</strong> |
| <strong><a href="https://github.com/QuestPDF/QuestPDF">QuestPDF</a></strong> | <a href="https://github.com/QuestPDF/QuestPDF">13.7k</a> | <a href="https://www.nuget.org/packages/QuestPDF">8.2k</a> | 15M | <strong>54/100</strong> |
| <strong><a href="https://github.com/empira/PDFsharp">PDFsharp</a></strong> | <a href="https://github.com/empira/PDFsharp">862</a> | <a href="https://www.nuget.org/packages/PdfSharp">9k</a> | 47M | <strong>48/100</strong> |
| <strong><a href="https://github.com/itext/itext-dotnet">iText</a></strong> | <a href="https://github.com/itext/itext-dotnet">1.9k</a> | <a href="https://www.nuget.org/packages/itext">17.2k</a> | 16M | <strong>44/100</strong> |
| <strong><a href="https://github.com/hardkoded/puppeteer-sharp">PuppeteerSharp</a></strong> | <a href="https://github.com/hardkoded/puppeteer-sharp">3.8k</a> | <a href="https://www.nuget.org/packages/PuppeteerSharp">8.7k</a> | 26M | <strong>40/100</strong> |</p>
<p><strong>How I calculated the score:</strong> I weighted GitHub Stars (30%), Daily Downloads (40% - because that's what matters NOW), and Total Downloads (30% - for historical context). Everything normalized to 0-100 before weighting. Higher = better momentum overall.</p>
<h2>The Breakdown - What You Actually Need to Know</h2>
<h3><a href="https://docs.pdfsharp.net/">PDFsharp</a></h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-01-19-Trend-PDF-Libraries-For-CSharp/pdfsharp.png" alt="pdfsharp" /></p>
<p><strong>NuGet:</strong> <a href="https://www.nuget.org/packages/PdfSharp">PdfSharp</a> | <strong>GitHub:</strong> <a href="https://github.com/empira/PDFsharp">empira/PDFsharp</a></p>
<p><strong>What it does:</strong> Code-first PDF stuff - drawing, manipulating, merging, that kind of thing. Not for HTML/browser rendering though, so don't try to convert your React app to PDF with this.</p>
<p><strong>What's the vibe?</strong> <strong>Stable, but kinda old school.</strong> It's got the biggest total download count (47M!) but only pulling ~9k/day now. They updated it 2 weeks ago (Jan 6) so it's alive, and it supports .NET 8-10 which is nice. The GitHub stars (862) are pretty low compared to the shiny new kids, but honestly? It's been around forever and people still use it. It's the reliable old workhorse.</p>
<p><strong>Pick this if:</strong></p>
<ul>
<li>You need to build PDFs from scratch with code (not HTML)</li>
<li>You want to draw graphics, manipulate existing PDFs, merge files</li>
<li>You don't want browser engines anywhere near your project</li>
</ul>
<hr />
<h3><a href="https://itextpdf.com/">iText</a></h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-01-19-Trend-PDF-Libraries-For-CSharp/itext.jpg" alt="iText Logo" /></p>
<p><strong>NuGet:</strong> <a href="https://www.nuget.org/packages/itext/">itext</a> | <strong>GitHub:</strong> <a href="https://github.com/itext/itext-dotnet">itext/itext-dotnet</a></p>
<p><strong>What it does:</strong> The enterprise beast. Digital signatures, PDF compliance (PDF/A, PDF/UA), forms, all that fancy stuff. Can do HTML-to-PDF too if you need it.</p>
<p><strong>What's the vibe?</strong> <strong>Actually doing pretty well!</strong> ~17.2k downloads/day (highest for code-first libs), updated literally yesterday (Jan 18). They're moving fast. 1.9k stars isn't huge but the community seems active. The catch? This is the enterprise option - check the licensing before you commit if you're doing commercial work.</p>
<p><strong>Pick this if:</strong></p>
<ul>
<li>You need digital signatures, PDF compliance, or advanced form stuff</li>
<li>Your company is cool with licensing fees (or you're doing open source)</li>
<li>You need serious PDF manipulation features</li>
<li>You want HTML-to-PDF AND code-based generation in one package</li>
</ul>
<hr />
<h3><a href="https://playwright.dev/dotnet/">Microsoft.Playwright</a></h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-01-19-Trend-PDF-Libraries-For-CSharp/playwright.png" alt="Playwright Logo" /></p>
<p><strong>NuGet:</strong> <a href="https://www.nuget.org/packages/Microsoft.Playwright">Microsoft.Playwright</a> | <strong>GitHub:</strong> <a href="https://github.com/microsoft/playwright-dotnet">microsoft/playwright-dotnet</a></p>
<p><strong>What it does:</strong> Browser automation that can turn HTML/CSS/JS into PDFs. Uses real browser engines (Chromium, WebKit, Firefox) so your PDFs look exactly like they would in a browser.</p>
<p><strong>What's the vibe?</strong> <strong>Killing it.</strong> ~23k downloads/day (highest in this whole list!). It's Microsoft-backed so you know they're not gonna abandon it anytime soon. Last commit was December 3rd but honestly that's fine, they're actively maintaining. 2.9k stars and climbing. If you need to turn web pages into PDFs, this is probably your best bet right now.</p>
<p><strong>Pick this if:</strong></p>
<ul>
<li>You need to convert HTML/CSS/JS to PDF and want it to look EXACTLY like the browser</li>
<li>You're working with SPAs, dynamic content, or web templates</li>
<li>You also need browser automation/testing (bonus!)</li>
<li>Layout accuracy is critical (forms, dashboards, etc.)</li>
</ul>
<hr />
<h3><a href="https://www.puppeteersharp.com/">PuppeteerSharp</a></h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-01-19-Trend-PDF-Libraries-For-CSharp/PuppeteerSharp.png" alt="PuppeteerSharp Logo" /></p>
<p><strong>NuGet:</strong> <a href="https://www.nuget.org/packages/PuppeteerSharp">PuppeteerSharp</a> | <strong>GitHub:</strong> <a href="https://github.com/hardkoded/puppeteer-sharp">hardkoded/puppeteer-sharp</a></p>
<p><strong>What it does:</strong> Basically Playwright's older sibling. Uses headless Chromium to turn HTML into PDFs. Same idea, different API.</p>
<p><strong>What's the vibe?</strong> <strong>Stable but losing ground.</strong> Got updated last week (Jan 12) so it's maintained, but ~8.7k/day is way less than Playwright's ~23k. 3.8k stars is decent though. It works fine, but Playwright is eating its lunch. Still, if you know Puppeteer already or only need Chromium, this might be fine.</p>
<p><strong>Pick this if:</strong></p>
<ul>
<li>You already know Puppeteer from Node.js and want the same vibe in .NET</li>
<li>You only need Chromium (don't care about Firefox/WebKit)</li>
<li>You have existing Puppeteer code you're porting</li>
</ul>
<hr />
<h3><a href="https://github.com/QuestPDF/QuestPDF">QuestPDF</a></h3>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2026-01-19-Trend-PDF-Libraries-For-CSharp/QuestPDF.png" alt="QuestPDF Logo" /></p>
<p><strong>NuGet:</strong> <a href="https://www.nuget.org/packages/QuestPDF">QuestPDF</a> | <strong>GitHub:</strong> <a href="https://github.com/QuestPDF/QuestPDF">QuestPDF/QuestPDF</a></p>
<p><strong>What it does:</strong> Build PDFs with fluent C# APIs. Think of it like building a UI layout, but for PDFs. No HTML needed - it's all code, all .NET.</p>
<p><strong>What's the vibe?</strong> <strong>The community favorite.</strong> 13.7k stars (most by far!), updated yesterday (Jan 18). ~8.2k downloads/day isn't the highest but the community is clearly excited about it. Modern API, active dev, people seem to actually enjoy using it. If you're building reports/invoices from code and want something that feels modern, this is it.</p>
<p><strong>Pick this if:</strong></p>
<ul>
<li>You want to build PDFs with code (not HTML) and you like fluent APIs</li>
<li>You're generating reports, invoices, structured documents</li>
<li>You want zero browser dependencies</li>
<li>You care about type safety and maintainable code</li>
<li>You want something that feels modern and well-designed</li>
</ul>
<h2>Who's Winning Right Now?</h2>
<p>Here's what the numbers are telling us:</p>
<h3>Code-First Libraries (Building PDFs with Code)</h3>
<p><strong><a href="https://github.com/QuestPDF/QuestPDF">QuestPDF</a></strong> - Score: 54/100
The people's choice. Most GitHub stars (13.7k), updated yesterday, community loves it. Downloads aren't the highest but the engagement is real. This is what people are excited about.</p>
<p><strong><a href="https://github.com/itext/itext-dotnet">iText</a></strong> - Score: 44/100<br />
Actually pulling the most daily downloads (~17.2k/day) for code-first libs, also updated yesterday. The enterprise crowd is still using this heavily. Just watch that licensing.</p>
<p><strong><a href="https://github.com/empira/PDFsharp">PDFsharp</a></strong> - Score: 48/100
The old reliable. 47M total downloads but only ~9k/day now. It works, it's stable, but it's not where the momentum is. Still a solid choice if you need something battle-tested.</p>
<h3>HTML/Browser-Based Libraries (Turning Web Pages into PDFs)</h3>
<p><strong><a href="https://github.com/microsoft/playwright-dotnet">Microsoft.Playwright</a></strong> - Score: 71/100
Winner winner. ~23k downloads/day (highest overall), Microsoft backing, actively maintained. If you need HTML-to-PDF, this is probably the move.</p>
<p><strong><a href="https://github.com/hardkoded/puppeteer-sharp">PuppeteerSharp</a></strong> - Score: 40/100
Still kicking around at ~8.7k/day but Playwright is clearly the future. Updated last week so it's not dead, just... less popular.</p>
<h2>TL;DR - What Should You Actually Use?</h2>
<p><strong>Building PDFs from code (not HTML):</strong></p>
<ul>
<li><strong>QuestPDF</strong> - If you want something modern and the community is raving about it (13.7k stars!)</li>
<li><strong>iText</strong> - If you need enterprise features and can handle the licensing</li>
<li><strong>PDFsharp</strong> - If you want the battle-tested option that's been around forever</li>
</ul>
<p><strong>Converting HTML/web pages to PDF:</strong></p>
<ul>
<li><strong>Playwright</strong> - Just use this. It's winning right now (~23k/day), Microsoft-backed, actively maintained. Game over.</li>
<li><strong>PuppeteerSharp</strong> - Only if you really need Chromium-only or you're migrating from Node.js Puppeteer</li>
</ul>
<p><strong>Bottom line:</strong> For HTML-to-PDF, Playwright is dominating. For code-first, QuestPDF has the hype but iText has the downloads. Choose your fighter.</p>
<hr />
<p><em>Numbers from GitHub and NuGet as of January 19, 2026. Daily downloads are from the last 90 days.</em></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1ee92d-3886-c743-0e8e-1b2d4a4622a2" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1ee92d-3886-c743-0e8e-1b2d4a4622a2" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/my-first-look-and-experience-with-google-antigravity-0hr4sjtf</guid>
      <link>https://abp.io/community/posts/my-first-look-and-experience-with-google-antigravity-0hr4sjtf</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>cursor</category>
      <category>google</category>
      <category>antigravity</category>
      <category>ide</category>
      <category>try</category>
      <title>My First Look and Experience with Google AntiGravity</title>
      <description>Will Google AntiGravity Replace the Main Code Editor? Today, I tried out Google AntiGravity, the new code editor after Cursor. There are a few things I need to tell you..</description>
      <pubDate>Mon, 24 Nov 2025 13:18:12 Z</pubDate>
      <a10:updated>2026-03-02T14:01:39Z</a10:updated>
      <content:encoded><![CDATA[<h1>My First Look and Experience with Google AntiGravity</h1>
<h2>Is Google AntiGravity Going to Replace Your Main Code Editor?</h2>
<p>Today, I tried the new code-editor AntiGravity by Google. <em>&quot;It's beyond a code-editor</em>&quot; by Google 🙄
When I first launch it, I see the UI is almost same as Cursor. They're both based on Visual Studio Code.
That's why it was not hard to find what I'm looking for.</p>
<p>First of all, the main difference as I see from the Cursor is; when I type a prompt in the agent section <strong>AntiGravity first creates a Task List</strong> (like a road-map) and whenever it finishes a task, it checks the corresponding task. Actually Cursor has a similar functionality but AntiGravity took it one step further.</p>
<p>Second thing which was good to me; AntiGravity uses <a href="https://gemini.google/tr/overview/image-generation/">Nano Banana 🍌</a>. This is Google's AI image generation model... Why it's important because when you create an app, you don't need to search for graphics, deal with image licenses. <strong>AntiGravity generates images automatically and no license is required!</strong></p>
<p>Third exciting feature for me; <strong>AntiGravity is integrated with Google Chrome and can communicate with the running website</strong>. When I first run my web project, it installed a browser extension which can see and interact with my website. It can see the results, click somewhere else on the page, scroll, fill up the forms, amazing 😵</p>
<p>Another feature I loved is that <strong>you can enter a new prompt even while AntiGravity is still generating a response</strong> 🧐. It instantly prioritizes the latest input and adjusts the ongoing process if needed. But in Cursor, if you add a prompt before the cursor finishes, it simply queues it and runs it later 😔.</p>
<p>And lastly, <strong>AntiGravity is working very good with Gemini 3</strong>.</p>
<p>Well, everything was not so perfect 😥 When I tried AntiGravity, couple of times it stucked AI generation and Agent stopped. I faced errors like this 👇</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/errors.png" alt="Errors" /></p>
<h2>Debugging .NET Projects via AntiGravity</h2>
<p>⚠ There's a crucial development issue with AntiGravity (and also for Cursor, Windsurf etc...) 🤕 you <strong>cannot debug your .NET application with AntiGravity 🥺.</strong> <em>This is Microsoft's policy!</em> Microsoft doesn't allow debugging for 3rd party IDEs and shows the below error... That's why I cannot say it's a downside of AntiGravity. You need to use Microsft's original VS Code, Visual Studio or Rider for debugging.  But wait a while there's a workaround for this,  I'll let you know in the next section.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/debug.png" alt="Debugging" /></p>
<h3>What does this error mean?</h3>
<p>AntiGravity, Cursor, Windsurf etc... are using Visual Studio Code and  the C# extension for VS Code includes the Microsoft .NET Core Debugger &quot;<em>vsdbg</em>&quot;.
VS Code is open-source but &quot;<em>vsdbg</em>&quot; is not open-source! It's working only with Visual Studio Code, Visual Studio and Visual Studio for Mac. This is clearly stated at <a href="https://github.com/dotnet/vscode-csharp/blob/main/docs/debugger/Microsoft-.NET-Core-Debugger-licensing-and-Microsoft-Visual-Studio-Code.md">Microsoft's this link</a>.</p>
<h3>Ok! How to resolve debugging issue with AntiGravity? and Cursor and Windsurf...</h3>
<p>There's a free C# debugger extension for Visual Studio Code based IDEs that supports AntiGravity, Cursor and Windsurf. The extension name is <strong>C#</strong>.
You can download this free C# debugger extension at 👉 <a href="https://open-vsx.org/extension/muhammad-sammy/csharp/">open-vsx.org/extension/muhammad-sammy/csharp/</a>.
For AntiGravity open Extension window (<em>Ctrl + Shift + X</em>) and search for <code>C#</code>, there you'll see this extension.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/csharp-debug-extension.png" alt="C# Debugging Extension" /></p>
<p>After installing, I restarted AntiGravity and now I can see the red circle which allows me to add breakpoint on C# code.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/breakpoint.png" alt="Add C# Breakpoint" /></p>
<h3>Another Extension For Debugging .NET Apps on VS Code</h3>
<p>Recently I heard about DotRush extension from the folks. As they say DotRush works slightly faster and support Razor pages (.cshtml files).
Here's the link for DotRush https://github.com/JaneySprings/DotRush</p>
<h3>Finding Website Running Port</h3>
<p>When you run the web project via C# debugger extension, normally it's not using the <code>launch.json</code> therefore the website port is not the one when you start from Visual Studio / Rider... So what's my website's port which I just run now? Normally for ASP.NET Core <strong>the default port is 5000</strong>. You can try navigating to http://localhost:5000/.
Alternatively you can write the below code in <code>Program.cs</code> which prints the full address of your website in the logs.
If you do the steps which I showed you, you can debug your C# application via AntiGravity and other VS Code derivatives.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/find-website-port.png" alt="Find Website Port" /></p>
<h2>How Much is AntiGravity? 💲</h2>
<p>Currently there's only individual plan is available for personal accounts and that's free 👏! The contents of Team and Enterprise plans and prices are not announced yet. But <strong>Gemini 3 is not free</strong>! I used it with my company's Google Workspace account which we normally pay for Gemini.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/pricing.png" alt="Pricing" /></p>
<h2>More About AntiGravity</h2>
<p>There have been many AI assisted IDEs like <a href="https://windsurf.com/">Windsurf</a>, <a href="https://cursor.com/">Cursor</a>, <a href="https://zed.dev/">Zed</a>, <a href="https://replit.com/">Replit</a> and <a href="https://www.jetbrains.com/fleet/">Fleet</a>. But this time it's different, this is backed by Google.
As you see from the below image AntiGravity, uses a standard grid layout as others based on VS Code editor.
It's very similar to Cursor, Visual Studio, Rider.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/anti-gravity-ui.png" alt="AntiGravity UI" /></p>
<h2>Supported LLMs 🧠</h2>
<p>Antigravity offers the below models which supports reasoning: Gemini 3 Pro, Claude Sonnet 4.5, GPT-OSS</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/llms.png" alt="LLMs" /></p>
<p>Antigravity uses other models for supportive tasks in the background:</p>
<ul>
<li><strong>Nano banana</strong>: This is used to generate images.</li>
<li><strong>Gemini 2.5 Pro UI Checkpoint</strong>: It's for the browser subagent to trigger browser action such as clicking, scrolling, or filling in input.</li>
<li><strong>Gemini 2.5 Flash</strong>: For checkpointing and context summarization, this is used.</li>
<li><strong>Gemini 2.5 Flash Lite</strong>: And when it's need to make a semantic search in your code-base, this is used.</li>
</ul>
<h2>AntiGravity Can See Your Website</h2>
<p>This makes a big difference from traditional IDEs. AntiGravity's browser agent is taking screenshots of your pages when it needs to check. This is achieved by a Chrome Extension as a tool to the agent, and you can also prompt the agent to take a screenshot of a page. It can iterate on website designs and implementations, it can perform UI Testing, it can monitor dashboards, it can automate routine tasks like rerunning CI.
This is the link for the extension 👉 <a href="https://chromewebstore.google.com/detail/antigravity-browser-exten/eeijfnjmjelapkebgockoeaadonbchdd">chromewebstore.google.com/detail/antigravity-browser-exten/eeijfnjmjelapkebgockoeaadonbchdd</a>. AntiGravity will install this extension automatically on the first run.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/extension.png" alt="Browser Extension" /></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/extension-features.png" alt="Extension Features" /></p>
<h2>MCP Integration</h2>
<h3>When Do We Need MCP in a Code Editor?</h3>
<p>Simply if we want to connect to a 3rd party service to complete our task we need MCP. So AntiGravity can connect to your DB and write proper SQL queries or it can pull in recent build logs from Netlify or Heroku. Also you can ask AntiGravity to to connect GitHub for finding the best authentication pattern.</p>
<h3>AntiGravity Supports These MCP Servers</h3>
<p>Airweave, AlloyDB for PostgreSQL, Atlassian, BigQuery, Cloud SQL for PostgreSQL, Cloud SQL for MySQL, Cloud SQL for SQL Server, Dart, Dataplex, Figma Dev Mode MCP, Firebase, GitHub, Harness, Heroku, Linear, Locofy, Looker, MCP Toolbox for Databases, MongoDB, Neon, Netlify, Notion, PayPal, Perplexity Ask, Pinecone, Prisma, Redis, Sequential Thinking, SonarQube, Spanner, Stripe and Supabase.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/mcp.png" alt="MCP" /></p>
<h2>Agent Settings ⚙️</h2>
<p>The major settings of Agent are:</p>
<ul>
<li><strong>Agent Auto Fix Lints</strong>: I enabled this setting because I want the Agent automatically fixes its own mistakes for invalid syntax, bad formatting, unused variables, unreachable code or following coding standards... It makes extra tool calls that's why little bit expensive 🥴.</li>
<li><strong>Auto Execution</strong>: Sometimes Agent tries to build application or writing test code and running it, in these cases it executes command. I choose &quot;Turbo&quot; 🤜  With this option, Agent always runs the terminal command and controls my browser.</li>
<li><strong>Review Policy</strong>: How much control you are giving to agent 🙎. I choose &quot;Always Proceed&quot; 👌 because I mostly trust AI 😀. The Agent will never ask for review.</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-11-21-AntiGravity/agent-settings.png" alt="Agent Settings" /></p>
<h2>Differences Between Cursor and AntiGravity</h2>
<p>While Cursor was the champion of AI code editors, <strong>Antigravity brings a different philosophy</strong>.</p>
<h3>1. &quot;Agent-First 🤖&quot;  vs &quot;You-First 🤠&quot;</h3>
<ul>
<li><strong>Cursor:</strong> It acts like an assistant; it predicts your next move, auto-completes your thoughts, and helps you refactor while you type. You are still the driver; Cursor just drives the car at 200 km/h.</li>
<li><strong>Antigravity:</strong> Antigravity is built to let you manage coding tasks. It is &quot;Agent-First.&quot; You don't just type code; you assign tasks to autonomous agents (e.g., &quot;Fix the bug in the login flow and verify it in the browser&quot;). It behaves more like a junior developer that you supervise.</li>
</ul>
<h3>2. The Interface</h3>
<ul>
<li><p><strong>Cursor:</strong> Looks and feels exactly like <strong>VS Code</strong>. If you know VS Code, you know Cursor.</p>
</li>
<li><p><strong>Antigravity:</strong> Introduces 2 major layouts:</p>
<ul>
<li><strong>Editor View:</strong> Similar to a standard IDE</li>
<li><strong>Manager View:</strong> A dashboard where you see multiple &quot;Agents&quot; working in parallel. You can watch them plan, execute, and test tasks asynchronously.</li>
</ul>
</li>
</ul>
<h3>3. Verification &amp; Trust</h3>
<ul>
<li><strong>Cursor:</strong> You verify by reading the code diffs it suggests.</li>
<li><strong>Antigravity:</strong> Introduces <strong>Artifacts</strong>... Since the agents work autonomously, they generate proof-of-work documents, screenshots of the app running, browser logs and execution plans. So you can verify what they did without necessarily reading every line of code immediately.</li>
</ul>
<h3>4. Capabilities</h3>
<ul>
<li><strong>Cursor:</strong> Best-in-class <strong>Autocomplete</strong> (&quot;Tab&quot; feature) and <strong>Composer</strong> (multi-file editing). It excels at &quot;Vibe Coding&quot;. It's getting into a flow state where the AI writes the boilerplate and you direct the logic.</li>
<li><strong>Antigravity:</strong> Is good at <strong>Autonomous Execution</strong>. It has a built-in browser and terminal that the <em>Agent</em> controls. The Agent can write code, run the server, open the browser, see the error, and fix it 😎</li>
</ul>
<h3>5. AI Models (Brains 🧠)</h3>
<ul>
<li><strong>Cursor:</strong> Model Agnostic. You can switch between <strong>Claude 3.5 Sonnet</strong> <em>-mostly the community uses this-</em>, GPT-4o, and others.</li>
<li><strong>Antigravity:</strong> Built deeply around <strong>Gemini 3 Pro</strong>. It leverages Gemini's massive context window (1M+ tokens) to understand huge mono repos without needing as much &quot;RAG&quot; as Cursor.</li>
</ul>
<h2>Try It Yourself Now 🤝</h2>
<p>If you are ready to experience the new AI code editor by Google, download and use 👇
<a href="https://antigravity.google/"><strong>Launch Google AntiGravity</strong></a></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1dc830-a134-b5a2-52a7-14d2d2421432" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1dc830-a134-b5a2-52a7-14d2d2421432" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/return-code-vs-exceptions-which-one-is-better-1rwcu9yi</guid>
      <link>https://abp.io/community/posts/return-code-vs-exceptions-which-one-is-better-1rwcu9yi</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>exception-handling</category>
      <category>best-practices</category>
      <category>error-handling</category>
      <title>Return Code vs Exceptions: Which One is Better?</title>
      <description>Discover the pros and cons of return codes vs exceptions in error handling — from performance and readability to real-world use cases — and learn which approach fits your project best.</description>
      <pubDate>Fri, 31 Oct 2025 12:40:39 Z</pubDate>
      <a10:updated>2026-03-02T16:44:47Z</a10:updated>
      <content:encoded><![CDATA[<h1><strong>Return Code vs Exceptions: Which One is Better?</strong></h1>
<p>Alright, so this debate pops up every few months on dev subreddits and forums</p>
<blockquote>
<p><em>Should you use return codes or exceptions for error handling?</em></p>
</blockquote>
<p>And honestly, there’s no %100 right answer here! Both have pros/cons, and depending on the language or context, one might make more sense than the other. Let’s see...</p>
<hr />
<h2>1. Return Codes --- Said to be &quot;Old School Way&quot; ---</h2>
<p>Return codes (like <code>0</code> for success, <code>-1</code> for failure, etc.) are the OG method. You mostly see them everywhere in C and C++.
They’re super explicit, the function literally <em>returns</em> the result of the operation.</p>
<h3>➕ Advantages of returning codes:</h3>
<ul>
<li>You <em>always</em> know when something went wrong</li>
<li>No hidden control flow — what you see is what you get</li>
<li>Usually faster (no stack unwinding, no exception overhead)</li>
<li>Easy to use in systems programming, embedded stuff, or performance-critical code</li>
</ul>
<h3>➖ Disadvantages of returning codes:</h3>
<ul>
<li>It’s easy to forget to check the return value (and boom, silent failure 😬)</li>
<li>Makes code noisy...  Everry function call followed by <code>if (result != SUCCESS)</code> gets annoying</li>
<li>No stack trace or context unless you manually build one</li>
</ul>
<p><strong>For example:</strong></p>
<pre><code class="language-csharp">try
{
	await SendEmailAsync();
}
catch (Exception e)
{
    Log.Exception(e.ToString());
	return -1;
}
</code></pre>
<p>Looks fine… until you forget one of those <code>if</code> conditions somewhere.</p>
<hr />
<h2>2. Exceptions --- The Fancy &amp; Modern Way ---</h2>
<p>Exceptions came in later, mostly with higher-level languages like Java, C#, and Python.
The idea is that you <em>throw</em> an error and handle it <em>somewhere else</em>.</p>
<h3>➕ Advantages of throwing exceptions:</h3>
<ul>
<li>Cleaner code... You can focus on the happy path and handle errors separately</li>
<li>Can carry detailed info (stack traces, messages, inner exceptions...)</li>
<li>Easier to handle complex error propagation</li>
</ul>
<h3>➖ Disadvantages of throwing exceptions:</h3>
<ul>
<li>Hidden control flow — you don’t always see what might throw</li>
<li>Performance hit (esp. in tight loops or low-level systems)</li>
<li>Overused in some codebases (“everything throws everything”)</li>
</ul>
<p><strong>Example:</strong></p>
<pre><code class="language-csharp">try
{
	await SendEmailAsync();
}
catch (Exception e)
{
	Log.Exception(e.ToString());
    throw e;
}
</code></pre>
<p>Way cleaner, but if <code>SendEmailAsync()</code> is deep in your call stack and it fails, it can be tricky to know exactly what went wrong unless you log properly.</p>
<hr />
<h3>And Which One’s Better? ⚖️</h3>
<p>Depends on what you’re building.</p>
<ul>
<li><strong>Low-level systems, drivers, real-time stuff   👉  Return codes.</strong> Performance and control matter more.</li>
<li><strong>Application-level, business logic, or high-level APIs  👉  Exceptions.</strong> Cleaner and easier to maintain.</li>
</ul>
<p>And honestly, mixing both sometimes makes sense.
For example, you can use return codes internally and exceptions at the boundary of your API to surface meaningful errors to the user.</p>
<hr />
<h3>Conclusion</h3>
<p>Return codes = simple, explicit, but messy.t
Exceptions = clean, powerful, but can bite you.
Use what fits your project and your team’s sanity level 😅.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1d4c75-9e3b-6e63-2288-030e51b92f60" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1d4c75-9e3b-6e63-2288-030e51b92f60" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/optimize-your-.net-app-for-production-complete-checklist-part-2-78xgncpi</guid>
      <link>https://abp.io/community/posts/optimize-your-.net-app-for-production-complete-checklist-part-2-78xgncpi</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>performance</category>
      <category>optimize</category>
      <category>aspnetcore</category>
      <category>kestrel</category>
      <category>best-practises</category>
      <category>dotnet</category>
      <title>Optimize Your .NET App for Production - Complete Checklist (Part 2)</title>
      <description>Optimize any .NET app for production with a practical checklist. In this list, you'll find releasing, publishing, trimming, kestrel &amp; GC tuning, caching, &amp; compression, docker configurations, health checks and open telemetry... Real commands, copy-paste snippets, minimal fluff! For part one see https://abp.io/community/articles/optimize-your-dotnet-app-for-production-for-any-.net-app-wa24j28e</description>
      <pubDate>Wed, 22 Oct 2025 07:19:10 Z</pubDate>
      <a10:updated>2026-03-02T14:40:09Z</a10:updated>
      <content:encoded><![CDATA[<p><em>If you’ve landed directly on this article, note that it’s part-2 of the series. You can read part-1 here: <a href="https://abp.io/community/articles/optimize-your-dotnet-app-for-production-for-any-.net-app-wa24j28e">Optimize Your .NET App for Production (Part 1)</a></em></p>
<h2>6)  Telemetry (Logs, Metrics, Traces)</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/6.png" alt="Telemetry" /></p>
<p>The below code adds <code>OpenTelemetry</code> to collect app logs, metrics, and traces in .NET.</p>
<pre><code class="language-csharp">builder.Services.AddOpenTelemetry()
  .UseOtlpExporter()
  .WithMetrics(m =&gt; m.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation())
  .WithTracing(t =&gt; t.AddAspNetCoreInstrumentation().AddHttpClientInstrumentation());
</code></pre>
<ul>
<li><code>UseOtlpExporter()</code> Tells it where to send telemetry. Usually that’s an OTLP collector (like Grafana , Jaeger, Tempo, Azure Monitor). So you can visualize metrics and traces in dashboards.</li>
<li><code>WithMetrics()</code> means it'll collects metrics. These metrics are Request rate (RPS), Request duration (latency), GC pauses, Exceptions, HTTP client timings.</li>
<li><code>.WithTracing(...)</code> means it'll collect distributed traces. That's useful when your app calls other APIs or microservices. You can see the full request path from one service to another with timings and bottlenecks.</li>
</ul>
<h3>.NET Diagnostic Tools</h3>
<p>When your app is on-air, you should know about the below tools. You know in airplanes there's <em>black box recorder</em> which is used to understand why the airplane crashed. For .NET below are our <em>black box recorders</em>.  They capture what happened without attaching a debugger.</p>
<p>| Tool                  | What It Does                            | When to Use                  |
| --------------------- | --------------------------------------- | ---------------------------- |
| <strong><code>dotnet-counters</code></strong> | Live metrics like CPU, GC, request rate | Monitor running apps         |
| <strong><code>dotnet-trace</code></strong>    | CPU sampling &amp; performance traces       | Find slow code               |
| <strong><code>dotnet-gcdump</code></strong>   | GC heap dumps (allocations)             | Diagnose memory issues       |
| <strong><code>dotnet-dump</code></strong>     | Full process dumps                      | Investigate crashes or hangs |
| <strong><code>dotnet-monitor</code></strong>  | HTTP service exposing all the above     | Collect telemetry via API    |</p>
<hr />
<h2>7) Build &amp; Run .NET App in Docker the Right Way</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/7.png" alt="Docker" /></p>
<p>A multi-stage build is a Docker technique where you use one image for building your app and another smaller image for running it. Why we do multi-stage build, because the .NET SDK image is big but has all the build tools. The .NET Runtime image is small and optimized for production. You copy only the published output from the build stage into the runtime stage.</p>
<pre><code class="language-dockerfile"># build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o /app/out -p:PublishTrimmed=true -p:PublishSingleFile=true -p:ReadyToRun=true

# run
FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080
COPY --from=build /app/out .
ENTRYPOINT [&quot;./YourApp&quot;]  # or [&quot;dotnet&quot;,&quot;YourApp.dll&quot;]
</code></pre>
<p>I'll explain what these Docker file commands;</p>
<p><strong>Stage1: Build</strong></p>
<ul>
<li><p><code>FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build</code>
Uses the .NET SDK image including compilers and tools. The <code>AS build</code> name lets you reference this stage later.</p>
</li>
<li><p><code>WORKDIR /src</code>
Sets the working directory inside the container.</p>
</li>
<li><p><code>COPY . .</code>
Copies your source code into the container.</p>
</li>
<li><p><code>RUN dotnet restore</code>
Restores NuGet packages.</p>
</li>
<li><p><code>RUN dotnet publish ...</code>
Builds the project in <strong>Release</strong> mode, optimizes it for production, and outputs it to <code>/app/out</code>.
The flags;</p>
<ul>
<li><code>PublishTrimmed=true</code> -&gt; removes unused code</li>
<li><code>PublishSingleFile=true</code> -&gt; bundles everything into one file</li>
<li><code>ReadyToRun=true</code> -&gt; precompiles code for faster startup</li>
</ul>
</li>
</ul>
<p><strong>Stage 2: Run</strong></p>
<ul>
<li><code>FROM mcr.microsoft.com/dotnet/aspnet:9.0</code>
Uses a lighter runtime image which no compiler, just the runtime.</li>
<li><code>WORKDIR /app</code>
Where your app will live inside the container.</li>
<li><code>ENV ASPNETCORE_URLS=http://+:8080</code>
Makes the app listen on port 8080 (and all network interfaces).</li>
<li><code>EXPOSE 8080</code>
Documents the port your container uses (for Docker/K8s networking).</li>
<li><code>COPY --from=build /app/out .</code>
Copies the published output from the <strong>build stage</strong> to this final image.</li>
<li><code>ENTRYPOINT [&quot;./YourApp&quot;]</code>
Defines the command that runs when the container starts. If you published as a single file, it’s <code>./YourApp</code>.  f not, use <code>dotnet YourApp.dll</code>.</li>
</ul>
<hr />
<h2>8) Security</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/8.png" alt="Security" /></p>
<h3>HTTPS Everywhere Even Behind Proxy</h3>
<p>Even if your app runs behind a reverse proxy like Nginx, Cloudflare or a load balancer, always enforce HTTPS. Why? Because internal traffic can still be captured if you don't use SSL and also cookies, HSTS, browser APIs require HTTPS. In .NET, you can easily enforce HTTPS like this:</p>
<pre><code class="language-csharp">app.UseHttpsRedirection();
</code></pre>
<h3>Use HSTS  in  Production</h3>
<p>HSTS (HTTP Strict Transport Security) tells browsers:</p>
<blockquote>
<p>Always use HTTPS for this domain — don’t even try HTTP again!</p>
</blockquote>
<p>Once you set, browsers cache this rule, so users can’t accidentally hit the insecure version. You can easily enforce this as below:</p>
<pre><code class="language-csharp">if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}
</code></pre>
<p>When you use HSTS, it sends browser this HTTP header: <code> Strict-Transport-Security: max-age=31536000; includeSubDomains</code>. Browser will remember this setting for 1 year (31,536,000 seconds) that this site must only use HTTPS. And <code>includeSubDomains</code> option applies the rule to all subdomains as well (eg: <code>api.abp.io</code>, <code>cdn.abp.io</code>,  <code>account.abp.io</code> etc..)</p>
<h3>Store Secrets on Environment Variables or Secret Stores</h3>
<p>Never store passwords, connection strings, or API keys in your code or Git. Then where should we keep them?</p>
<ul>
<li><p>Best/practical way is <strong>Environment variables</strong>. You can easily sett an environment variable in a Unix-like system as below:</p>
<ul>
<li>
<pre><code class="language-bash">export ConnectionStrings__Default=&quot;Server=...;User Id=...;Password=...&quot;
</code></pre>
</li>
</ul>
</li>
<li><p>And you can easily access these environment variables from your .NET app like this:</p>
<ul>
<li>
<pre><code class="language-csharp">var conn = builder.Configuration.GetConnectionString(&quot;Default&quot;);
</code></pre>
</li>
</ul>
</li>
</ul>
<p>Or <strong>Secret stores</strong> like: Azure Key Vault, AWS Secrets Manager, HashiCorp Vault</p>
<h3>Add Rate-Limiting to Public Endpoints</h3>
<p>Don't forget there'll be not naive guys who will use your app! We've many times faced this issue in the past on our public front-facing websites. So protect your public APIs from abuse, bots, and DDoS. Use rate-limiting!!! Stop brute-force attacks, prevent your resources from exhaustion...</p>
<p>In .NET,  there's a built-in rate-limit feature for .NET (System.Threading.RateLimiting):</p>
<pre><code class="language-csharp">builder.Services.AddRateLimiter(_ =&gt; _
    .AddFixedWindowLimiter(&quot;default&quot;, options =&gt;
    {
        options.PermitLimit = 100;
        options.Window = TimeSpan.FromMinutes(1);
    }));

app.UseRateLimiter();
</code></pre>
<ul>
<li>Also there's an open-source rate-limiting library -&gt; <a href="https://github.com/stefanprodan/AspNetCoreRateLimit">github.com/stefanprodan/AspNetCoreRateLimit</a></li>
<li>Another one -&gt; <a href="https://www.nuget.org/packages/Polly.RateLimiting">nuget.org/packages/Polly.RateLimiting</a></li>
</ul>
<h3>Secure Cookies</h3>
<p>Cookies are often good targets for attacks. You must secure them properly otherwise you can face cookie stealing or CSRF attack.</p>
<pre><code class="language-csharp">options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict; // or Lax
</code></pre>
<ul>
<li><strong><code>SecurePolicy = Always</code></strong> -&gt; only send cookies over HTTPS</li>
<li><strong><code>SameSite=Lax/Strict</code></strong> -&gt; prevent CSRF (Cross-Site Request Forgery)
<ul>
<li><code>Strict</code> = safest</li>
<li><code>Lax</code> = good balance for login sessions</li>
</ul>
</li>
</ul>
<hr />
<h2>9) Startup/Cold Start</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/9.png" alt="Cold Start / Startup" /></p>
<h3>Keep Tiered JIT On</h3>
<p>The <strong>JIT (Just-In-Time) compiler</strong> converts your app’s Intermediate Language (IL) into native CPU instructions when the code runs. <em>Tiered JIT</em> means the runtime uses 2 stages of compilation. Actually this setting is enabled by default in modern .NET. So just keep it on.</p>
<ol>
<li><strong>Tier 0 (Quick JIT):</strong>
Fast, low-optimization compile → gets your app running ASAP.
(Used at startup.)</li>
<li><strong>Tier 1 (Optimized JIT):</strong>
Later, the runtime re-compiles <em>hot</em> methods (frequently used ones) with deeper optimizations for speed.</li>
</ol>
<h3>Use PGO (Profile-Guided Optimization)</h3>
<p>PGO lets .NET learn from real usage of your app. It profiles which functions are used most often, then re-optimizes the build for that pattern. You can think of it as the runtime saying:</p>
<blockquote>
<p>I’ve seen what your app actually does... I’ll rearrange and optimize code paths accordingly.</p>
</blockquote>
<p>In .NET 8+, you don’t have to manually enable PGO (Profile-Guided Optimization). The JIT collects runtime profiling data (e.g. which types are common, branch predictions) and uses it to generate more optimized code later. In .NET 9, PGO has been improved: the JIT uses PGO data for more patterns (like type checks / casts) and makes better decisions.</p>
<hr />
<h2>10) Graceful Shutdown</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/10.png" alt="Shutdown" /></p>
<p>When we break up with our lover, we often argue and regret it later. When an application breaks up with an operating system, it should be done well 😘 ...
When your app stops, maybe you deploy a new version or Kubernetes restarts a pod... the OS sends a signal called <code>SIGTERM</code> (terminate).
A <strong>graceful shutdown</strong> means handling that signal properly, finishing what’s running, cleaning up, and exiting cleanly (like an adult)!</p>
<pre><code class="language-csharp">var app = builder.Build();
var lifetime = app.Services.GetRequiredService&lt;IHostApplicationLifetime&gt;();
lifetime.ApplicationStopping.Register(() =&gt;
{
    // stop accepting, finish in-flight, flush telemetry
});
app.Run();
</code></pre>
<p>On K8s, set <code>terminationGracePeriodSeconds</code> and wire <strong>readiness</strong>/startup probes.</p>
<hr />
<h2>11) Load Test</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11.png" alt="Load Test" /></p>
<p>Sometimes arguing with our lover is good. We can see her/his face before marrying 😀 Use <strong>k6</strong> or <strong>bombardier</strong>  and test with realistic payloads and prod-like limits. Don't be surprise later when your app is running on prod! These topics should be tested: <code>CPU %</code> , <code>Time in GC</code> ,  <code>LOH Allocations</code> , <code>ThreadPool Queue Length</code> and <code>Socket Exhaustion</code>.</p>
<h3>About K6</h3>
<ul>
<li><p>A modern load testing tool, using Go and JavaScript.</p>
</li>
<li><p>29K stars on GitHub</p>
</li>
<li><p>GitHub address: https://github.com/grafana/k6</p>
</li>
</ul>
<h3>About Bombardier</h3>
<ul>
<li><p>Fast cross-platform HTTP benchmarking tool written in Go.</p>
</li>
<li><p>7K stars on GitHub</p>
</li>
<li><p>GitHub address: https://github.com/codesenberg/bombardier</p>
</li>
</ul>
<p><a href="https://trends.google.com/trends/explore?cat=31&amp;q=bombardier%20%2B%20benchmarking,k6%20%2B%20benchmarking"><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/11_1.png" alt="Bombardier vs K6" /></a></p>
<h2>Summary</h2>
<p>In summary, I listed 11 items for optimizing a .NET application for production; Covering build configuration, hosting setup, runtime behavior, data access, telemetry, containerization, security, startup performance and reliability under load. By applying the checklist from Part 1 and Part 2 of this series, leveraging techniques like trimmed releases, server GC, minimal payloads, pooled <code>DbContexts</code>, OpenTelemetry, multi-stage Docker builds, HTTPS enforcement, and proper shutdown handling—you’ll improve your app’s durability, scalability and maintainability under real-world traffic and production constraints. Each item is a checkpoint and you’ll be able to deliver a robust, high-performing .NET application ready for live users.</p>
<p>🎉 Want top-tier .NET performance without the headaches? Try <a href="https://abp.io?utm_source=alper-ebicoglu-performance-article">ABP Framework</a> for best-performance and skip all the hustles of .NET app development.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1d1cf6-0db1-a0a6-3488-0183f2d91252" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1d1cf6-0db1-a0a6-3488-0183f2d91252" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/optimize-your-.net-app-for-production-complete-checklist-part-1-wa24j28e</guid>
      <link>https://abp.io/community/posts/optimize-your-.net-app-for-production-complete-checklist-part-1-wa24j28e</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>performance</category>
      <category>optimize</category>
      <category>aspnetcore</category>
      <category>kestrel</category>
      <category>best-practises</category>
      <category>dotnet</category>
      <title>Optimize Your .NET App for Production - Complete Checklist (Part 1)</title>
      <description>Optimize any .NET app for production with a practical checklist. In this list, you'll find releasing, publishing, trimming, kestrel &amp; GC tuning, caching, &amp; compression, docker configurations, health checks and open telemetry... Real commands, copy-paste snippets, minimal fluff!</description>
      <pubDate>Wed, 22 Oct 2025 07:00:25 Z</pubDate>
      <a10:updated>2026-03-02T14:38:45Z</a10:updated>
      <content:encoded><![CDATA[<h1>Optimize Your .NET App for Production (Complete Checklist)</h1>
<p>I see way too many .NET apps go to prod like it’s still “F5 on my laptop.” Here’s the checklist I wish someone shoved me years ago. It’s opinionated, pragmatic, copy-pasteable.</p>
<hr />
<h2>1) Publish Command and CSPROJ  Settings</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/1.png" alt="Publish Command and CSPROJ Setting" /></p>
<p>Never go to production with debug build! See the below command which publishes properly a .NET app for production.</p>
<pre><code class="language-bash">dotnet publish -c Release -o out -p:PublishTrimmed=true -p:PublishSingleFile=true -p:ReadyToRun=true
</code></pre>
<p><code>csproj</code> for the optimum production publish:</p>
<pre><code class="language-xml">&lt;PropertyGroup&gt;
  &lt;PublishReadyToRun&gt;true&lt;/PublishReadyToRun&gt;
  &lt;PublishTrimmed&gt;true&lt;/PublishTrimmed&gt;
  &lt;InvariantGlobalization&gt;true&lt;/InvariantGlobalization&gt;
  &lt;TieredCompilation&gt;true&lt;/TieredCompilation&gt;
&lt;/PropertyGroup&gt;
</code></pre>
<ul>
<li><p><strong>PublishTrimmed</strong> It's trimmimg assemblies. What's that!? It removes unused code from your application and its dependencies, hence it reduces the output files.</p>
</li>
<li><p><strong>PublishReadyToRun</strong> When you normally build a .NET app, your C# code is compiled into <strong>IL</strong> (Intrmediate Language). When your app runs, the JIT Compiler turns that IL code into native CPU commands. But this takes much time on startup. When you enable <code>PublishReadyToRun</code>, the build process precompiles your IL into native code and it's called AOT (Ahead Of Time). Hence your app starts faster... But the downside is; the output files are now a bit bigger. Another thing; it'll compile only for a specific OS like Windows and will not run on Linux anymore.</p>
</li>
<li><p><strong>Self-contained</strong> When you publish your .NET app this way, it ncludes the .NET runtime inside your app files. It will run even on a machine that doesn’t have .NET installed. The output size gets larger, but the runtime version is exactly what you built with.</p>
</li>
</ul>
<hr />
<h2>2) Kestrel Hosting</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/2.png" alt="Kestrel Hosting" /></p>
<p>By default, ASP.NET Core app listen only <code>localhost</code>, it means it accepts requests only from inside the machine. When you deploy to Docker or Kubernetes, the container’s internal network needs to expose the app to the outside world. To do this you can set it via environment variable as below:</p>
<pre><code class="language-bash">ASPNETCORE_URLS=http://0.0.0.0:8080
</code></pre>
<p>Also if you’re building an internall API or a containerized microservice which is not multilngual, then add also the below setting. it disables operating system's globalization to reduce image size and dependencies..</p>
<pre><code class="language-bash">DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
</code></pre>
<p>Clean <code>Program.cs</code> startup!
Here's a minimal <code>Program.cs</code> which includes just the essential middleware and settings:</p>
<pre><code class="language-csharp">var builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders();
builder.Logging.AddConsole();

builder.Services.AddResponseCompression();
builder.Services.AddResponseCaching();
builder.Services.AddHealthChecks();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler(&quot;/error&quot;);
    app.UseHsts();
}

app.UseResponseCompression();
app.UseResponseCaching();

app.MapHealthChecks(&quot;/health&quot;);
app.MapGet(&quot;/error&quot;, () =&gt; Results.Problem(statusCode: 500));

app.Run();
</code></pre>
<hr />
<h2>3) Garbage Collection and ThreadPool</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/3.png" alt="Garbage Collection and ThreadPool" /></p>
<h3>GC Memory Cleanup Mode</h3>
<p>GC (Garbage Collection) is how .NET automatically frees memory. There are two main modes:</p>
<ul>
<li><strong>Workstation GC:</strong> good for desktop apps (focuses on responsiveness)</li>
<li><strong>Server GC:</strong>  good for servers (focuses on throughput)</li>
</ul>
<p>The below environment variable is telling the .NET runtime to use the <em>Server Garbage Collector (Server GC)</em> instead of the <em>Workstation GC</em>. Because our ASP.NET Core app must be optmized for servers not personal computers.</p>
<pre><code class="language-bash">COMPlus_gcServer=1
</code></pre>
<h3>GC Limit Memory Usage</h3>
<p>Use at max 60% of the total available memory for the managed heap (the memory that .NET’s GC controls). So if your container or VM has, let's say 4 GB of RAM, .NET will try to keep the GC heap below 2.4 GB (60% of 4 GB). Especially when you run your app in containers, don’t let the GC assume host memory:</p>
<pre><code class="language-bash">COMPlus_GCHeapHardLimitPercent=60
</code></pre>
<h3>Thread Pool Warm-up</h3>
<p>When your .NET app runs, it uses a thread pool. This is for handling background work like HTTP requests, async tasks, I/O things... By default, the thread pool starts small and grows dynamically as load increases. That’s good for desktop apps but for server apps  it's too slow! Because during sudden peek of traffic, the app might waste time creating threads instead of handling requests. So below code keeps at least 200 worker threads and 200 I/O completion threads ready to go even if they’re idle.</p>
<pre><code class="language-csharp">ThreadPool.SetMinThreads(200, 200);
</code></pre>
<hr />
<h2>4) HTTP Performance</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/4.png" alt="HTTP Performance" /></p>
<h3>HTTP Response Compression</h3>
<p><code>AddResponseCompression()</code> enables HTTP response compression. It shrinks your outgoing responses before sending them to the client. Making smaller payloads for faster responses and uses less bandwidth. Default compression method is <code>Gzip</code>. You can also add <code>Brotli</code> compression. <code>Brotli</code> is great for APIs returning JSON or text. If your CPU is already busy, keep the default <code>Gzip</code> method.</p>
<pre><code class="language-csharp">builder.Services.AddResponseCompression(options =&gt;
{
    options.Providers.Add&lt;BrotliCompressionProvider&gt;();
    options.EnableForHttps = true;
});
</code></pre>
<h3>HTTP Response Caching</h3>
<p>Use caching for GET endpoints where data doesn’t change often (e.g., configs, reference data). <code>ETags</code> and <code>Last-Modified</code> headers tell browsers or proxies skip downloading data that hasn’t changed.</p>
<ul>
<li><strong>ETag</strong> = a version token for your resource.</li>
<li><strong>Last-Modified</strong> = timestamp of last change.</li>
</ul>
<p>If a client sends <code>If-None-Match: &quot;abc123&quot;</code> and your resource’s <code>ETag</code> hasn’t changed, .NET automatically returns <code>304 Not Modified</code>.</p>
<h3>HTTP/2 or HTTP/3</h3>
<p>These newer protocols make web requests faster and smoother. It's good for microservices or frontends making many API calls.</p>
<ul>
<li><strong>HTTP/2</strong> : multiplexing (many requests over one TCP connection).</li>
<li><strong>HTTP/3</strong> : uses QUIC (UDP) for even lower latency.</li>
</ul>
<p>You can enable them on your reverse proxy (Nginx, Caddy, Kestrel)...
.NET supports both out of the box if your environment allows it.</p>
<h3>Minimal Payloads with DTOs</h3>
<p>The best practise here is; Never send/recieve your entire database entity, use DTOs. In the DTOs include only the fields the client actually needs by doing so you will keep the responses smaller and even safer. Also, prefer <code>System.Text.Json</code> (now it’s faster than <code>Newtonsoft.Json</code>) and for very high-traffic APIs, use source generation to remove reflection overhead.</p>
<pre><code class="language-csharp">//define your entity DTO
[JsonSerializable(typeof(MyDto))]
internal partial class MyJsonContext : JsonSerializerContext { }

//and simply serialize like this    
var json = JsonSerializer.Serialize(dto, MyJsonContext.Default.MyDto)
</code></pre>
<hr />
<h2>5) Data Layer (Mostly Where Most Apps Slow Down!)</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-10-17-Optimize-Your-App-For-Production/5.png" alt="Data Layer" /></p>
<h3>Reuse <code>DbContext</code> via Factory (Pooling)</h3>
<p>Creating a new <code>DbContext</code> for every query is expensive! Use <code>IDbContextFactory&lt;TContext&gt;</code>,  it gives you pooled <code>DbContext</code> instances from a pool that reuses objects instead of creating them from scratch.</p>
<pre><code class="language-csharp">services.AddDbContextFactory&lt;AppDbContext&gt;(options =&gt;
    options.UseSqlServer(connectionString));
</code></pre>
<p>Then inject the factory:</p>
<pre><code class="language-csharp">using var db = _contextFactory.CreateDbContext();
</code></pre>
<p>Also, ensure your database server (SQL Server, PostgreSQL....) has <strong>connection pooling enabled</strong>.</p>
<hr />
<h3>N+1 Query Problem</h3>
<p>The N+1 problem occurs when your app runs <strong>one query for the main data</strong>, then <strong>N more queries for related entities</strong>. That kills performance!!!</p>
<p><strong>Bad-Practise:</strong></p>
<pre><code class="language-csharp">var users = await context.Users.Include(u =&gt; u.Orders).ToListAsync();
</code></pre>
<p><strong>Good-Practise:</strong>
Project to DTOs using <code>.Select()</code> so EF-Core generates a single optimized SQL query:</p>
<pre><code class="language-csharp">var users = await context.Users.Select(u =&gt; new UserDto
   {
        Id = u.Id,
        Name = u.Name,
        OrderCount = u.Orders.Count
    }).ToListAsync();
</code></pre>
<hr />
<h3><strong>Indexes</strong></h3>
<p>Use EF Core logging, SQL Server Profiler, or <code>EXPLAIN</code> (Postgres/MySQL) to find slow queries. Add missing indexes <strong>only</strong> where needed. For example <a href="https://blog.sqlauthority.com/2011/01/03/sql-server-2008-missing-index-script-download/">at this page</a>, he wrote an SQL query which lists missing index list (also there's another version at <a href="https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-db-missing-index-details-transact-sql?view=sql-server-ver17">Microsoft Docs</a>). This perf improvement is mostly applied after running the app for a period of time.</p>
<hr />
<h3>Migrations</h3>
<p>In production run migrations manually, never do it on app startup. That way you can review schema changes, back up data and avoid breaking the live DB.</p>
<hr />
<h3>Resilience with Polly</h3>
<p>Use <a href="https://www.pollydocs.org/">Polly</a> for retries, timeouts and circuit breakers for your DB or HTTP calls. Handles short outages gracefully</p>
<p><em>To keep the article short and for the better readability I spitted it into 2 parts 👉 <a href="https://abp.io/community/articles/optimize-your-dotnet-app-for-production-for-any-.net-app-2-78xgncpi">Continue with the second part here</a>...</em></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1d1ce4-e4de-49cc-b83c-c9cf4d3932e7" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1d1ce4-e4de-49cc-b83c-c9cf4d3932e7" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/native-aot-for-.net-how-to-fasten-startup-time-and-memory-footprint-3gsfre75</guid>
      <link>https://abp.io/community/posts/native-aot-for-.net-how-to-fasten-startup-time-and-memory-footprint-3gsfre75</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>aot</category>
      <category>performance</category>
      <category>optimization</category>
      <category>dotnet</category>
      <title>Native AOT for .NET — How to Fasten Startup Time and Memory Footprint</title>
      <description>How .NET’s Native AOT (Ahead-of-Time compilation) can improve startup time and reduce memory footprint. Perfect for serverless apps, microservices, and performance-focused developers.</description>
      <pubDate>Fri, 03 Oct 2025 14:04:38 Z</pubDate>
      <a10:updated>2026-03-02T16:49:49Z</a10:updated>
      <content:encoded><![CDATA[<h1>Native AOT: How to Fasten Startup Time and Memory Footprint</h1>
<p>So since .NET 8 there's been one feature that’s quietly a game-changer for performance nerds is <strong>Native AOT</strong> (Ahead-of-Time compilation). If you’ve ever fought with sluggish cold starts (especially in containerized or serverless environments), or dealt with memory pressure from bloated apps, Native AOT might just be your new best friend.</p>
<hr />
<h2>What is Native AOT?</h2>
<p>Normally, .NET apps ship as IL (<em>Intermediate Language</em>) and JIT-compile at runtime. That’s flexible, but it takes longer startup time and memory.
Native AOT flips the script: your app gets compiled straight into a platform-specific binary <em>before it ever runs</em>.</p>
<p>As a result;</p>
<ul>
<li>No JIT overhead at startup.</li>
<li>Smaller memory footprint (no JIT engine or IL sitting around).</li>
<li>Faster startup (especially noticeable in microservices, functions, or CLI tools).</li>
</ul>
<hr />
<h2>Advantages of AOT</h2>
<ul>
<li><strong>Broader support</strong> → More workloads and libraries now play nice witt.h AOT.</li>
<li><strong>Smaller output sizes</strong> → Trimmed down runtime dependencies.</li>
<li><strong>Better diagnostics</strong> → Easier to figure out why your build blew up (because yes, AOT can be picky).</li>
<li><strong>ASP.NET Core AOT</strong> → Minimal APIs and gRPC services actually <em>benefit massively</em> here. Cold starts are crazy fast.</li>
</ul>
<hr />
<h2>Why you should care</h2>
<p>If you’re building:</p>
<ul>
<li><strong>Serverless apps (AWS Lambda, Azure Functions, GCP Cloud Run)</strong> → Startup time matters a LOT.</li>
<li><strong>Microservices</strong> → Lightweight services scale better when they use less memory per pod.</li>
<li><strong>CLI tools</strong> → No one likes waiting half a second for a tool to boot. AOT makes them feel “native” (because they literally are).</li>
</ul>
<p>And yeah, you <em>can</em> get Go-like startup performance in .NET now.</p>
<hr />
<h2>The trade-offs (because nothing’s free)</h2>
<p>Native AOT isn’t a silver bullet:</p>
<ul>
<li>Build times are longer (the compiler does all the heavy lifting upfront).</li>
<li>Less runtime flexibility (no reflection-based magic, dynamic codegen, or IL rewriting).</li>
<li>Debugging can be trickier.</li>
</ul>
<p>Basically: if you rely heavily on reflection-heavy libs or dynamic runtime stuff, expect pain.</p>
<hr />
<h2>Quick demo (conceptual)</h2>
<pre><code class="language-bash"># Regular publish
dotnet publish -c Release

# Native AOT publish
dotnet publish -c Release -r win-x64 -p:PublishAot=true
</code></pre>
<p>Boom. You get a native executable. On Linux, drop it into a container and watch that startup time drop like a rock.</p>
<hr />
<h3>Conclusion</h3>
<ul>
<li>Native AOT in .NET 8 = faster cold starts + lower memory usage.</li>
<li>Perfect for microservices, serverless, and CLI apps.</li>
<li>Comes with trade-offs (longer builds, less dynamic flexibility).</li>
<li>If performance is critical, it’s absolutely worth testing.</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1cbc90-72b1-8a73-1d4a-844d3cd04f66" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1cbc90-72b1-8a73-1d4a-844d3cd04f66" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/highperformance-.net-libraries-you-didnt-know-you-needed-nu5t88sz</guid>
      <link>https://abp.io/community/posts/highperformance-.net-libraries-you-didnt-know-you-needed-nu5t88sz</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>performance</category>
      <category>optimization</category>
      <category>.net</category>
      <category>dotnet</category>
      <title>High-Performance .NET Libraries You Didn’t Know You Needed</title>
      <description>Discover high-performance .NET libraries from ultra-fast serializers to resilience tools and low-latency messaging, to build faster, more scalable apps.</description>
      <pubDate>Thu, 11 Sep 2025 15:23:00 Z</pubDate>
      <a10:updated>2026-03-02T16:44:02Z</a10:updated>
      <content:encoded><![CDATA[<h1>High-Performance .NET Libraries You Didn’t Know You Needed</h1>
<p>Whether you’re building enterprise apps, microservices, or SaaS platforms, using the right libraries can help you ship faster and scale effortlessly.
Here are some <strong>high-performance .NET libraries</strong> you might not know but definitely should.</p>
<h2>1. BenchmarkDotNet – Measure before you optimize</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/BenchmarkDotnet.png" alt="BenchmarkDotnet" /></p>
<p>BenchmarkDotNet makes it simple to <strong>benchmark .NET code with precision</strong>.</p>
<ul>
<li>Easy setup with <code>[Benchmark]</code> attributes</li>
<li>Generates detailed performance reports</li>
<li>Works with .NET Core, .NET Framework, and Mono</li>
</ul>
<p>Perfect for spotting bottlenecks in APIs, background services, or CPU-bound operations.</p>
<ul>
<li><strong>NuGet</strong> (40M downloads) 🔗 https://www.nuget.org/packages/BenchmarkDotNet</li>
<li><strong>GitHub</strong> (11k stars) 🔗 https://github.com/dotnet/BenchmarkDotNet</li>
</ul>
<h2>2. MessagePack – Fastest JSON serializer</h2>
<p>Need speed beyond System.Text.Json or Newtonsoft.Json?  MessagePack is the fastest serializer for C# (.NET, .NET Core, Unity, Xamarin). MessagePack has a compact binary size and a full set of general-purpose expressive data types. Ideal for high-traffic APIs, IoT data processing, and microservices.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MessagePack.png" alt="MessagePack Benchmark" /></p>
<ul>
<li><strong>NuGet</strong> (204M downloads) 🔗 https://www.nuget.org/packages/messagepack</li>
<li><strong>GitHub</strong> (6.4K stars) 🔗 https://github.com/MessagePack-CSharp/MessagePack-CSharp</li>
</ul>
<h2>3. Polly – Resilience at scale</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Polly.png" alt="Polly" /></p>
<p>In distributed systems, failures are inevitable. <strong>Polly</strong> provides a fluent way to add <strong>retry, circuit-breaker, and fallback</strong> strategies.</p>
<ul>
<li>Handle transient faults gracefully</li>
<li>Improve uptime and user experience</li>
<li>Works seamlessly with HttpClient and gRPC</li>
</ul>
<p>A must-have for cloud-native .NET applications.</p>
<ul>
<li><strong>NuGet</strong> (1B downloads) 🔗 https://www.nuget.org/packages/polly/</li>
<li><strong>GitHub</strong> (14K stars) 🔗 https://github.com/App-vNext/Polly</li>
</ul>
<h2>4. MemoryPack – Zero-cost binary serialization</h2>
<p>If you need <strong>blazing-fast serialization</strong> for in-memory caching or network transport, <strong>MemoryPack</strong> is a game-changer.</p>
<ul>
<li>Zero-copy, zero-alloc serialization</li>
<li>Perfect for high-performance caching or game servers</li>
<li>Strongly typed and version-tolerant</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/MemoryPack.png" alt="MemoryPack" /></p>
<p>Great for real-time multiplayer games, chat apps, or financial systems.</p>
<ul>
<li><strong>NuGet</strong> (5.3M downloads) 🔗 https://www.nuget.org/packages/MemoryPack</li>
<li><strong>GitHub</strong> (4K stars) 🔗 https://github.com/Cysharp/MemoryPack</li>
</ul>
<h2>5. WolverineFx –  Ultra-low latency messaging</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine-logo.png" alt="wolverine" /></p>
<p>MediatR was one of the best mediator libraries, but now it's a paid library. Wolverine is a toolset for command execution and message handling within .NET applications. The killer feature of Wolverine is its very efficient command execution pipeline that can be used as:</p>
<ul>
<li>An <a href="https://wolverinefx.net/tutorials/mediator.html">inline &quot;mediator&quot; pipeline</a> for executing commands</li>
<li>A <a href="https://wolverinefx.net/guide/messaging/transports/local.html">local message bus</a> for in-application communication</li>
<li>A full-fledged <a href="https://wolverinefx.net/guide/messaging/introduction.html">asynchronous messaging framework</a> for robust communication and interaction between services when used in conjunction with low-level messaging infrastructure tools like RabbitMQ</li>
<li>With the <a href="https://wolverinefx.net/guide/http/">WolverineFx.Http</a> library, Wolverine's execution pipeline can be used directly as an alternative ASP.NET Core Endpoint provider</li>
</ul>
<p><em>image below is from <a href="https://www.codecrash.net/2024/02/06/Mediatr-versus-Wolverine-performance.html">codecrash.net</a></em>
<img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/wolverine.png" alt="WolverineFx" /></p>
<p>WolverineFx is great for cleanly separating business logic from controllers while unifying in-process mediator patterns with powerful distributed messaging in a single, high-performance .NET library.</p>
<ul>
<li><strong>NuGet</strong> (1.5M downloads) 🔗 https://www.nuget.org/packages/WolverineFx</li>
<li><strong>GitHub</strong> (1.7K stars) 🔗 https://github.com/JasperFx/wolverine</li>
</ul>
<h2>6.  Disruptor-net – Next generation free .NET mediator</h2>
<p>The Disruptor is a high-performance inter-thread message passing framework. A lock-free ring buffer for ultra-low latency messaging.
Features are:</p>
<ul>
<li><p>Zero memory allocation after initial setup (the events are pre-allocated).</p>
</li>
<li><p>Push-based consumers.</p>
</li>
<li><p>Optionally lock-free.</p>
</li>
<li><p>Configurable wait strategies.</p>
</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/Disruptor.png" alt="Disruptor" /></p>
<ul>
<li><strong>NuGet</strong> (1.2M downloads) 🔗 https://www.nuget.org/packages/Disruptor/</li>
<li><strong>GitHub</strong> (1.3K stars) 🔗 https://github.com/disruptor-net/Disruptor-net</li>
</ul>
<h2>7. CliWrap - Running command-line processes</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-11-High-Perf-DotNet-Libs/cliwrap.png" alt="CLIWrap" /></p>
<p>CliWrap makes it easy to <strong>run and manage external CLI processes in  .NET</strong>.</p>
<ul>
<li>Fluent, task-based API for starting commands</li>
<li>Streams standard input/output and error in real time</li>
<li>Supports cancellation, timeouts, and piping between processes</li>
</ul>
<p>Ideal for automation, build tools, and integrating external executables.</p>
<ul>
<li><strong>NuGet</strong> (14.1M downloads) 🔗 https://www.nuget.org/packages/CliWrap</li>
<li><strong>GitHub</strong> (4.7K stars) 🔗 https://github.com/Tyrrrz/CliWrap</li>
</ul>
<hr />
<h2>Hidden Libs from the Community</h2>
<h3>Sylvan.Csv &amp; <strong>Sep</strong></h3>
<ul>
<li><strong>Sylvan.Csv</strong>: Up to <em>10× faster</em> and <em>100× less memory allocations</em> than <code>CsvHelper</code>, making CSV processing lightning-fast. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
<li><strong>Sep</strong>: Even faster than Sylvan, but trades off some flexibility. Great when performance matters more than API richness. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
</ul>
<h3>String Parsing: <strong>csFastFloat</strong></h3>
<ul>
<li>Parses <code>float</code> and <code>double</code> around <em>8–9× faster</em> than <code>.Parse</code> methods—perfect for high-volume parsing tasks. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
</ul>
<h3>CySharp’s Suite: MemoryPack, MasterMemory, SimdLinq</h3>
<ul>
<li><strong>MemoryPack</strong>: One of the fastest serializers available, with low allocations and high throughput. Ideal for Web APIs or microservices. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
<li><strong>MasterMemory</strong>: Designed for databases or config storage. Claims <em>4,700× faster than SQLite</em> with zero-allocations per query. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
<li><strong>SimdLinq</strong>: SIMD-accelerated LINQ operations supporting a broader set of methods than  .NET's built-in SIMD. Works when slight floating-point differences are acceptable. (<a href="https://www.reddit.com/r/csharp/comments/191rwgt/extremely_highperformance_libraries_for_common/?utm_source=chatgpt.com">Reddit</a>)</li>
</ul>
<h3>Jil – JSON Deserializer</h3>
<ul>
<li>Ultra-fast JSON (de)serializer with low memory overhead, used in high-scale systems. (<a href="https://www.mattwarren.org/2014/09/05/stack-overflow-performance-lessons-part-2/?utm_source=chatgpt.com">Performance is a Feature!</a>)</li>
</ul>
<h3>StackExchange.NetGain – WebSocket Efficiency</h3>
<ul>
<li>High-performance WebSocket server library designed for low-latency IO scenarios. (Now mostly replaced by Kestrel's built-in support, but worth knowing.) (<a href="https://github.com/StackExchange/NetGain?utm_source=chatgpt.com">GitHub</a>)</li>
</ul>
<h3>Math Libraries: Math.NET Numerics &amp; ILNumerics</h3>
<ul>
<li><strong>Math.NET Numerics</strong>: Core numerical methods and matrix math, similar to BLAS/LAPACK. (<a href="https://en.wikipedia.org/wiki/Math.NET_Numerics?utm_source=chatgpt.com">Wikipedia</a>)</li>
<li><strong>ILNumerics</strong>: Efficient numerical arrays with parallelized processing, loop unrolling and cache optimizations. Great for scientific computing. (<a href="https://en.wikipedia.org/wiki/ILNumerics?utm_source=chatgpt.com">Wikipedia</a>)</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1c4b8c-4821-505f-263b-bdd2d4cbbf8f" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1c4b8c-4821-505f-263b-bdd2d4cbbf8f" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/.net-10-what-you-need-to-know-lts-release-coming-november-2025-xennnnky</guid>
      <link>https://abp.io/community/posts/.net-10-what-you-need-to-know-lts-release-coming-november-2025-xennnnky</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>EfCore</category>
      <category>csharp</category>
      <category>net10</category>
      <title>.NET 10: What You Need to Know (LTS Release, Coming November 2025)</title>
      <description>.NET 10 brings long-term support with major improvements across performance, runtime, and developer productivity. Key highlights include C# 14 language features, ASP.NET Core and EF Core enhancements, better passkey authentication, OpenAPI support, WebSocketStream, and updates for cross-platform development with .NET MAUI.</description>
      <pubDate>Wed, 10 Sep 2025 12:10:31 Z</pubDate>
      <a10:updated>2026-03-02T17:02:39Z</a10:updated>
      <content:encoded><![CDATA[<h1>.NET 10: What You Need to Know (LTS Release, Coming November 2025)</h1>
<p>The next version of .NET is .NET 10 and it is coming with <strong>Long-Term Support (LTS)</strong>, scheduled for <strong>November 2025</strong>.</p>
<p>On <strong>September 9, 2025</strong>, Microsoft released <strong>.NET 10 Release Candidate 1 (RC1)</strong>, which supports go-live usage and is compatible with <a href="https://visualstudio.microsoft.com/insiders/">Visual Studio 2026 Insider</a> and <a href="https://code.visualstudio.com/insiders/">Visual Studio Code Insider</a> via the <a href="https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit">C# Dev Kit</a> extension.</p>
<hr />
<h2>.NET 10 Runtime Enhancements</h2>
<ul>
<li><strong>JIT Speed-ups</strong>: Enhanced struct argument handling—members now go directly into registers, reducing memory load/store operations.</li>
<li><strong>Advanced Loop Optimization</strong>: New graph-based loop inversion improves precision and boosts further optimizations.</li>
<li><strong>Array Interface De-virtualization</strong>: Critical for performance, now array-based enumerations inline and skip virtual calls including de-abstraction of array enumeration and small-array stack allocation.</li>
<li><strong>General JIT Improvements</strong>: Better code layout and branch reduction support overall efficiency.</li>
</ul>
<hr />
<h2>Language &amp; Library Upgrades</h2>
<h3>C# 14 Enhancements</h3>
<ul>
<li>Field-backed properties: easier custom getters/setters.</li>
<li><code>nameof</code> for unbound generics like <code>List&lt;&gt;</code>.</li>
<li>Implicit conversions for <code>Span&lt;T&gt;</code> and <code>ReadOnlySpan&lt;T&gt;</code>.</li>
<li>Lambda parameter modifiers (<code>ref</code>, <code>in</code>, <code>out</code>).</li>
<li>Partial constructors/events.</li>
<li><code>extension</code> blocks for static extension members.</li>
<li>Null-conditional assignment (<code>?.=</code>) and custom compound/increment operators.</li>
</ul>
<h3>F# &amp; Visual Basic Enhancements</h3>
<ul>
<li>F# improvements via <code>&lt;LangVersion&gt;preview&lt;/LangVersion&gt;</code>, updated <code>FSharp.Core</code>, and compiler fixes.</li>
<li>VB compiler supports <code>unmanaged</code> generics and respects <code>OverloadResolutionPriorityAttribute</code> for performance and overload clarity.</li>
</ul>
<h2>.NET Libraries &amp; SDK</h2>
<h3>Libraries:</h3>
<ul>
<li>Better ZipArchive performance (lazy entry loading).</li>
<li>JSON improvements, including <code>JsonSourceGenerationOptions</code> and reference-handling tweaks.</li>
<li>Enhanced <code>OrderedDictionary</code>, ISOWeek date APIs, PEM data and certificate handling, <code>CompareOptions.NumericOrdering</code></li>
</ul>
<h3>SDK &amp; CLI:</h3>
<ul>
<li>No major new SDK features in RC1—you should expect stability fixes rather than additions.</li>
<li>Earlier previews brought JSON support improvements (e.g., <code>PipeReader</code> for JSON, WebSocketStream, ML-DSA crypto, AES KeyWrap), TLS 1.3 for macOS</li>
</ul>
<hr />
<h2>ASP.NET Core &amp; Blazor</h2>
<h3>Blazor &amp; Web App Security:</h3>
<p>Enhanced OIDC and Microsoft Entra ID integration, including encrypted token caching and Key Vault use.</p>
<h3>UI Enhancements:</h3>
<ul>
<li><code>QuickGrid</code> gains <code>RowClass</code> for conditional styling.</li>
<li>Scripts now served as static assets with compression and fingerprinting.</li>
<li>NavigationManager no longer scrolls to top for same-page updates.</li>
</ul>
<h3>API Improvements:</h3>
<p>Full support for OpenAPI 3.1 (JSON Schema draft 2020-12), and metrics for authentication/authorization events (e.g., sign-ins, logins) .</p>
<hr />
<h2>.NET MAUI</h2>
<p>Updates include multiple file selection, image compression, WebView request interception, and support for Android API 35/36.</p>
<h2>EF Core</h2>
<p>LINQ enhancements, performance boosts, better Azure Cosmos DB support, and more flexible named query filters.</p>
<h2>Breaking Changes in .NET 10</h2>
<h3>ASP.NET Core - Breaking Changes in .NET 10:</h3>
<p>.NET 10 Preview 7 brings <strong>several deprecations + behavior changes</strong>, while <strong>RC1 removes the old WebHost model</strong>.</p>
<ul>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/cookie-authentication-api-endpoints">Cookie login redirects disabled</a></strong> → Redirects no longer occur for API endpoints; APIs now return <code>401</code>/<code>403</code>. <em>(Behavioral change)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/withopenapi-deprecated">WithOpenApi deprecated</a></strong> → Extension method removed; use updated OpenAPI generator features. <em>(Source incompatible)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/exception-handler-diagnostics-suppressed">Exception diagnostics suppressed</a></strong> → When <code>TryHandleAsync</code> returns true, exception details aren’t logged. <em>(Behavioral change)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/iactioncontextaccessor-obsolete">IActionContextAccessor obsolete</a></strong> → Marked obsolete; may break code depending on it. <em>(Source/behavioral change)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/openapi-analyzers-deprecated">IncludeOpenAPIAnalyzers deprecated</a></strong> → Property and MVC API analyzers removed. <em>(Source incompatible)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/ipnetwork-knownnetworks-obsolete">IPNetwork &amp; KnownNetworks obsolete</a></strong> → Old networking APIs removed in favor of new ones. <em>(Source incompatible)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/apidescription-client-deprecated">ApiDescription.Client package deprecated</a></strong> → No longer maintained; migrate to other tools. <em>(Source incompatible)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/razor-runtime-compilation-obsolete">Razor run-time compilation obsolete</a></strong> → Disabled at runtime; precompilation required. <em>(Source incompatible)</em></li>
<li><strong><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/10/webhostbuilder-deprecated">WebHostBuilder, IWebHost, WebHost obsolete</a></strong> → Legacy hosting model deprecated; use <code>WebApplicationBuilder</code>. <em>(Source incompatible, RC1)</em></li>
</ul>
<h3>EF Core - Breaking Changes in .NET 10:</h3>
<p>You can find the complete list at <a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/breaking-changes">Microsoft EF Core 10 Breaking Changes page</a>. Here's the brief summary:</p>
<h4>EF Core - SQL Server</h4>
<ul>
<li><strong>JSON column type by default (Azure SQL / compat level ≥170).</strong> Primitive collections and owned types mapped to JSON now use SQL Server’s native <code>json</code> type instead of <code>nvarchar(max)</code>. A migration may alter existing columns. Mitigate by setting compat level &lt;170 or explicitly forcing <code>nvarchar(max)</code>.</li>
<li><strong><code>ExecuteUpdateAsync</code> signature change.</strong> Column setters now take a regular <code>Func&lt;…&gt;</code> (not an expression). Dynamic expression-tree code won’t compile; replace with imperative setters inside the lambda.</li>
</ul>
<h4>Microsoft.Data.Sqlite</h4>
<ul>
<li><strong><code>GetDateTimeOffset</code> (no offset) assumes UTC.</strong> Previously assumed local time. You can temporarily revert via <code>AppContext.SetSwitch(&quot;Microsoft.Data.Sqlite.Pre10TimeZoneHandling&quot;, true)</code>.</li>
<li><strong>Writing <code>DateTimeOffset</code> to REAL stores UTC.</strong> Conversion now happens before writing; revertable with the same switch.</li>
<li><strong><code>GetDateTime</code> (with offset) returns UTC <code>DateTime</code> (<code>DateTimeKind.Utc</code>).</strong> Was <code>Local</code> before. Same temporary switch if needed.</li>
</ul>
<h4>Who’s most affected</h4>
<ul>
<li>Apps on <strong>Azure SQL / SQL Server 2025</strong> using JSON mapping.</li>
<li>Codebases building <strong>expression trees</strong> for bulk updates.</li>
<li>Apps using <strong>SQLite</strong> with date/time parsing or REAL timestamp storage.</li>
</ul>
<h4>Quick mitigations</h4>
<ul>
<li>Set SQL Server compatibility &lt;170 or force column type.</li>
<li>Rewrite <code>ExecuteUpdateAsync</code> callers to use the new delegate form.</li>
<li>For SQLite, update handling to UTC or use the temporary AppContext switch while transitioning.</li>
</ul>
<h3>Containers - Breaking Changes in .NET 10:</h3>
<p>Default .NET images now use <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/containers/10.0/default-images-use-ubuntu">Ubuntu</a>.</p>
<h3>Core Libraries - Breaking Changes in .NET 10:</h3>
<p><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/activity-sampling">ActivitySource</a> behavior tweaks; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/generic-math">generic math</a> shift behavior aligned; W3C trace context is <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/default-trace-context-propagator">default</a>; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/driveinfo-driveformat-linux">DriveInfo</a> reports Linux FS types; InlineArray size rules tightened; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/asyncenumerable">System.Linq.AsyncEnumerable</a> included in core libs...</p>
<h3>Cryptography - Breaking Changes in .NET 10:</h3>
<p><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/x500distinguishedname-validation">Stricter X500</a> name validation; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/openssl-macos-unsupported">OpenSSL</a> primitives unsupported on macOS; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/mldsa-slhdsa-secretkey-to-privatekey">some key members</a> nullable/renamed; env var <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/cryptography/10.0/version-override">rename to</a> <code>DOTNET_OPENSSL_VERSION_OVERRIDE</code>.</p>
<h3>Extensions - Breaking Changes in .NET 10:</h3>
<p><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/configuration-null-values-preserved">Config preserves</a> nulls; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/console-json-logging-duplicate-messages">logging</a>/<a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/provideraliasattribute-moved-assembly">package</a>/trim annotations changes; some <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/extensions/10.0/dynamically-accessed-members-configuration">trim-unsafe</a> code annotations removed.</p>
<h3>Globalization &amp; Interop - Breaking Changes in .NET 10:</h3>
<p><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/globalization/10.0/version-override">ICU</a> env var renamed; single-file apps stop probing executable dir for native libs; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/interop/10.0/search-assembly-directory">DllImport</a> search path tightened.</p>
<p>Networking:</p>
<p><a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/http3-disabled-with-publishtrimmed">HTTP/3 disabled </a> by default when trimming; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/ssl-certificate-revocation-check-default">default cert revocation</a> check now Online; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/default-http-streaming">browser clients</a> stream responses by default; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/networking/10.0/uri-length-limits-removed">URI length limits</a> removed.</p>
<h3>SDK &amp; MSBuild/NuGet - Breaking Changes in .NET 10:</h3>
<p><code>dotnet --interactive</code> <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-cli-interactive">defaults to true</a>; tool packages are <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-tool-pack-publish">RID-specific</a>; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/default-workload-config">workload</a> sets default; <code>dotnet new sln</code> uses <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-new-sln-slnx-default">SLNX</a>; restore audits transitives; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-tool-install-local-manifest">local tool</a> install creates manifest by default; <code>project.json</code> <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/dotnet-restore-project-json-unsupported">not supported</a>; stricter NuGet <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/nuget-packageid-validation">validation</a>/<a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/sdk/10.0/http-warnings-to-errors">errors</a>.</p>
<p>WinForms/WPF:</p>
<p>Multiple <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/obsolete-apis">API obsoletions</a>/parameter <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/insertadjacentelement-orientation">renames</a>; <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/windows-forms/10.0/statusstrip-renderer">rendering</a>/behavior tweaks; stricter XAML rules (e.g., <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/wpf/10.0/empty-grid-definitions">disallow empty row</a>/column definitions or incorrect usage of <a href="https://learn.microsoft.com/en-us/dotnet/core/compatibility/wpf/10.0/dynamicresource-crash">DynamicResource</a> will crash).</p>
<hr />
<h2>Support Policy for .NET 10</h2>
<p>As you can see from the picture below, <strong>.NET 10 has long term support</strong> therefore it will be maintained for 3 years <strong>until November 2028</strong>.</p>
<p><a href="https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core"><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-2.png" alt=".NET 10 Support Policy" /></a></p>
<h2>Download .NET10</h2>
<p>Click 👉 https://dotnet.microsoft.com/en-us/download/dotnet/10.0 to download the latest release candidate (currently RC.1).</p>
<p><a href="https://dotnet.microsoft.com/en-us/download/dotnet/10.0"><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-09-10-NET10-What-You-Need-To-Know/image-1.png" alt="Download .NET 10" /></a></p>
<p>Also to use the latest features, download/update your Visual Studio to the latest 👉  https://visualstudio.microsoft.com/downloads/</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1c45b5-b5f4-7691-9361-0ddc9004b3fb" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1c45b5-b5f4-7691-9361-0ddc9004b3fb" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/best-free-alternatives-to-automapper-in-.net-why-we-moved-to-mapperly-l9f5ii8s</guid>
      <link>https://abp.io/community/posts/best-free-alternatives-to-automapper-in-.net-why-we-moved-to-mapperly-l9f5ii8s</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <title>Best Free Alternatives to AutoMapper in .NET  — Why We Moved to Mapperly</title>
      <description>AutoMapper has been one of the most popular mapping libraries for .NET apps. Now it's a paid library. In this article, we will see the alternatives to AutoMapper.</description>
      <pubDate>Wed, 27 Aug 2025 12:32:19 Z</pubDate>
      <a10:updated>2026-03-02T18:02:40Z</a10:updated>
      <content:encoded><![CDATA[<h1>Best Free Alternatives to AutoMapper in .NET  — Why We Moved to Mapperly</h1>
<hr />
<h2>Introduction</h2>
<p><a href="https://automapper.io/">AutoMapper</a> has been one of the most popular mapping library for .NET apps. It has been free and <a href="https://github.com/LuckyPennySoftware/AutoMapper">open-source</a> since 2009. On 16 April 2025, Jimmy Bogard (the owner of the project) decided to make it commercial for his own reasons. You can read <a href="https://www.jimmybogard.com/automapper-and-mediatr-licensing-update/">this announcement</a> about what happened to AutoMapper.</p>
<h3>Why AutoMapper’s licensing change matters</h3>
<p>In ABP Framework we have been also using AutoMapper for object mappings. After its commercial transition, we also needed to replace it. Because ABP Framework is open-source and under <a href="https://github.com/abpframework/abp#LGPL-3.0-1-ov-file">LGPL-3.0 license</a>.</p>
<p><strong>TL;DR</strong></p>
<blockquote>
<p>That's why, <strong>we decided to replace AutoMapper with Mapperly</strong>.</p>
</blockquote>
<p>In this article, we'll discuss the alternatives of AutoMapper so that you can cut down on costs and maximize performance while retaining control over your codebase. Also I'll explain why we chose Mapperly.</p>
<p>Also AutoMapper uses heavily reflection. And reflection comes with a performance cost if used indiscriminately, and compile-time safety is limited. Let's see how we can overcome these...</p>
<h2>Cost-Free Alternatives to AutoMapper</h2>
<p>Check out the comparison table for key features vs. AutoMapper.</p>
<p>|                     | <strong>AutoMapper (Paid)</strong>                           | <strong>Mapster (Free)</strong>                        | <strong>Mapperly (Free)</strong>                          | <strong>AgileMapper (Free)</strong>                      | <strong>Manual Mapping</strong>                               |
| ------------------- | ----------------------------------------------- | ----------------------------------------- | -------------------------------------------- | ------------------------------------------- | ------------------------------------------------ |
| <strong>License &amp; Cost</strong>  | Paid/commercial                                 | Free, MIT License                         | Free, MIT License                            | Free, Apache 2.0                            | Free (no library)                                |
| <strong>Performance</strong>     | Slower due to reflection &amp; conventions          | Very fast (runtime &amp; compile-time modes)  | Very fast (compile-time code generation)     | Good, faster than AutoMapper                | Fastest (direct assignment)                      |
| <strong>Ease of Setup</strong>   | Easy, but configuration-heavy                   | Easy, minimal config                      | Easy, but different approach from AutoMapper | Simple, flexible configuration              | Manual coding required                           |
| <strong>Features</strong>        | Rich features, conventions, nested mappings     | Strong typed mappings, projection support | Strong typed, compile-time safe mappings     | Dynamic &amp; conditional mapping               | Whatever you code                                |
| <strong>Maintainability</strong> | Hidden mappings can be hard to debug            | Explicit &amp; predictable                    | Very explicit, compiler-verified mappings    | Readable, good balance                      | Very explicit, most maintainable                 |
| <strong>Best For</strong>        | Large teams used to AutoMapper &amp; willing to pay | Teams wanting performance + free tool     | Teams prioritizing type-safety &amp; performance | Developers needing flexibility &amp; simplicity | Small/medium projects, performance-critical apps |</p>
<p>There are other libraries such as <a href="https://github.com/fluentsprings/ExpressMapper"><strong>ExpressMapper</strong></a> <strong>(308 GitHub stars)</strong>, <a href="https://github.com/omuleanu/ValueInjecter"><strong>ValueInjecter</strong></a> <strong>(258 GitHub stars)</strong>, <a href="https://github.com/agileobjects/AgileMapper"><strong>AgileMapper</strong></a> <strong>(463 GitHub stars)</strong>. These are not very popular but also free and offer a different balance of simplicity and features.</p>
<h2>Why We Chose Mapperly</h2>
<p>We filtered down all the alternatives into 2: <strong>Mapster</strong> and <strong>Mapperly</strong>.</p>
<p>The crucial factor was maintainability! As you see from the screenshots below, Mapster is already stopped development. Mapster’s development appears stalled, and its future maintenance is uncertain. On the other hand, Mapperly regularly gets commits. The community support is valuable.</p>
<p>We looked up different alternatives of AutoMapper also, here's the initial issue of AutoMapper replacement <a href="https://github.com/abpframework/abp/issues/23243">github.com/abpframework/abp/issues/23243</a>.</p>
<p>The ABP team started Mapperly integration with this initial commit <a href="https://github.com/abpframework/abp/commit/178d3f56d42b4e5acb7e349470f4a644d4c5214e">github.com/abpframework/abp/commit/178d3f56d42b4e5acb7e349470f4a644d4c5214e</a>. And this is our Mapperly integration package : <a href="https://github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.Mapperly.">github.com/abpframework/abp/tree/dev/framework/src/Volo.Abp.Mapperly.</a></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-08-25-AutoMapper-Alternatives/mapster-mapperly-community-powers.png" alt="Community Powers" /></p>
<p>Here are some considerations for developers who are used to ABP and AutoMapper.</p>
<h3><a href="https://github.com/MapsterMapper/Mapster">Mapster</a>:</h3>
<ul>
<li>✔ It is similar to AutoMapper, configuring mappings through code.</li>
<li>✔ Support for dependency injection and complex runtime configuration.</li>
<li>❌ It is looking additional Mapster maintainers (<a href="https://github.com/MapsterMapper/Mapster/discussions/752">Call for additional Mapster maintainers MapsterMapper/Mapster#752</a>)</li>
</ul>
<h3><a href="https://github.com/riok/Mapperly">Mapperly</a>:</h3>
<ul>
<li>✔ It generates mapping code(<code> source generator</code>) during the build process.</li>
<li>✔ It is actively being developed and maintained.</li>
<li>❌ It is a static <code>map</code> method, which is not friendly to dependency injection.</li>
<li>❌ The configuration method is completely different from AutoMapper, and there is a learning curve.</li>
</ul>
<p><strong>Mapperly</strong> → generates mapping code at <strong>compile time</strong> using source generators.</p>
<p><strong>Mapster</strong> → has two modes:</p>
<ul>
<li><p>By default, it uses <strong>runtime code generation</strong> (via expression trees and compilation).</p>
</li>
<li><p>But with <strong>Mapster.Tool</strong> (source generator), it can also generate mappings at <strong>compile time</strong>.</p>
</li>
</ul>
<p>This is important because it guarantees the mappings are working well. Also they provide type safety and improved performance. Another advantages of these libraries, they eliminate runtime surprises and offer better IDE support.</p>
<hr />
<h2>When Mapperly Will Come To ABP</h2>
<p>Mapperly integration will be delivered with ABP v10. If you have already defined AutoMapper configurations, you can still keep and use them. But the framework will use Mapperly. So there'll be 2 mapping integrations in your app. You can also remove AutoMapper from your final application and use one mapping library: Mapperly. It's up to you! Check <a href="https://automapper.io/#pricing">AutoMapper pricing table</a>.</p>
<h2>Migrating from AutoMapper to Mapperly</h2>
<p>In ABP v10, we will be migrating from AutoMapper to Mapperly. The document about the migration is not delivered by the time I wrote this article, but you can reach the document in our dev docs branch</p>
<ul>
<li><a href="https://github.com/abpframework/abp/blob/dev/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md">github.com/abpframework/abp/blob/dev/docs/en/release-info/migration-guides/AutoMapper-To-Mapperly.md</a>.</li>
</ul>
<p>Also for ABP, you can check out how you will define DTO mappings based on Mapperly at this document</p>
<ul>
<li><a href="https://github.com/abpframework/abp/blob/dev/docs/en/framework/infrastructure/object-to-object-mapping.md">github.com/abpframework/abp/blob/dev/docs/en/framework/infrastructure/object-to-object-mapping.md</a></li>
</ul>
<h2>Mapping  Code Examples for AutoMapper, Mapster, AgileMapper</h2>
<h3>AutoMapper vs Mapster vs Mapperly Performance</h3>
<p>Here are concise, drop-in <strong>side-by-side C# snippets</strong> that map the same model with AutoMapper, Mapster, AgileMapper, and manual mapping.</p>
<p>Models used in all examples</p>
<p>We'll use these models to show the mapping examples for AutoMapper, Mapster, AgileMapper.</p>
<pre><code class="language-csharp">public class Order
{
    public int Id { get; set; }
    public Customer Customer { get; set; } = default!;
    public List&lt;OrderLine&gt; Lines { get; set; } = new();
    public DateTime CreatedAt { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; } = &quot;&quot;;
    public string? Email { get; set; }
}

public class OrderLine
{
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
}

public class OrderDto
{
    public int Id { get; set; }
    public string CustomerName { get; set; } = &quot;&quot;;
    public int ItemCount { get; set; }
    public decimal Total { get; set; }
    public string CreatedAtIso { get; set; } = &quot;&quot;;
}
</code></pre>
<h4>AutoMapper Example (Paid)</h4>
<pre><code class="language-csharp">public sealed class OrderProfile : Profile
{
    public OrderProfile()
    {
        CreateMap&lt;Order, OrderDto&gt;()
            .ForMember(d =&gt; d.CustomerName, m =&gt; m.MapFrom(s =&gt; s.Customer.Name))
            .ForMember(d =&gt; d.ItemCount,   m =&gt; m.MapFrom(s =&gt; s.Lines.Sum(l =&gt; l.Quantity)))
            .ForMember(d =&gt; d.Total,       m =&gt; m.MapFrom(s =&gt; s.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice)))
            .ForMember(d =&gt; d.CreatedAtIso,m =&gt; m.MapFrom(s =&gt; s.CreatedAt.ToString(&quot;O&quot;)));
    }
}

// registration
services.AddAutoMapper(typeof(OrderProfile));

// mapping
var dto = mapper.Map&lt;OrderDto&gt;(order);

// EF Core projection (common pattern)
var list = dbContext.Orders
    .ProjectTo&lt;OrderDto&gt;(mapper.ConfigurationProvider)
    .ToList();
</code></pre>
<p><strong>NuGet Packages:</strong></p>
<ul>
<li>https://www.nuget.org/packages/AutoMapper</li>
<li>https://www.nuget.org/packages/AutoMapper.Extensions.Microsoft.DependencyInjection</li>
</ul>
<hr />
<h4>Mapperly (Free, Apache-2.0)</h4>
<p>This is compile-time generated mapping.</p>
<pre><code class="language-csharp">[Mapper] // generates the implementation at build time
public partial class OrderMapper
{
    // Simple property mapping: Customer.Name -&gt; CustomerName
    [MapProperty(nameof(Order.Customer) + &quot;.&quot; + nameof(Customer.Name), nameof(OrderDto.CustomerName))]
    public partial OrderDto ToDto(Order source);

    // Update an existing target (like MapToExisting)
    [MapProperty(nameof(Order.Customer) + &quot;.&quot; + nameof(Customer.Name), nameof(OrderDto.CustomerName))]
    public partial void UpdateDto(Order source, OrderDto target);

    public OrderDto Map(Order s)
    {
        var d = ToDto(s);
        AfterMap(s, d);
        return d;
    }

    public void Map(Order source, OrderDto d)
    {
        UpdateDto(source, d);
        AfterMap(source, d);
    }

    private void AfterMap(Order source, OrderDto d)
    {
        d.ItemCount = source.Lines.Sum(l =&gt; l.Quantity);
        d.Total = source.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice);
        d.CreatedAtIso = source.CreatedAt.ToString(&quot;O&quot;);
    }
}


//USAGE
var mapper = new OrderMapper();
var order = new Order
{
    Id = 1,
    Customer = new Customer { Id = 1, Name = &quot;John Doe&quot;, Email = &quot;johndoe@abp.io&quot; },
    Lines =
    [
        new OrderLine {ProductId = 1, Quantity = 2, UnitPrice = 10.0m},
        new OrderLine {ProductId = 2, Quantity = 1, UnitPrice = 20.0m}
    ]
};

// Map to a new object
var dto = mapper.Map(order);

// Map to an existing object
var target = new OrderDto();
mapper.Map(order, target);
</code></pre>
<p><strong>NuGet Packages:</strong></p>
<ul>
<li>https://www.nuget.org/packages/Riok.Mapperly/</li>
</ul>
<hr />
<h4>Mapster Example (Free, MIT)</h4>
<pre><code class="language-csharp">TypeAdapterConfig&lt;Order, OrderDto&gt;.NewConfig()
    .Map(d =&gt; d.CustomerName, s =&gt; s.Customer.Name)
    .Map(d =&gt; d.ItemCount,    s =&gt; s.Lines.Sum(l =&gt; l.Quantity))
    .Map(d =&gt; d.Total,        s =&gt; s.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice))
    .Map(d =&gt; d.CreatedAtIso, s =&gt; s.CreatedAt.ToString(&quot;O&quot;));

// one-off
var dto = order.Adapt&lt;OrderDto&gt;();

// DI-friendly registration
services.AddSingleton(TypeAdapterConfig.GlobalSettings);
services.AddScoped&lt;IMapper, ServiceMapper&gt;();

// EF Core projection (strong suit)
var mappedList = dbContext.Orders
    .ProjectToType&lt;OrderDto&gt;()   // Mapster projection
    .ToList();
</code></pre>
<p><strong>NuGet Packages:</strong></p>
<ul>
<li>https://www.nuget.org/packages/Mapster</li>
<li>https://www.nuget.org/packages/Mapster.DependencyInjection</li>
<li>https://www.nuget.org/packages/Mapster.SourceGenerator (for performance improvement)</li>
</ul>
<hr />
<h4>AgileMapper Example (Free, Apache-2.0)</h4>
<pre><code class="language-csharp">var mapper = Mapper.CreateNew(cfg =&gt;
{
    cfg.WhenMapping
       .From&lt;Order&gt;()
       .To&lt;OrderDto&gt;()
       .Map(ctx =&gt; ctx.Source.Customer.Name).To(dto =&gt; dto.CustomerName)
       .Map(ctx =&gt; ctx.Source.Lines.Sum(l =&gt; l.Quantity)).To(dto =&gt; dto.ItemCount)
       .Map(ctx =&gt; ctx.Source.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice)).To(dto =&gt; dto.Total)
       .Map(ctx =&gt; ctx.Source.CreatedAt.ToString(&quot;O&quot;)).To(dto =&gt; dto.CreatedAtIso);
});

var mappedDto = mapper.Map(order).ToANew&lt;OrderDto&gt;();
</code></pre>
<p><strong>NuGet Packages:</strong></p>
<ul>
<li>https://www.nuget.org/packages/AgileObjects.AgileMapper</li>
</ul>
<hr />
<h4>Manual (Pure) Mapping (no library)</h4>
<p>Straightforward, fastest, and most explicit. Good for simple applications which doesn't need long term maintenance.  Hand-written mapping is faster, safer, and more maintainable. And for tiny mappings, you can still use manual mapping.</p>
<ul>
<li>Examples of when manual mapping is better than libraries.</li>
</ul>
<pre><code class="language-csharp">public static class OrderMapping
{
    public static OrderDto ToDto(this Order s) =&gt; new()
    {
        Id = s.Id,
        CustomerName = s.Customer.Name,
        ItemCount = s.Lines.Sum(l =&gt; l.Quantity),
        Total = s.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice),
        CreatedAtIso = s.CreatedAt.ToString(&quot;O&quot;)
    };
}

// usage
var dto = order.ToDto();

// EF Core projection (best for perf + SQL translation)
var mappedList = dbContext.Orders.Select(s =&gt; new OrderDto
    {
        Id = s.Id,
        CustomerName = s.Customer.Name,
        ItemCount = s.Lines.Sum(l =&gt; l.Quantity),
        Total = s.Lines.Sum(l =&gt; l.Quantity * l.UnitPrice),
        CreatedAtIso = s.CreatedAt.ToString(&quot;O&quot;)
    }).ToList();
</code></pre>
<h3>Conclusion</h3>
<p>If you rely on AutoMapper today, it’s time to evaluate alternatives. For ABP Framework, we chose <strong>Mapperly</strong> due to active development, strong community, and compile-time performance. But your team may prefer <strong>Mapster</strong> for flexibility or even manual mapping for small apps. Your requirements might be different, your project is not a framework so you decide the best one for you.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1bfdb0-a1fe-cfbe-acea-3cb7065e49e4" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1bfdb0-a1fe-cfbe-acea-3cb7065e49e4" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/urlbased-localization-3ivzinbb</guid>
      <link>https://abp.io/community/posts/urlbased-localization-3ivzinbb</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <title>URL-Based Localization</title>
      <description>I'll show you how to optimize your ABP website localization with a URL parameter. So you can use https://fabrikam.com/en/ or https://fabrikam.com/tr/</description>
      <pubDate>Wed, 05 Mar 2025 13:22:20 Z</pubDate>
      <a10:updated>2026-03-02T16:36:48Z</a10:updated>
      <content:encoded><![CDATA[<h1>URL-Based Localization</h1>
<p>In this article I'll show you how to optimize your ABP website localization with a URL parameter. URL Paths are commonly being used to change the current UI culture. This method makes our website SEO-Friendly as you structuring the URLs for multiple languages. And you can also share the link of your website with a specific language. Let's see implementing multi-language support with URL parameters in an ABP project.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/scrshot1.jpg" alt="Turkish and English Localization within URL" /></p>
<h2>Mastering Website Localization: Language Codes in URLs Explained</h2>
<p>Enhancing UX with URL-Based website localization is mainly done with ASP.NET Core's routing system. Also we need to automatically redirect the links without language code parameter. Our URL structures for the localization will be as following:</p>
<ul>
<li>https://mywebsite.com/en/dashboard  (English)</li>
<li>https://mywebsite.com/tr/dashboard (Turkish)</li>
</ul>
<h2>Routing</h2>
<p>Before starting to explain how to do this, you can see <a href="https://github.com/salihozkara/MultiLangRoute/commit/09e40cfd751562dec0dab890e54e0c5ca9ee256c">this commit</a> which implements this functionality. The routing module consists of these fundamental classes:</p>
<h3>1. <strong>MultiLanguageSupportMetaData.cs</strong></h3>
<p>This class is used to add a language parameter to route templates. For example, it changes the <code>/about</code> route to <code>/language/about</code>.</p>
<h3>2. <strong>MultiLanguageRedirectRequiredMetaData.cs</strong></h3>
<p>This class is used to redirect users to the correct language version. If a user visits the <code>/about</code> page and the current culture is <code>&quot;tr-TR&quot;</code>, this class will redirect them to <code>/tr-TR/about</code>.</p>
<h3>3. <strong>UrlNormalizer.cs</strong></h3>
<p>This static class is used to normalize URLs by adding language information and improving performance using caching.</p>
<pre><code class="language-csharp">public static string NormalizeUrl(EndpointDataSource endpointDataSource, HttpContext httpContext, string url)
{
    // Normalize the URL and cache it
    return Cache.GetOrAdd(url, (key) =&gt;
    {
        var absoluteUrl = GetAbsoluteUrl(key);
        var multiLanguageRedirectRequiredMetaData =
            GetMultiLanguageRedirectRequiredMetaData(endpointDataSource, absoluteUrl);
        return multiLanguageRedirectRequiredMetaData?.ReBuildUrl(httpContext, key) ?? key;
    });
}
</code></pre>
<h3>4. <strong>MyLinkGenerator.cs</strong></h3>
<p>This class extends ASP.NET Core’s <code>LinkGenerator</code> class to automatically add language information to all generated links.</p>
<h3>5. <strong>MyRouteDataRequestCultureProvider.cs</strong></h3>
<p>This class determines the current culture using the language parameter in the URL. For example, it extracts the <code>&quot;tr-TR&quot;</code> culture from the <code>/tr-TR/about</code> URL.</p>
<h3>6. <strong>RoutingMiddleware.cs</strong></h3>
<p>This middleware processes HTTP requests and redirects users to the correct language version when necessary.</p>
<pre><code class="language-csharp">public override Task InvokeAsync(HttpContext context, RequestDelegate next)
{
    var endpoint = context.GetEndpoint();
    if(endpoint is not RouteEndpoint)
    {
        return next(context);
    }
    
    // Redirect if necessary
    var redirectMetaData = endpoint.Metadata.GetMetadata&lt;IRedirectMetaData&gt;();
    if (redirectMetaData is not null)
    {
        redirectMetaData.Redirect(context);
        return Task.CompletedTask;
    }

    // ...
}
</code></pre>
<h2>CultureAnchorTagHelper.cs</h2>
<p>This <strong>Tag Helper</strong> processes <code>&lt;a&gt;</code> tags in a Razor page and automatically adds language information to URLs if it's missing.</p>
<pre><code class="language-csharp">[HtmlTargetElement(&quot;a&quot;, Attributes = &quot;href&quot;, TagStructure = TagStructure.NormalOrSelfClosing)]
public class CultureAnchorTagHelper(EndpointDataSource endpointDataSource, IHttpContextAccessor contextAccessor)
    : TagHelper, ITransientDependency
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        var href = output.Attributes[&quot;href&quot;].Value.ToString();
        if (href != null)
        {
            output.Attributes.SetAttribute(&quot;href&quot;,
                UrlNormalizer.NormalizeUrl(endpointDataSource, contextAccessor.HttpContext!, href));
        }
    }
}
</code></pre>
<p><strong>How This Tag Helper Works:</strong></p>
<ul>
<li>Finds all <code>&lt;a href=&quot;...&quot;&gt;</code> tags within your Razor pages.</li>
<li>Retrieves the <code>href</code> attribute of each link.</li>
<li>Uses the <code>UrlNormalizer.NormalizeUrl()</code> method to normalize the URL with the current culture information.</li>
<li>Replaces the original URL with the normalized one.</li>
</ul>
<p>For example, if the current culture is <code>&quot;tr&quot;</code> and a page contains <code>&lt;a href=&quot;/about&quot;&gt;</code>, this Tag Helper will transform it into <code>&lt;a href=&quot;/tr-TR/about&quot;&gt;</code>.</p>
<h2>Sample Project</h2>
<p>Salih Özkara from ABP team created a sample working project which implements URL localization. He used ABP free tier MVC template and MongoDB. You can check out the related commit which implements URL localization:</p>
<p>https://github.com/salihozkara/MultiLangRoute/commit/09e40cfd751562dec0dab890e54e0c5ca9ee256c</p>
<p>And full working demo is available at:</p>
<p>https://github.com/salihozkara/MultiLangRoute</p>
<p>You can download the demo project at:</p>
<p><a href="https://github.com/abpframework/abp/blob/634ff52fb07d0b1281640695dbeffccdc943ca53/docs/en/Community-Articles/2024-03-05-URL-Based-Localization/UrlLocalizationSampleProject.zip">UrlLocalizationSampleProject.zip</a></p>
<h2>Summary</h2>
<p>This implementation extends ASP.NET Core’s routing mechanism and utilizes caching for improved performance. It ensures multilingual support by normalizing URLs, redirecting users to the appropriate language version, and automatically handling language-specific links.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1878a5-881f-731f-0c5a-9f754b144e00" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1878a5-881f-731f-0c5a-9f754b144e00" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/migrate-your-db-from-the-web-application-adding-a-db-migration-controller-in-abp-framework-x3u3uvk3</guid>
      <link>https://abp.io/community/posts/migrate-your-db-from-the-web-application-adding-a-db-migration-controller-in-abp-framework-x3u3uvk3</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <title>Migrate Your DB from the Web Application — Adding a DB Migration Controller in ABP Framework</title>
      <description>In some scenarios, you might prefer updating your ABP project's database by visiting a URL rather than running a console application (such as a typical DbMigrator project). This post demonstrates how to do that in an ABP application...</description>
      <pubDate>Fri, 14 Feb 2025 11:59:48 Z</pubDate>
      <a10:updated>2026-03-02T16:52:49Z</a10:updated>
      <content:encoded><![CDATA[<p>In some scenarios, you might prefer to <strong>update your ABP project's database by simply visiting a URL</strong> rather than running a console application (such as a typical <code>DbMigrator</code> project). This post demonstrates how to do that in an ABP application. In my sample application I used the single-layer project but you can benefit the same approach for other templates. My sample project name was created with this name: <strong>Acme.BookStore</strong>.</p>
<hr />
<h2>Step 1: Remove the Existing Localization Middleware</h2>
<p>Open your web project's module class file—this is typically in <code>BookStoreModule.cs</code> if you’re using the no-layer template.
Or if your project is multi-layered, it's <code>BookStoreWebModule.cs</code>. Find the below line and <strong>remove</strong> it:</p>
<pre><code class="language-csharp">app.UseAbpRequestLocalization();
</code></pre>
<p>The reason is that the localization middleware depends on the database, which does not yet exist!
We'll add this middleware conditionally in the next step.</p>
<hr />
<h2>Step 2: Conditionally Use the Localization Middleware</h2>
<p>We only want <code>AbpRequestLocalizationMiddleware</code> for routes <strong>other than</strong> our new migration endpoint (<code>/api/migrate</code>). To achieve this, we use <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/">Middleware Branching</a>. Our new controller will work on <code>/api/migrate</code> endpoint, so let's add a condition for this specific URL.</p>
<pre><code class="language-csharp">app.UseWhen(httpContext =&gt;
    !httpContext.Request.Path.StartsWithSegments(&quot;/api/migrate&quot;, StringComparison.OrdinalIgnoreCase),
    appBuilder =&gt;
    {
        appBuilder.UseAbpRequestLocalization();
    }
);
</code></pre>
<p>This ensures all requests except <code>/api/migrate</code> will still use <code>AbpRequestLocalization</code> middleware.</p>
<hr />
<h2>Step 3: Create the Migration Controller</h2>
<p>Create a new file named <code>MigrationController.cs</code> under your <code>Controllers</code> folder or wherever you store controllers.
Then copy-paste the following class:</p>
<pre><code class="language-csharp">using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Data;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Saas.Tenants;

namespace Acme.BookStore.Web.Controllers //TODO: you may need to fix this namespace!
{
    [Route(&quot;api&quot;)]
    [IgnoreAntiforgeryToken]
    public class MigrationController : AbpController
    {
        private const string DefaultAdminEmail = &quot;admin@admin.com&quot;;
        private const string DefaultAdminPassword = &quot;My-Admin-Password&quot;;

        private readonly IDataSeeder _dataSeeder;
        private readonly ITenantRepository _tenantRepository;
        private readonly ICurrentTenant _currentTenant;
        private readonly IEnumerable&lt;DbSchemaMigrator&gt; _dbSchemaMigrators;

        public MigrationController(
            IDataSeeder dataSeeder,
            ITenantRepository tenantRepository,
            ICurrentTenant currentTenant,
            IEnumerable&lt;DbSchemaMigrator&gt; dbSchemaMigrators)
        {
            _dataSeeder = dataSeeder;
            _tenantRepository = tenantRepository;
            _currentTenant = currentTenant;
            _dbSchemaMigrators = dbSchemaMigrators;
        }

        [HttpGet]
        [Route(&quot;migrate&quot;)]
        public async Task&lt;IActionResult&gt; MigrateAsync(CancellationToken cancellationToken)
        {
            try
            {
                Logger.LogInformation(&quot;Started database migrations...&quot;);

                await MigrateDatabaseSchemaAsync();
                await SeedDataAsync();

                Logger.LogInformation(&quot;Successfully completed host database migrations. Started migrating tenant databases...&quot;);

                if (_currentTenant.IsAvailable) // or check MultiTenancyConsts.IsEnabled
                {
                    await MigrateTenantDatabases(cancellationToken);
                }

                Logger.LogInformation(&quot;Successfully completed all database migrations.&quot;);
                return Ok(&quot;Migration and seed completed successfully.&quot;);
            }
            catch (Exception ex)
            {
                return BadRequest($&quot;An error occurred during migration: {ex.Message}&quot;);
            }
        }

        private async Task MigrateTenantDatabases(CancellationToken cancellationToken)
        {
            var tenants = await _tenantRepository.GetListAsync(includeDetails: true, cancellationToken: cancellationToken);

            var migratedDatabaseSchemas = new HashSet&lt;string&gt;();
            foreach (var tenant in tenants)
            {
                using (_currentTenant.Change(tenant.Id))
                {
                    if (tenant.ConnectionStrings.Any())
                    {
                        var tenantConnectionStrings = tenant.ConnectionStrings
                            .Select(x =&gt; x.Value)
                            .ToList();

                        if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings))
                        {
                            await MigrateDatabaseSchemaAsync(tenant);
                            migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);
                        }
                    }

                    await SeedDataAsync(tenant);
                }

                Logger.LogInformation($&quot;Successfully completed {tenant.Name} tenant database migrations.&quot;);
            }
        }

        private async Task MigrateDatabaseSchemaAsync(Tenant tenant = null)
        {
            Logger.LogInformation($&quot;Migrating schema for {(tenant == null ? &quot;host&quot; : tenant.Name + &quot; tenant&quot;)} database...&quot;);
            foreach (var migrator in _dbSchemaMigrators)
            {
                await migrator.MigrateAsync();
            }
        }

        private async Task SeedDataAsync(Tenant tenant = null)
        {
            Logger.LogInformation($&quot;Executing {(tenant == null ? &quot;host&quot; : tenant.Name + &quot; tenant&quot;)} database seed...&quot;);

            await _dataSeeder.SeedAsync(
                new DataSeedContext(tenant?.Id)
                    .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, DefaultAdminEmail)
                    .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, DefaultAdminPassword)
            );
        }
    }
}
</code></pre>
<hr />
<h2>Step 4: Navigate to the Migration URL</h2>
<p>Build and run your web application. Then visit:</p>
<pre><code>https://your-website.com/api/migrate
</code></pre>
<p>If your database did not exist, it will be created, and the default data will be seeded. If you enabled multi-tenancy, the tenant databases will also be migrated in this solution.</p>
<hr />
<p><strong>That’s all there is to it!</strong> By adding a simple controller and selectively applying the localization middleware, you can migrate your ABP app’s database with a single URL.</p>
<p>Happy coding 😊</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a181681-26a0-971a-8062-bf4bde8bc902" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a181681-26a0-971a-8062-bf4bde8bc902" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-framework-background-jobs-vs-background-workers-when-to-use-which-t98pzjv6</guid>
      <link>https://abp.io/community/posts/abp-framework-background-jobs-vs-background-workers-when-to-use-which-t98pzjv6</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>abp-essentials</category>
      <title>ABP Framework: Background Jobs vs Background Workers — When to Use Which?</title>
      <description>Are you confused about ABP Framework's Background Jobs and Background Workers? Yes, it might be a little bit confusing.  Let's clarify these terms...</description>
      <pubDate>Fri, 03 Jan 2025 09:47:06 Z</pubDate>
      <a10:updated>2026-03-02T17:02:11Z</a10:updated>
      <content:encoded><![CDATA[<h1>ABP Framework: Background Jobs vs Background Workers — When to Use Which?</h1>
<p>In the ABP Framework, <strong>Background Jobs</strong> and <strong>Background Workers</strong> serve different purposes but can sometimes seem interchangeable. Sometimes it can be confusing. Let’s clarify their differences, and I'll show you some real-world cases to help you understand how to decide between these two. We have official documents for these:</p>
<p>📕 <strong>Background Workers ABP Document</strong>  https://abp.io/docs/latest/framework/infrastructure/background-workers</p>
<p>📘 <strong>Background Jobs ABP Document</strong> https://abp.io/docs/latest/framework/infrastructure/background-jobs</p>
<hr />
<p>I posted this article because recently, I came across <a href="https://abp.io/support/questions/5931/Background-Jobs-vs-Background-Workers-when-to-use-which">this support ticket</a> on the ABP support website. I thought these terms could be confusing for devs. He has two tasks and is asking whether he needs to use Background Worker or Background Job.</p>
<ul>
<li>The first one is <code>FileRecievedActivity.</code> He says it's running 2 times a day. So, it's a recurring activity that needs to run in the background. So <code>FileRecievedActivity</code> is a &quot;Background Worker&quot;.</li>
<li>The second one is <code>ProcessQueueFiles</code>. It sounds like a polling task. It runs whenever a new file comes to the directory. So, it's also a recurring task that needs to be scheduled every 1 minute. Hence the <code>ProcessQueueFiles</code> is also &quot;Backgrounder Worker.&quot;</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2025-01-03-ABP-Background-Workers-vs-Jobs/support-question.png" alt="https://abp.io/support/questions/5931/Background-Jobs-vs-Background-Workers-when-to-use-which" /></p>
<h2>Background Workers  🔄 <em>/Looping/</em></h2>
<p>The background workers are stateless and runs in-memory as long as the application is up and ready.</p>
<ul>
<li><strong>Purpose</strong>: Long-running, periodic tasks that run continuously in the background. They are queued and executed asynchronously.</li>
<li><strong>Lifetime:</strong> Runs throughout the application's lifetime.</li>
<li><strong>Scheduling:</strong> Executes on a fixed schedule, like every X minutes / hours...</li>
<li><strong>Infrastructure</strong>: ABP uses an in-memory implementation for running background workers.  You can also use the 3rd party tools for running your background worker:
<ul>
<li><a href="https://abp.io/docs/latest/framework/infrastructure/background-workers/quartz">Quartz + ABP integration</a></li>
<li><a href="https://abp.io/docs/latest/framework/infrastructure/background-workers/hangfire">Hangfire + ABP integration</a></li>
</ul>
</li>
</ul>
<p><strong>Use Cases:</strong> Use background workers for any task that needs to run repeatedly at fixed intervals. For example &quot;Health checks&quot;, &quot;Periodic cleanup tasks&quot;, &quot;Monitoring tasks&quot;, &quot;Processing daily data&quot;...  In the last section, you will find real-world examples.</p>
<blockquote>
<p>In Microsoft Docs, this topic is called &quot;Background Tasks&quot;. Check out <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services">Microsoft's official doc for running background tasks</a>.</p>
</blockquote>
<hr />
<h2>Background Jobs ▶ <em>/One time/</em></h2>
<ul>
<li><strong>Purpose:</strong> One-time tasks that need to be queued and can be executed in the background. Here the main goal is not to block the application to run the task.</li>
</ul>
<ul>
<li><p><strong>Lifetime</strong>: Executes one time and completes.</p>
</li>
<li><p><strong>Scheduling</strong>: Can be delayed/scheduled for a specific time.</p>
</li>
<li><p><strong>Infrastructure</strong>: ABP uses in-memory implementation but you can also use the below 3rd party tools:</p>
<ul>
<li><p><a href="https://abp.io/docs/latest/framework/infrastructure/background-jobs/hangfire">Hangfire + ABP implementation</a></p>
</li>
<li><p><a href="https://abp.io/docs/latest/framework/infrastructure/background-jobs/rabbitmq">RabbitMQ + ABP implementation</a></p>
</li>
<li><p><a href="https://abp.io/docs/latest/framework/infrastructure/background-jobs/quartz">Quartz + ABP implementation</a></p>
</li>
</ul>
</li>
</ul>
<p><strong>Use Cases:</strong> Use background jobs to send emails, process uploaded files, generating reports, any fire-and-forget tasks or tasks that need retry mechanisms.</p>
<blockquote>
<p>In Microsoft docs this topic is called as &quot;Background Tasks&quot;. Check out <a href="https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs">Microsoft's official background jobs doc</a>.</p>
</blockquote>
<h2>When to Use Which?</h2>
<h3>Use Background Workers when:</h3>
<ul>
<li><p>You need continuous, recurring execution</p>
</li>
<li><p>The task should run as long as the application is running</p>
</li>
<li><p>You don't need persistence in task state</p>
</li>
<li><p>You want in-memory, efficient execution</p>
</li>
</ul>
<h3>Use Background Jobs when:</h3>
<ul>
<li><p>You need one-time execution</p>
</li>
<li><p>The task should survive application restarts</p>
</li>
<li><p>You need guaranteed execution</p>
</li>
<li><p>You want built-in retry mechanisms</p>
</li>
<li><p>You need to queue multiple instances of the same task</p>
</li>
</ul>
<h2>Technical Differences</h2>
<pre><code class="language-csharp">// A Background Worker Example
public class MyBackgroundWorker : AsyncPeriodicBackgroundWorkerBase
{
    public MyBackgroundWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory) 
        : base(timer, serviceScopeFactory)
    {
        Timer.Period = 5000; // Runs every 5 seconds
    }
}

// A Background Job Example
public class MyBackgroundJob : AsyncBackgroundJob&lt;MyArgs&gt;
{
    public override async Task ExecuteAsync(MyArgs args)
    {
        // Executes once when triggered
    }
}

// Triggering a Background Job
await _backgroundJobManager.EnqueueAsync(
    new MyArgs { /* ... */ },
    delay: TimeSpan.FromHours(2)
);
</code></pre>
<blockquote>
<p>While background workers no additional infrastructure needed, background jobs requires a database to persist jobs (or a distributed cache/message broker depending on the implementation)</p>
</blockquote>
<h2>🚩 Background Worker Examples</h2>
<h3>1) Querying an external API</h3>
<ul>
<li><strong>Scenario</strong>: Continuously fetch data from an external API at regular intervals.</li>
<li><strong>Why a Background Worker?</strong>: You need a long-running process to poll the API and handle the results.</li>
</ul>
<pre><code class="language-csharp">public class ApiPollingWorker : AsyncPeriodicBackgroundWorkerBase
{
    private readonly IAmazonPriceService _apiService;

    public ApiPollingWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IAmazonPriceService apiService)
        : base(timer, serviceScopeFactory)
    {
        _apiService = apiService;
        Timer.Period = 60000; // Run every 1 minute
    }

    protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
    {
        var data = await _apiService.FetchPricesAsync();
        // Process the data
    }
}
</code></pre>
<p>Here are practical examples of <strong>Background Workers</strong> that demonstrate how to use them effectively within the ABP Framework. Background Workers are ideal for long-running or periodic tasks that require stateful or persistent execution.</p>
<h3>2) Polling an External API</h3>
<ul>
<li><strong>Scenario</strong>: Continuously fetch data from an external API at regular intervals.</li>
<li><strong>Why a Background Worker?</strong>: You need a long-running process to poll the API and handle the results.</li>
</ul>
<pre><code>csharpCopy codepublic class ApiPollingWorker : AsyncPeriodicBackgroundWorkerBase
{
    private readonly IApiService _apiService;

    public ApiPollingWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IApiService apiService)
        : base(timer, serviceScopeFactory)
    {
        _apiService = apiService;
        Timer.Period = 60000; // Run every 1 minute
    }

    protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
    {
        var data = await _apiService.FetchDataAsync();
        // Process the data
    }
}
</code></pre>
<h3>3) Processing a Queue</h3>
<ul>
<li><strong>Scenario</strong>: Continuously process items from a queue, such as Azure Service Bus or RabbitMQ.</li>
<li><strong>Why a Background Worker?</strong>: This requires a stateful, persistent process to monitor and handle the queue.</li>
</ul>
<pre><code class="language-csharp">public class QueueProcessingWorker : AsyncBackgroundWorker
{
    private readonly IQueueService _queueService;

    public QueueProcessingWorker(IServiceScopeFactory serviceScopeFactory, IQueueService queueService)
        : base(serviceScopeFactory)
    {
        _queueService = queueService;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            var message = await _queueService.GetNextMessageAsync();
            if (message != null)
            {
                await _queueService.ProcessMessageAsync(message);
            }
            await Task.Delay(1000, stoppingToken); // Delay for throttling
        }
    }
}
</code></pre>
<h3>4) Maintaining a Database</h3>
<ul>
<li><strong>Scenario</strong>: Perform periodic database maintenance, rebuild indices or cleanup tasks.</li>
<li><strong>Why a Background Worker?</strong>: These are recurring tasks requiring regular execution.</li>
</ul>
<pre><code class="language-csharp">public class DatabaseCleanupWorker : AsyncPeriodicBackgroundWorkerBase
{
    private readonly ICleanupService _cleanupService;

    public DatabaseCleanupWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, ICleanupService cleanupService)
        : base(timer, serviceScopeFactory)
    {
        _cleanupService = cleanupService;
        Timer.Period = 3600000; // Run every hour
    }

    protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
    {
        await _cleanupService.DeleteOldRecordsAsync();
    }
}
</code></pre>
<h3>5) Running a Health Check Service</h3>
<ul>
<li><strong>Scenario</strong>: Periodically check the health of connected services and log their status.</li>
<li><strong>Why a Background Worker?</strong>: Periodic health checks are naturally suited to background workers.</li>
</ul>
<pre><code class="language-csharp">public class HealthCheckWorker : AsyncPeriodicBackgroundWorkerBase
{
    private readonly IHealthCheckService _healthCheckService;

    public HealthCheckWorker(AbpAsyncTimer timer, IServiceScopeFactory serviceScopeFactory, IHealthCheckService healthCheckService)
        : base(timer, serviceScopeFactory)
    {
        _healthCheckService = healthCheckService;
        Timer.Period = 60000; // Run every minute
    }

    protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
    {
        await _healthCheckService.PerformChecksAsync();
    }
}
</code></pre>
<hr />
<h2>🚩 Background Job Examples</h2>
<h3>1) Email Notifications</h3>
<ul>
<li><strong>Scenario</strong>: Sending a welcome email to new users.</li>
<li><strong>Why a Background Job?</strong>: The email sending process doesn’t need to block the main application thread. It can run in the background, and failed jobs can be retried.</li>
</ul>
<pre><code class="language-csharp">public class SendWelcomeEmailJob : IBackgroundJob&lt;string&gt;
{
    private readonly IEmailSender _emailSender;

    public SendWelcomeEmailJob(IEmailSender emailSender)
    {
        _emailSender = emailSender;
    }

    public async Task ExecuteAsync(string emailAddress)
    {
        await _emailSender.SendAsync(
            emailAddress,
            &quot;Welcome!&quot;,
            &quot;Thank you for signing up to our service.&quot;
        );
    }
}
</code></pre>
<h3>2) Data Import/Export</h3>
<ul>
<li><strong>Scenario</strong>: Exporting a large dataset to a CSV file and notifying the user once complete.</li>
<li><strong>Why a Background Job?</strong>: Long-running tasks like file generation can be processed asynchronously.</li>
</ul>
<pre><code class="language-csharp">public class ExportDataJob : IBackgroundJob&lt;int&gt;
{
    private readonly IDataExporter _dataExporter;
    private readonly INotificationService _notificationService;

    public ExportDataJob(IDataExporter dataExporter, INotificationService notificationService)
    {
        _dataExporter = dataExporter;
        _notificationService = notificationService;
    }

    public async Task ExecuteAsync(int userId)
    {
        var filePath = await _dataExporter.ExportAsync(userId);
        await _notificationService.NotifyAsync(userId, &quot;Your data export is complete: &quot; + filePath);
    }
}
</code></pre>
<h3>3) Push Notifications</h3>
<ul>
<li><strong>Scenario</strong>: Sending push notifications to users about specific events (e.g., “Your order has been shipped!”).</li>
<li><strong>Why a Background Job?</strong>: Push notifications are non-blocking and can be handled in bulk in the background.</li>
</ul>
<pre><code class="language-csharp">public class SendPushNotificationJob : IBackgroundJob&lt;PushNotificationInput&gt;
{
    private readonly IPushNotificationService _pushNotificationService;

    public SendPushNotificationJob(IPushNotificationService pushNotificationService)
    {
        _pushNotificationService = pushNotificationService;
    }

    public async Task ExecuteAsync(PushNotificationInput input)
    {
        await _pushNotificationService.SendAsync(input.UserId, input.Message);
    }
}
</code></pre>
<h3>4) File Upload Processing</h3>
<ul>
<li><strong>Scenario</strong>: Processing a file uploaded by a user (e.g., parsing, validating, and saving to a database).</li>
<li><strong>Why a Background Job?</strong>: File processing can be offloaded to the background, ensuring quick user feedback.</li>
</ul>
<pre><code class="language-csharp">public class ProcessFileUploadJob : IBackgroundJob&lt;FileProcessingInput&gt;
{
    private readonly IFileParser _fileParser;
    private readonly IDataService _dataService;

    public ProcessFileUploadJob(IFileParser fileParser, IDataService dataService)
    {
        _fileParser = fileParser;
        _dataService = dataService;
    }

    public async Task ExecuteAsync(FileProcessingInput input)
    {
        var parsedData = await _fileParser.ParseAsync(input.FilePath);
        await _dataService.SaveAsync(parsedData);
    }
}
</code></pre>
<h2>Final Words</h2>
<p>Use <strong>Background Workers</strong> for stateful, continuous operations and <strong>Background Jobs</strong> for isolated, retriable units of work.</p>
<p>I hope this article will clarify these terms in ABP Framework.</p>
<p>https://abp.io/ a complete web application platform.</p>
<p>Happy coding😊</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a173dbc-8d96-cf6d-9ac7-f163271eaa9e" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a173dbc-8d96-cf6d-9ac7-f163271eaa9e" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/builtin-openapi-document-generation-with-.net-9-no-more-swaggerui--au56cck5</guid>
      <link>https://abp.io/community/posts/builtin-openapi-document-generation-with-.net-9-no-more-swaggerui--au56cck5</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>dotnet-9.0</category>
      <title>Built-in OpenAPI Document Generation with .NET 9 — No more SwaggerUI! 👋</title>
      <description>SwaggerUI has been removed from the .NET 9 web templates. Introducing the new built-in OpenAPI documentation system by the Microsoft team...</description>
      <pubDate>Wed, 13 Nov 2024 15:27:13 Z</pubDate>
      <a10:updated>2026-03-02T18:25:48Z</a10:updated>
      <content:encoded><![CDATA[<h1>Built-in OpenAPI Document Generation with .NET 9 — No more SwaggerUI! 👋</h1>
<h2>What’s Swagger UI?</h2>
<p><a href="https://swagger.io/">Swagger UI</a> is an open-source tool that automatically generates an interactive, web-based documentation interface for WebAPIs.
It supports OpenAPI standards. It was very popular tool among the ASP.NET Core developers from 2020 to 2024.
Because it was a built-in tool comes with ASP.NET Core default templates.
We liked this tool because it was the first tool that allows us to make WebAPI calls for testing.
Now it provides paid services as well as free ones.</p>
<blockquote>
<p>Previously, Swagger was included by default from <strong>.NET 5</strong> to <strong>.NET 8</strong> in .NET web templates.</p>
</blockquote>
<hr />
<h2>What’s OpenAPI?</h2>
<p>OpenAPI is a standard specification for defining REST APIs.
The official website is <a href="https://www.openapis.org/">https://www.openapis.org/</a>.
Microsoft is now using OpenAPI and here is the official documentation 👉 <a href="https://aka.ms/aspnet/openapi">https://aka.ms/aspnet/openapi</a></p>
<hr />
<h2>Replacement of Swagger UI with OpenAPI</h2>
<p>Swagger UI is no longer integrated into NET 9, as Microsoft wants a solution with first-class support, better control, and enhanced security. As you see in the below screenshot, Microsoft declares that it's already removed.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img2.png" alt="Docs" /></p>
<hr />
<h2>Why is Swagger Removed from .NET 9?</h2>
<p>In March 2024, the ASP.NET Core team announced that they are removing the <code>Swashbuckle.AspNetCore</code> dependency from web templates from .NET 9 release.</p>
<blockquote>
<p>This decision was influenced by the project's lack of active maintenance and the absence of an official release for .NET 8.</p>
</blockquote>
<p>Microsoft team created a new package <code>Microsoft.AspNetCore.OpenApi</code>. It provides built-in OpenAPI document generation just like Swagger. So Microsoft doesn't depend on external tools. Because in every .NET release, they need to ask the owners of the external tool libraries to align with their new version. And sometimes these library owners cannot update their code-base according to the recent .NET changes. And it is becoming harder for Microsoft to support the 3rd party libraries under these circumstances. Basically reducing 3rd party dependencies will help Microsoft fast release cycles.</p>
<p>I read Reddit, GitHub discussions and YouTube reviews about this topic. As I see community members expressed concerns about the inactivity of Swashbuckle and they are discussing alternatives like contributing to or forking the project. The Microsoft team also contacted the owners of Swashbuckle and NSwag to explore potential collaborations and ensure a smooth transition for developers.</p>
<p>In the below GitHub issue, you can see the details of this decision:</p>
<ul>
<li><a href="https://github.com/dotnet/aspnetcore/issues/54599">github.com/dotnet/aspnetcore/issues/54599</a></li>
</ul>
<p><strong>Jeremy</strong> -Product Manager- at Microsoft, answers why they took this decision in <a href="https://github.com/dotnet/aspnetcore/issues/54599#issuecomment-2004975574">this post</a>.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img3.png" alt="Jeremy Comments" /></p>
<p>As a summary;</p>
<p><strong>The change is due to a lack of maintenance of the Swagger library</strong>, although it has seen some recent updates. This aims to reduce dependency on external tools and provide a streamlined, out-of-the-box experience for generating OpenAPI documentation for ASP.NET Core Web APIs.</p>
<hr />
<h2>What are the Benefits of the New OpenAI Package?</h2>
<h3>Native Support and Reduced Dependency</h3>
<p>The new <code>Microsoft.AspNetCore.OpenApi</code> package provides first-class citizen support for OpenAPI. It reduces reliance on external tools like Swashbuckle or NSwag for basic documentation needs. The native implementation leverages source generators to reduce runtime overhead.</p>
<h3>Simplified Configuration</h3>
<p>No need extra setup or 3rd party integrations. Just by defining controllers and endpoints, ASP.NET Core automatically generates OpenAPI specifications.</p>
<h3>Well Integration with Minimal APIs</h3>
<p><a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis">Minimal APIs</a> introduced in .NET 6. There's an optimized built-in support for Minimal APIs. It automatically adds metadata for routes, request parameters, and responses.</p>
<h3>Compatibility with Existing Tools</h3>
<p>You can still use the output of OpenAPI with Swagger or NSwag... So it doesn't mean that in this case you have only one option when you use OpenAPI.</p>
<hr />
<h2>How to Use the New OpenAPI in .NET9?</h2>
<p>When you create a new ASP.NET Core project, you can see the below checkbox to add OpenAPI.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img5.png" alt="New .NET 9 Project Screen" /></p>
<p>I created a new .NET 9 web project, I saw that OpenAPI had already been added.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img4.png" alt="Package Reference" /></p>
<h2>Add OpenAPI Support For Your Existing Project</h2>
<p>Upgrade your project to .NET 9 and add the required NuGet package <a href="https://www.nuget.org/packages/Microsoft.AspNetCore.OpenApi">Microsoft.AspNetCore.OpenApi</a></p>
<pre><code>dotnet add package Microsoft.AspNetCore.OpenApi
</code></pre>
<h3></h3>
<p>Add the following services and middleware in <code>Program.cs</code></p>
<pre><code>var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi(); //&lt;&lt;-----
var app = builder.Build();
app.MapOpenApi(); //&lt;&lt;-----
app.MapGet(&quot;/&quot;, () =&gt; &quot;Test&quot;);
app.Run();
</code></pre>
<p>Your OpenAPI document URL is <a href="https://localhost:7077/openapi/v1.json"><em>https://localhost:7077/openapi/v1.json</em></a></p>
<p>Change the port to your active port. This is how it looks like:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-11-13-BuiltIn-OpenApi-Documentation/img1.png" alt="Web UI of the Documentation" /></p>
<hr />
<h1>Alternative 3rd Party Tool: Scalar</h1>
<p><strong>Scalar</strong> is an open-source API platform for RestAPI documentation. Also, it provides an interface for interacting with RESTful API. Generates interactive and user-friendly API documentation. Supports OpenAPI and Swagger specifications. It’s open-source with <strong>7K stars</strong> on GitHub.</p>
<p>See the repo 👉 <a href="https://github.com/scalar/scalar">https://github.com/scalar/scalar</a>.</p>
<p>That's all from the replacement of Swagger in .NET 9.
Happy coding 👨‍💻</p>
<p><strong>References</strong></p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#openapi">https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#openapi</a></li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a16384f-9f70-dcdf-58ed-95a4c8aea777" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a16384f-9f70-dcdf-58ed-95a4c8aea777" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-now-supports-.net-9-zpkznc4f</guid>
      <link>https://abp.io/community/posts/abp-now-supports-.net-9-zpkznc4f</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>abp</category>
      <category>release</category>
      <title>ABP Now Supports .NET 9</title>
      <description>The stable version of .NET 9 will be released on November 12, 2024 🎉 The ABP Platform is fully ready for the new .NET version 🚀 We already updated all the modules and application templates 👊 Check out the blog post for the updates 💥</description>
      <pubDate>Wed, 23 Oct 2024 11:48:22 Z</pubDate>
      <a10:updated>2026-03-02T17:47:47Z</a10:updated>
      <content:encoded><![CDATA[<h1>ABP Now Supports .NET 9</h1>
<p><strong>.NET 9.0.100-rc.2</strong>  has been released on <strong>October 8, 2024</strong>. To align with the latest .NET, we also released the ABP Platform <a href="https://github.com/abpframework/abp/releases/tag/9.0.0-rc.1">9.0.0-rc.1</a> version.
<strong>With this release, ABP now supports .NET 9.</strong></p>
<p>The .NET 9 stable version is planned to be released on <strong>November 12, 2024</strong> before the <a href="https://www.dotnetconf.net/">.NET Conf 2024</a> event. The ABP 9.0 stable version is planned to be released on November 19, 2024.</p>
<hr />
<ul>
<li><p><strong>Download the .NET 9 runtime</strong> and SDK from the following link:</p>
<p><a href="https://dotnet.microsoft.com/en-us/download/dotnet/9.0">https://dotnet.microsoft.com/en-us/download/dotnet/9.0</a></p>
</li>
<li><p>There are many enhancements and bug fixes with ABP 9.0. Read the ABP 9 announcement:</p>
<p>https://abp.io/blog/announcing-abp-9-0-release-candidate</p>
</li>
<li><p>Read <strong>our migration ABP 9.0 migration guide</strong> from the following link:</p>
<p><a href="https://abp.io/docs/9.0/release-info/migration-guides/abp-9-0">abp.io/docs/9.0/release-info/migration-guides/abp-9-0</a></p>
</li>
<li><p>The following is the <strong>PR is for the .NET 9 upgrade</strong> in the ABP source code:</p>
<p><a href="https://github.com/abpframework/abp/pull/20803">https://github.com/abpframework/abp/pull/20803</a></p>
</li>
</ul>
<hr />
<h2>.NET 9 Releases</h2>
<p>In the following link, you can find <strong>a list of all .NET 9 releases</strong> with direct links to release notes and announcements/discussions:</p>
<ul>
<li>https://github.com/dotnet/core/discussions/9234</li>
</ul>
<hr />
<h2>ABP Supports Both .NET 8 &amp; .NET 9</h2>
<p>The ABP 9.0 version fully supports .NET 9 within our new templates and modules. For developers who want to update their ABP packages to the latest but want to keep them in .NET 8, <strong>we support both .NET 8 and .NET 9</strong> in ABP 9. In your host application, you can choose your target framework.</p>
<p>So you can decide which version you want to use in your startup Host Application’s <code>&lt;TargetFramework&gt;</code> tag.</p>
<p>In <a href="https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp/Volo.Abp.csproj#L7">this link</a> you can see that netstandard2.0/2.1 and net8/9 are supported.</p>
<pre><code class="language-xml">&lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;&gt;
    &lt;TargetFrameworks&gt;
      netstandard2.0;netstandard2.1;net8.0;net9.0
    &lt;/TargetFrameworks&gt;
&lt;/Project&gt;
</code></pre>
<h3>New ASP.NET Core Middleware: Static Asset Delivery</h3>
<p><code>MapStaticAssets</code> is a new middleware that helps optimize the delivery of static assets in any ASP.NET Core app, including Blazor apps. With this change, some <code>JavaScript/CSS/Images</code> files exist in the <a href="https://abp.io/docs/latest/framework/infrastructure/virtual-file-system?_redirected=B8ABF606AA1BDF5C629883DF1061649A">Virtual File System</a>, but the new ASP.NET Core 9 <code>MapStaticAssets</code> can't handle them. You need to add <code>StaticFileMiddleware</code> to serve these files. In ABP 9, we added <code>MapAbpStaticAssetsan </code>extension method to support the new <code>MapStaticAssets</code>. You can read about this new feature at <a href="https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#static-asset-delivery-optimization">this link</a>.
ABP’s new extension method is available <a href="https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/AbpApplicationBuilderExtensions.cs#L129-L198">here</a>.</p>
<hr />
<h2>How to Upgrade from .NET 8 to .NET 9:</h2>
<p>Install the latest .NET 9 SDK from <a href="https://dotnet.microsoft.com/en-us/download/dotnet/9.0">this link</a>.
Upgrade <a href="https://learn.microsoft.com/en-us/ef/core/cli/dotnet">dotnet-ef</a> tool version with the following command:</p>
<pre><code class="language-bash">dotnet tool uninstall --global dotnet-ef &amp;&amp; dotnet tool install --global dotnet-ef
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/ef-core-upgrade.png" alt="EF Core Upgrade" /></p>
<ol>
<li>Change all <code>TargetFramework</code> tags from <code>net8.0</code> to <code>net9.0</code>.</li>
<li>Upgrade all Microsoft NuGet packages to <code>9.0.0</code>.</li>
<li>If you have <code>global.json</code>, update <code>dotnet</code>version to <code>9.0.0</code> .</li>
<li>Replace<code>app.UseStaticFiles()</code> to <code>app.MapAbpStaticAssets()</code> in your module classes and startup projects.
<a href="https://github.com/abpframework/abp/commit/0f34f6dfcdbeb5d27fd63cf764f1ef13eb9cdfcd">See the related changes in the repository.</a></li>
</ol>
<hr />
<h2>What’s new with .NET 9</h2>
<p><strong>.NET 9 Blazor New Features</strong></p>
<ul>
<li>https://abp.io/community/articles/asp.net-core-blazor-9.0-new-features-summary--x0fovych</li>
</ul>
<p><strong>.NET 9 Performance Improvements Summary</strong></p>
<ul>
<li>https://abp.io/community/articles/.net-9-performance-improvements-summary-gmww3gl8</li>
</ul>
<p><strong>What’s new in .NET 9 (Microsoft’s post)</strong></p>
<ul>
<li>https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/overview</li>
</ul>
<hr />
<h2>We Are Eating Our Own Dog Food</h2>
<p>Before we release any version of ABP, <strong>we test our upcoming version</strong> on our sample apps and live website https://abp.io. The ABP.io website is also built on top of the ABP Framework, and you can see that we have already started to use .NET 9-rc.2 on our live website.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/dog-food.png" alt="Eating our own dog food" /></p>
<hr />
<h2>Microsoft .NET Support Policy</h2>
<p>Lastly, I want to mention Microsoft's .NET support policy.</p>
<ul>
<li><strong>.NET 7</strong> support has been <strong>finished</strong> on <strong>May 2024</strong>.</li>
<li><strong>.NET 8</strong> will be supported until <strong>November 2026</strong>.</li>
<li><strong>.NET 9</strong> is on the standard term support, which means Microsoft will release patches until <strong>May 2026</strong>.</li>
</ul>
<p>Find detailed information about the .NET support policy at <a href="https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core">this link.</a></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-10-23-Abp-Net9-Upgrade/net-support-policy.png" alt=".NET Core Official Support Policy" /></p>
<hr />
<h2>Finally</h2>
<p>.NET 9 is making a significant impact. It introduces features like Native AOT for faster applications, enhanced AI integration and improved tools for cloud-native and cross-platform development, all aimed at simplifying developers’ work. Whether you’re handling small projects or large-scale enterprise applications, it offers enhancements that <strong>elevate your productivity by just upgrading your .NET version to 9.0</strong></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a15cb61-b600-7175-6557-c38da5616783" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a15cb61-b600-7175-6557-c38da5616783" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/when-to-use-cookies-when-to-use-local-storage-uexsjunf</guid>
      <link>https://abp.io/community/posts/when-to-use-cookies-when-to-use-local-storage-uexsjunf</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>frontend</category>
      <category>javascript</category>
      <title>When to Use Cookies, When to Use Local Storage?</title>
      <description>When you want to save client-side data in browsers, you either use Cookies or Local Storage. So which one do we use?</description>
      <pubDate>Wed, 16 Oct 2024 12:45:50 Z</pubDate>
      <a10:updated>2026-03-02T13:07:22Z</a10:updated>
      <content:encoded><![CDATA[<h1>When to Use Cookies, When to Use Local Storage?</h1>
<h2>Cookies vs Local Storage</h2>
<p>When you want to save client-side data on browsers, you can use <code>Cookies</code> or <code>Local Storage</code> of the browser. While these methods look similar, they have different behaviors. You need to decide based on the specific use-case, security concerns and the data size being stored. I'll clarify the differences between these methods.</p>
<h2>When to use Cookies 🍪?</h2>
<ol>
<li><strong>Server Communication (e.g: Authentication Tokens):</strong> Cookies are ideal when you need to send data automatically with HTTP requests to the server, such as authentication tokens (JWTs) or session IDs. Cookies can be configured to be sent only to specific domains or paths, making them useful for session management.</li>
<li><strong>Cross-Domain Communication:</strong> Cookies can be shared across subdomains, which is useful when working with multiple subdomains under the same parent domain for microservice architecture.</li>
<li><strong>Expiration Control:</strong> Cookies come with built-in expiration times. You don’t need to manually remove them after a certain period that should expire.</li>
<li><strong>Security:</strong> Cookies can be marked as <code>HttpOnly</code> which makes them accessible <strong>only via the server</strong>, not via JavaScript! Also, when you set a cookie attribute, <code>Secure</code> it can be sent only over HTTPS, which forces enhanced security for sensitive data.</li>
</ol>
<h3>Considerations for Cookies</h3>
<ul>
<li><strong>Size Limitation:</strong> Cookies are generally limited to around 4KB of data.</li>
<li><strong>Security Risks:</strong> Cookies are susceptible to cross-site scripting (XSS) attacks unless marked <code>HttpOnly</code>.</li>
</ul>
<hr />
<h2>When to use Local Storage🗄️?</h2>
<ol>
<li><strong>Client-Side Data Storage:</strong> Local storage is ideal for storing large amounts of data (up to 5–10 MB) that doesn’t need to be sent to the server with every request. For example; <em>user preferences</em>, <em>settings</em>, or <em>cached data</em>.</li>
<li><strong>Persistence:</strong> Data in local storage persists even after the browser is restarted. This behavior makes it useful for long-term storage needs.</li>
<li><strong>No Automatic Server Transmission:</strong> Local storage data is never automatically sent to the server, which can be a security advantage if you don’t want certain data to be exposed to the server or included in the requests.</li>
</ol>
<h3>Considerations for Local Storage</h3>
<ul>
<li><p><strong>Security Risks:</strong> Local storage is accessible via JavaScript, making it vulnerable to XSS attacks. Sensitive data should not be stored in local storage unless adequately encrypted.</p>
</li>
<li><p><strong>No Expiration Mechanism:</strong> Local storage does not have a built-in expiration mechanism. You must manually remove the data when it’s no longer needed.</p>
</li>
</ul>
<hr />
<h2>Summary</h2>
<h3>Use Cookies</h3>
<ul>
<li>For data that needs to be sent to the server with HTTP requests, particularly for session management or authentication purposes.</li>
</ul>
<h3>Use Local Storage</h3>
<ul>
<li>For storing large amounts of client-side data that doesn’t need to be automatically sent to the server and for data that should persist across browser sessions.</li>
</ul>
<p>In many cases, you might use both cookies and local storage, depending on the specific requirements of different parts of your application. There are also other places where you can store the client-side data. You can check out <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">this article</a> for more information.</p>
<p>Happy coding 🧑🏽‍💻</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a15a789-cf73-716b-738c-4df20271b682" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a15a789-cf73-716b-738c-4df20271b682" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/.net-9-performance-improvements-summary-gmww3gl8</guid>
      <link>https://abp.io/community/posts/.net-9-performance-improvements-summary-gmww3gl8</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>release</category>
      <category>dotnet</category>
      <title>.NET 9 Performance Improvements Summary</title>
      <description>With the .NET 9 release, your app becomes faster! Simply by updating to the.NET 9 runtime, you get these improvements for free. Read what's improved in the latest release...</description>
      <pubDate>Wed, 09 Oct 2024 09:22:54 Z</pubDate>
      <a10:updated>2026-03-02T13:41:08Z</a10:updated>
      <content:encoded><![CDATA[<h1>.NET 9 Performance Improvements Summary</h1>
<p>With every release, .NET becomes faster &amp; faster! You get these improvements for free by just updating your project to the latest .NET!</p>
<p>It’s very interesting that <strong>20% of these improvements</strong> are implemented by <strong>open-source volunteers</strong> rather than Microsoft employees. These improvements mostly focus on cloud-native and high-throughput applications. I’ll briefly list them below.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-10-09-NET9-Performance-Improvements/cited-from-microsoft-blog-post.png" alt="From Microsoft Blog Post" /></p>
<h2>1. Dynamic PGO with JIT Compiler</h2>
<ul>
<li><h3>What is dynamic PGO?</h3>
<p>With “Profile Guided Optimization” the compiler optimizes the code, based on the flow and the way the code executes. It is predicated on the idea that every potential behavior of the code will always transpire.</p>
</li>
<li><h3>What’s Improved?</h3>
<p>The tiered compilation, inlining, and dynamic PGO are three ways that .NET 9 optimizes the JIT compiler. This enhances runtime performance and speeds up the time for apps to launch.</p>
</li>
<li><h3>Performance Gains</h3>
<p>CPU use is lower during execution; therefore, <strong>startup times are about 15% faster</strong>.</p>
</li>
<li><h3>As a Developer</h3>
<p>Faster, smoother deployments with reduced warm-up times... These enhancements reduce latency for applications with complex workflows, particularly in microservices and high-throughput environments.</p>
</li>
<li><h3>How to activate Dynamic PGO?</h3>
<p>Add the following to your <code>csproj</code> file, or if you have several <code>csproj</code> files, you can add it once in <code>Directory.Build.props</code> file. Check out <a href="https://learn.microsoft.com/en-us/dotnet/core/runtime-config/compilation#profile-guided-optimization">this link</a> to understand PGO.</p>
</li>
</ul>
<pre><code class="language-xml">  &lt;PropertyGroup&gt;
    &lt;TieredPGO&gt;true&lt;/TieredPGO&gt;
  &lt;/PropertyGroup&gt;
</code></pre>
<h2>2. Library Improvements</h2>
<ul>
<li><h3>What’s Improved?</h3>
<p>LINQ and JSON serialization, collections and libraries are significantly improved with .NET 9.</p>
</li>
<li><h3>Performance Gains</h3>
<p><strong>JSON serialization</strong> performance <strong>increases by about 35%</strong>. This helps with heavy data parsing and API requests. Less memory is allocated to <code>Span</code> operations as well, and LINQ techniques such as <code>Where</code> and <code>Select</code> are now faster.</p>
</li>
<li><h3>As a Developer</h3>
<p>This means that apps will be faster, especially those that handle data primarily in JSON or manipulate data with LINQ.</p>
</li>
</ul>
<h2>3. ASP.NET Core</h2>
<ul>
<li><h3>What’s Improved?</h3>
<p>Kestrel server has undergone significant modifications, mostly in processing the HTTP/2 and HTTP/3 protocols.</p>
</li>
<li><h3>Performance Gains</h3>
<p>Now, <strong>Kestrel handles requests up to 20% faster</strong> and <strong>has a 25% reduction in average latency</strong>. Improved connection management and SSL processing also result in overall efficiency gains.</p>
</li>
<li><h3>As a Developer</h3>
<p>These modifications result in less resource use, quicker response times for web applications, and more seamless scaling in high-traffic situations.</p>
</li>
</ul>
<h2>4. Garbage Collection &amp; Memory Management</h2>
<ul>
<li><h3>What’s Improved?</h3>
<p>NET 9’s garbage collection (GC) is more effective, especially for apps with high allocation rates.</p>
</li>
<li><h3>Performance Gains</h3>
<p>Applications experience smoother <strong>garbage collection cycles with 8–12% less memory overhead</strong>, which lowers latency and delays.</p>
</li>
<li><h3>As a Developer</h3>
<p>The performance will be more reliable and predictable for developers as there will be fewer memory-related bottlenecks, particularly in applications that involve frequent object allocations.</p>
</li>
</ul>
<h2>5. Native AOT Compilation</h2>
<ul>
<li><h3>What’s Improved?</h3>
<p>Native AOT (Ahead-of-Time) compilation is now more efficient by lowering memory footprint and cold-start times. This leads to better support for cloud-native applications.</p>
</li>
<li><h3>Performance Gains</h3>
<p>Native AOT apps now have faster cold launches and use <strong>30–40% less memory</strong>. This improvement focuses on containerized applications.</p>
</li>
</ul>
<hr />
<p><strong>References:</strong></p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-9/">Microsoft .NET blog post</a>.</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-9/runtime#performance-improvements">What’s new in the .NET 9 runtime?</a></li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1582c3-8080-4283-7f3f-6d3cf8758abd" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1582c3-8080-4283-7f3f-6d3cf8758abd" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/asp.net-core-signalr-new-features-summary-kcydtdgq</guid>
      <link>https://abp.io/community/posts/asp.net-core-signalr-new-features-summary-kcydtdgq</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>signalr</category>
      <category>dotnet</category>
      <title>ASP.NET Core SignalR New Features — Summary</title>
      <description>With .NET 9, some new features have come to SignalR. Let's summarize these enhancements.</description>
      <pubDate>Thu, 03 Oct 2024 08:21:41 Z</pubDate>
      <a10:updated>2026-03-02T16:19:25Z</a10:updated>
      <content:encoded><![CDATA[<h3>ASP.NET Core SignalR New Features — Summary</h3>
<p>In this article, I’ll highlight the latest .<strong>NET 9 SignalR updates</strong> for ASP.NET Core 9.0.</p>
<h3>SignalR Hub Accepts Base Classes</h3>
<p>SignalR <code>Hub</code> class can now get a base class of a polymorphic class. As you see in the example below, I can send <code>Animal</code> to  <code>Process</code> method. Before .NET 9,  we could only pass the derived classes: <code>Cat</code> and <code>Dog</code>.</p>
<pre><code class="language-csharp">/*** My Base Class is Animal ***/
[JsonPolymorphic]
[JsonDerivedType(typeof(Cat), nameof(Cat))]
[JsonDerivedType(typeof(Dog), nameof(Dog))]
private class Animal
{
    public string Name { get; set; }
}

/*** CAT derived from Animal ***/
private class Cat : Animal
{
    public CatTypes CatType  { get; set; }
}

/*** DOG derived from Animal ***/
private class Dog : Animal
{
    public DogTypes DogType { get; set; }
}


public class MyHub : Hub
{
    /*** We can use the base type Animal here  ***/
    public void Process(Animal animal)
    {
        if (animal is Cat) { ... }
        else if (animal is Dog) { ... }
    }
}

</code></pre>
<h3>Better Diagnostics and Telemetry</h3>
<p>Microsoft focuses mainly on .NET Aspire nowadays. That’s why SignalR now integrates more deeply with the .NET Activity API, which is commonly used for distributed tracing. The enhancement is implemented for better monitoring in <a href="https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals/dashboard/overview?tabs=bash#using-the-dashboard-with-net-aspire-projects">.NET Aspire Dashboard</a>. To support this feature:</p>
<p>1- Add these packages to your<code>csproj</code>:</p>
<pre><code class="language-xml">&lt;PackageReference Include=&quot;OpenTelemetry.Exporter.OpenTelemetryProtocol&quot; Version=&quot;1.9.0&quot; /&gt;
&lt;PackageReference Include=&quot;OpenTelemetry.Extensions.Hosting&quot; Version=&quot;1.9.0&quot; /&gt;
&lt;PackageReference Include=&quot;OpenTelemetry.Instrumentation.AspNetCore&quot; Version=&quot;1.9.0&quot; /&gt;
</code></pre>
<p>2- Add the following startup code to your host project:</p>
<pre><code class="language-csharp">builder.Services.AddSignalR();
/* After AddSignalR use AddOpenTelemetry() */
builder
    .Services
    .AddOpenTelemetry()
    .WithTracing(tracing =&gt;
    {
        if (builder.Environment.IsDevelopment())
        {         
            tracing.SetSampler(new AlwaysOnSampler()); //for dev env monitor all traces
        }

        tracing.AddAspNetCoreInstrumentation();
        tracing.AddSource(&quot;Microsoft.AspNetCore.SignalR.Server&quot;);
    });

builder.Services.ConfigureOpenTelemetryTracerProvider(tracing =&gt; tracing.AddOtlpExporter());
</code></pre>
<p>Finally, you’ll see the <strong>SignalR Hub</strong> events on the <a href="https://learn.microsoft.com/en-us/dotnet/aspire/fundamentals/dashboard/overview">Aspire Dashboard</a>:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-10-01-SignalR-9-New-Features/signalr-activity-dashboard.png" alt=".NET Aspire Activity Dashboard" /></p>
<h3>Trimming and Native AOT Support</h3>
<p>With .NET 9, <strong>trimming</strong> and <strong>native</strong> <strong>Ahead Of Time</strong> compilation are <strong>supported</strong>. This will improve our application performance. To support AOT, your SignalR object serialization needs to be JSON, and you must use the <code>System.Text.Json</code> s<a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation">ource generator</a>. Also on the server side, <a href="https://github.com/dotnet/aspnetcore/issues/56179">you shouldn't use</a> <code>IAsyncEnumerable&lt;T&gt;</code> and <code>ChannelReader&lt;T&gt;</code> where <code>T</code> is a ValueType (<code>struct</code>) for  Hub method arguments. One more limitation; <a href="https://learn.microsoft.com/en-us/aspnet/core/signalr/hubs?view=aspnetcore-8.0#strongly-typed-hubs">Strongly typed hubs</a> aren't supported with Native AOT (<code>PublishAot</code>).  And you should use only <code>Task</code>, <code>Task&lt;T&gt;</code>, <code>ValueTask</code>, <code>ValueTask&lt;T&gt;</code> for <code>async</code> return types.</p>
<hr />
<p>That's all the new features coming to SignalR in .NET 9!
Happy coding 🧑🏽‍💻</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a1563a5-4b03-9695-4824-bfa058eb02b1" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a1563a5-4b03-9695-4824-bfa058eb02b1" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/difference-between-promise-and-observable-in-angular-bxv97pkc</guid>
      <link>https://abp.io/community/posts/difference-between-promise-and-observable-in-angular-bxv97pkc</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>angular</category>
      <category>typescript</category>
      <title>Difference Between "Promise" and "Observable" in Angular</title>
      <description>The "Promise" and "Observable" are similar in handling async operations but have different use cases and behaviors. In this article, we'll see the six differences between them.</description>
      <pubDate>Tue, 24 Sep 2024 08:49:32 Z</pubDate>
      <a10:updated>2026-03-02T16:07:50Z</a10:updated>
      <content:encoded><![CDATA[<h1>Difference Between &quot;Promise&quot; and &quot;Observable&quot; in Angular</h1>
<p>In this article, I will mention the differences between <code>Promise</code> and <code>Observable</code> . They are used in TypeScript (Angular) for handling async operations but have different use cases and behaviors. Let's see these six differences...</p>
<h2>1. Eager or Lazy Evaluation</h2>
<ul>
<li><p><strong>Promise</strong>: A <code>promise</code> is <strong>eager</strong>! This means that as soon as a  <code>promise</code> is created, it executes the operation, like initiating immediately an HTTP request. <strong>You can't control the execution start time; it begins right away!</strong></p>
</li>
<li><p><strong>Observable:</strong> An <code>observable</code> is a <strong>lazy</strong> operation! It doesn't start executing until you subscribe to it. This allows you to define an <code>observable</code> without triggering the actual operation until it's needed.</p>
</li>
</ul>
<h2>2. Handling Value Count</h2>
<ul>
<li><p><strong>Promise:</strong> A <code>promise</code> is designed to <strong>handle a single async value</strong>. Once the operation completes, it either resolves with a value or rejects with an error, and that's it! You can't emit multiple values with a single <code>promise</code>.</p>
</li>
<li><p><strong>Observable:</strong> An <code>observable</code> <strong>can emit multiple values</strong> over time. It can have several values, and it can continue to do so until it either completes or errors out. So <code>observable</code> is ideal for event streams or data streams.</p>
</li>
</ul>
<h2>3. Cancellablity</h2>
<ul>
<li><p><strong>Promise:</strong> Once a <code>promise</code> is created and the operation has started**, you cannot cancel it!** The <code>promise</code> will resolve or reject eventually, and   there's no way to stop it from being executed.</p>
</li>
<li><p><strong>Observable:</strong> An <code>observable</code> <strong>can be canceled</strong>. If you unsubscribe from an <code>observable</code>, it stops emitting values and can clean up any resources like canceling an ongoing HTTP request. This makes <code>observable</code> more flexible in scenarios where you need to abort an operation.</p>
</li>
</ul>
<h2>4. Chaining and Composition</h2>
<ul>
<li><p><strong>Promise:</strong> It <strong>supports chaining</strong> using <code>.then()</code> for handling the result and <code>.catch()</code> for handling errors. This is straightforward but can become complex for more advanced scenarios.</p>
</li>
<li><p><strong>Observable:</strong> It <strong>supports powerful operators</strong> like <code>map</code>, <code>filter</code>, <code>merge</code>, <code>switchMap</code>. This allows for complex composition and transformation of data streams and makes it suitable for handling complex async scenarios.</p>
</li>
</ul>
<h2>5. Error Handling:</h2>
<ul>
<li><p><strong>Promise:</strong> Error handling in <code>promise</code> is done usually using <code>.catch()</code>. However, <strong>if an error occurs</strong>, the <code>promise</code> will reject, and <strong>the chain will stop</strong>.</p>
</li>
<li><p><strong>Observable:</strong> It has more <strong>robust error-handling mechanisms</strong>. You can handle errors using operators like <code>catchError</code> and decide whether to recover, continue or retry the process. It can also be completed successfully after an error is handled.</p>
</li>
</ul>
<h2>6. Built-In or RxJS</h2>
<ul>
<li><strong>Promise:</strong> It’s a <strong>built-in feature of JavaScript</strong> and a part of the ECMAScript. Almost all <strong>browsers support it</strong>.</li>
<li><strong>Observable:</strong> It’s <strong>not a built-in feature of JavaScript</strong>. In Angular, it’s provided by the <code>RxJS</code> library.</li>
</ul>
<hr />
<h2>Use Cases</h2>
<p><strong>Promise:</strong></p>
<ul>
<li>Simple async operations that return a single result, like fetching data from a Web API.</li>
<li>Scenarios where you don’t need to cancel the operation.</li>
<li>Handling a single event or action.</li>
</ul>
<p><strong>Observable:</strong></p>
<ul>
<li>Operations that might emit multiple values over time, such as <code>WebSocket</code> connections, user input events, or real-time data streams.</li>
<li>When you need the ability to cancel the operation.</li>
<li>Complex async flows require composition, transformation, or error handling.</li>
</ul>
<hr />
<h2>Examples</h2>
<h3>Promise Example</h3>
<pre><code class="language-javascript">const myPromise = new Promise((resolve, reject) =&gt; {
  setTimeout(() =&gt; {
    resolve('Promise is resolved!');
  }, 1000);
});

myPromise.then(value =&gt; console.log(value)).catch(error =&gt; console.error(error));
</code></pre>
<h3>Observable Example</h3>
<pre><code class="language-javascript">import { Observable } from 'rxjs';

const myObservable = new Observable(observer =&gt; {
  setTimeout(() =&gt; {
    observer.next('Value-1 retrieved!');
    observer.next('Value-2 retrieved!');
    observer.complete(); // No more values after this
  }, 1000);
});

const subscription = myObservable.subscribe({
  next: value =&gt; console.log(value),
  error: error =&gt; console.error(error),
  complete: () =&gt; console.log('Observable finished!')
});

/* 
  You can unsubscribe to cancel the observable as below:
  subscription.unsubscribe();
*/
</code></pre>
<h2>Summary</h2>
<ul>
<li><strong>A promise</strong> is simple and suitable for operations that return a single value or need to handle a single event. It’s eager and can’t be canceled.</li>
<li><strong>An observable</strong> is more flexible, especially for handling multiple values over time, allowing for complex data manipulation, and providing the ability to cancel operations. It supports lazy operations via <code>RxJS</code>.</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a153565-8d85-72bf-e104-66d37bd1401b" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a153565-8d85-72bf-e104-66d37bd1401b" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/asp.net-core-blazor-9.0-new-features-summary--x0fovych</guid>
      <link>https://abp.io/community/posts/asp.net-core-blazor-9.0-new-features-summary--x0fovych</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>dotnet</category>
      <category>blazor</category>
      <title>ASP.NET Core Blazor 9.0 New Features Summary 🆕</title>
      <description>.NET 9 in front of the door! With this new version, Blazor has some great new features; let's take a look at a summary of them.</description>
      <pubDate>Fri, 20 Sep 2024 15:45:57 Z</pubDate>
      <a10:updated>2026-03-02T13:23:41Z</a10:updated>
      <content:encoded><![CDATA[<h1>ASP.NET Core Blazor 9.0 New Features Summary 🆕</h1>
<p>In this article, I'll highlight .NET 9's Blazor updates and important features for ASP.NET Core 9.0. These features are based on the latest .NET 9 Preview 7.</p>
<h2>.NET MAUI Blazor Hybrid App and Web App solution template</h2>
<p>There's a new solution template to create .<strong>NET MAUI native</strong> and <strong>Blazor web client</strong> apps. This new template allows to choose a Blazor interactive render mode, it uses a shared Razor class library to maintain the UI's Razor components.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/hybrid/tutorials/maui-blazor-web-app?view=aspnetcore-9.0">learn.microsoft.com &gt; maui blazor web app tutorial</a></li>
<li><a href="https://www.reddit.com/r/Blazor/comments/1dabyzk/net_8_blazor_hybrid_maui_app_web_hosting/">reddit.com/r/Blazor/comments/1dabyzk/net_8_blazor_hybrid_maui_app_web_hosting/</a></li>
</ul>
<h2>A new middleware: <code>MapStaticAssets</code></h2>
<p>This new middleware optimizes the delivery of static assets in any ASP.NET Core app, also for Blazor. Basically it compresses assets via <a href="https://datatracker.ietf.org/doc/html/rfc1952">Gzip</a>, <a href="https://developer.mozilla.org/docs/Glossary/Fingerprinting">fingerprints</a> for all assets at build time with a Base64 and removes caches when Visual Studio Hot Reload (development time) is in action.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/release-notes/aspnetcore-9.0?view=aspnetcore-8.0#optimizing-static-web-asset-delivery">learn.microsoft.com &gt; optimizing static web assets</a></li>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/static-files?view=aspnetcore-9.0#static-asset-middleware">learn.microsoft.com &gt; fundamentals of static files</a></li>
</ul>
<h2>Simplifying the process of querying component states at runtime</h2>
<ol>
<li>Finding the component's current execution location: This can be especially helpful for component performance optimization and debugging.</li>
<li>Verifying whether the component is operating in a dynamic environment by checking: This can be useful for parts whose actions vary according to how their surroundings interact.</li>
<li>Obtaining the render mode allocated to the component: Comprehending the render mode can aid in enhancing the rendering procedure and augmenting the component's general efficiency.</li>
</ol>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-9.0#detect-rendering-location-interactivity-and-assigned-render-mode-at-runtime">learn.microsoft.com &gt; detect rendering location interactivity &amp; render mode runtime</a></li>
</ul>
<h2>Detecting component's location, interactivity support and render mode</h2>
<p>The <code>ComponentBase.RendererInfo</code> and <code>ComponentBase.AssignedRenderMode</code>  now allows to detect the following actions:</p>
<ul>
<li><code>RendererInfo.Name</code> returns the location where the component is executing</li>
<li><code>RendererInfo.IsInteractive</code> indicates if the component supports interactivity at the time of rendering.</li>
<li><code>ComponentBase.AssignedRenderMode</code> exposes the component's assigned render mode</li>
</ul>
<h2>Better server-side reconnection</h2>
<ul>
<li><p>When the previous app is disconnected and the user navigates to this app, or browser put this app in sleep mode, Blazor runs reconnection mechanism.</p>
</li>
<li><p>When reconnection is not successful because your server killed connection, it automatically makes a full page refresh.</p>
</li>
<li><p>With the new below config, you can adjust your reconnection retry time:</p>
<ul>
<li>
<pre><code class="language-csharp">Blazor.start({
  circuit: {
    reconnectionOptions: {
      retryIntervalMilliseconds: (previousAttempts, maxRetries) =&gt; 
        previousAttempts &gt;= maxRetries ? null : previousAttempts * 1000
    },
  },
});
</code></pre>
</li>
</ul>
</li>
</ul>
<h2>Simple serialization for authentication</h2>
<p>The new APIs in ASP.NET make it easier to add authentication to existing Blazor Web Apps. These APIs, now part of the Blazor Web App project template, allow authentication state to be serialized on the server and deserialized in the browser, simplifying the process of integrating authentication. This removes the need for developers to manually implement or copy complex code, especially when using WebAssembly-based interactivity.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/?view=aspnetcore-9.0#blazor-identity-ui-individual-accounts">learn.microsoft.com &gt; blazor Identity UI individual accounts</a></li>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/?view=aspnetcore-9.0#manage-authentication-state-in-blazor-web-apps">learn.microsoft.com &gt; manage authentication state</a></li>
</ul>
<h2>Easily add static server-side rendering pages</h2>
<p>With .NET 9, adding static server-side rendering (SSR) pages to globally interactive Blazor Web Apps has become simpler. The new <code>[ExcludeFromInteractiveRouting]</code> attribute allows developers to mark specific Razor component pages that require static SSR, such as those relying on HTTP cookies and the request/response cycle. Pages annotated with this attribute exit interactive routing and trigger a full-page reload, while non-annotated pages default to interactive rendering modes like <code>InteractiveServer</code>. This approach enables flexibility between static and interactive rendering depending on the page's requirements.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-9.0#static-ssr-pages-in-a-globally-interactive-app">learn.microsoft.com &gt; render-modes</a></li>
</ul>
<h2>Constructor Injection in Razor Components</h2>
<p>Razor components support constructor injection, allowing services like <code>NavigationManager</code> to be injected directly into a component's constructor. This can be used to manage navigation actions, such as redirecting the user upon an event like a button click.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/dependency-injection?view=aspnetcore-9.0#request-a-service-in-a-component">learn.microsoft.com&gt; dependency-injection</a></li>
</ul>
<h2>Configuring WebSocket Compression and Frame-Ancestors CSP in Interactive Server Components</h2>
<p>By default, Interactive Server components enable WebSocket compression and set a <code>frame-ancestors</code> Content Security Policy (CSP) to <code>self</code>, restricting embedding the app in <code>&lt;iframe&gt;</code>. Besides, compression can be disabled to improve security by setting <code>ConfigureWebSocketOptions</code> to null, though this may reduce performance. To prevent embedding the app in any <code>iframe</code> while maintaining WebSocket compression, set the <code>ContentSecurityFrameAncestorsPolicy</code> to 'none'.</p>
<p>For more info:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-9.0#websocket-compression-for-interactive-server-components">learn.microsoft.com &gt; websocket compression</a></li>
<li><a href="https://learn.microsoft.com/en-us/aspnet/core/blazor/security/server/interactive-server-side-rendering?view=aspnetcore-9.0#interactive-server-components-with-websocket-compression-enabled">learn.microsoft.com &gt; interactive server-side rendering when compression enabled</a></li>
</ul>
<h2>Tracking Composition State with <code>KeyboardEventArgs.IsComposing</code></h2>
<p>The new <code>KeyboardEventArgs.IsComposing</code> property indicates whether a keyboard event is part of a composition session, which is essential for properly handling international character input methods.</p>
<h2>Configuring Row Overscan in <code>QuickGrid</code> with new <code>OverscanCount</code> parameter</h2>
<p>The <code>QuickGrid</code> component now includes an <code>OverscanCount</code> property, which controls how many extra rows are rendered before and after the visible area when virtualization is enabled. By default, <code>OverscanCount</code> is set to <strong>3</strong>, but it can be adjusted as below to <strong>5</strong>.</p>
<pre><code class="language-html">&lt;QuickGrid ItemsProvider=&quot;itemsProvider&quot; Virtualize=&quot;true&quot; OverscanCount=&quot;5&quot;&gt;...&lt;/QuickGrid&gt;
</code></pre>
<h2>Range Input Support in <code>InputNumber&lt;TValue&gt;</code> Component</h2>
<p>The <code>InputNumber&lt;TValue&gt;</code> component now supports the <code>type=&quot;range&quot;</code> <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range">attribute</a>, allowing for range inputs like sliders or dials. This feature supports model binding and form validation, offering a more interactive way to input numerical data compared to the traditional text box.</p>
<pre><code class="language-html">&lt;EditForm&gt;
     &lt;InputNumber @bind-Value=&quot;Model.ProductCount&quot; max=&quot;999&quot; min=&quot;1&quot; step=&quot;1&quot; type=&quot;range&quot; /&gt;
&lt;/EditForm&gt;

@code {
    public class MyModel
    {
        [Required, Range(minimum: 1, maximum: 999)]
        public int ProductCount { get; set; }
    }
}
</code></pre>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a152249-5da6-dfb8-fb80-b2f0ad61dcae" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a152249-5da6-dfb8-fb80-b2f0ad61dcae" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/do-you-really-need-multitenancy-hpwn44r3</guid>
      <link>https://abp.io/community/posts/do-you-really-need-multitenancy-hpwn44r3</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>multi-tenancy</category>
      <category>architecture</category>
      <title>Do You Really Need Multi-tenancy?</title>
      <description>The article discusses whether you need a multi-tenancy architecture. Answer my critical questions to decide if multi-tenancy suits your application or not!</description>
      <pubDate>Sat, 31 Aug 2024 21:28:27 Z</pubDate>
      <a10:updated>2026-03-02T17:14:39Z</a10:updated>
      <content:encoded><![CDATA[<h1>Do You Really Need Multi-tenancy?</h1>
<p>This article discusses whether you need a multi-tenancy architecture for your next project. Answer my critical questions to decide if multi-tenancy suits your application or not!</p>
<h2>What’s Multi-tenancy?</h2>
<p>It’s an architectural approach to building SaaS solutions. In this model, the hardware and software resources are shared between tenants, and application data is virtually or physically isolated between tenants. Here, <strong>the main goal is minimizing costs and maximizing customer count</strong>.</p>
<p><strong>An ideal multi-tenant application should be;</strong></p>
<ul>
<li>A multi-tenancy system should be designed to <strong>work seamlessly</strong> and make your application code <strong>multi-tenancy aware</strong> as much as possible.</li>
<li>When a customer wants to separate their database, it <strong>should also be deployable to on-premise</strong>.</li>
</ul>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/tenancy-schema.png" alt="Tenancy Schema" /></p>
<hr />
<h2>Multi-tenant Development is Hard - Reconsider!</h2>
<p><strong>Developing a multi-tenant application is harder</strong> compared to non-multi-tenant applications. You add <code>TenandId</code> to all your shared entities. And each time you make a query, you need to filter by <code>TenantId</code>. There is an increased risk of security breaches if one tenant's data is compromised.  Multi-tenancy can limit the extent of customization available to each tenant since they all operate on the same core infrastructure. Also, in a microservice environment, things get two times more complicated. So you should carefully consider if you need multi-tenancy or not. Sometimes, I got questions like;</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/questions.png" alt="Questions" /></p>
<p><strong>No! These are not multi-tenant applications.</strong> It just needs a simple filtering by your different branches/faculties/departments/holding sub-companies/ groups or whatever hierarchy is…
<strong>You are confusing &quot;grouping&quot; with &quot;resource sharing&quot;.</strong></p>
<hr />
<h2>Do I Really Need Multi-tenancy?</h2>
<p>Ask yourself the following questions if you cannot decide whether your app needs multi-tenancy or not;</p>
<ol>
<li>Can a user be shared among other tenants?</li>
<li>Any tenant needs to see other tenant's data?</li>
<li>Does your application break when you physically move one of the tenants?</li>
<li>Do your customers need higher security and better GDPR enforcement?</li>
<li>Do you need cumulative queries over your tenants?</li>
</ol>
<p>Let's answer these questions;</p>
<h5><strong>1. Can a user be shared among other tenants?</strong></h5>
<p>If you need to <em>share a user among other tenants, or in other words, users can be members of different tenants,</em> then <strong>your application is definitely not multi-tenant</strong>! Multi-tenancy means a tenant’s data is always isolated, even if it’s logically separated. <strong>You cannot share a user among your tenants.</strong> The reason is simple: In the future, if you move a tenant to on-premise, then your application will break!</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/user-multiple-membership.png" alt="user-multiple-membership" /></p>
<h5><strong>2. Does any tenant need to see other tenants' data?</strong></h5>
<p>If your answer is <strong>YES</strong>, <strong>then</strong> <strong>your application is not multi-tenant</strong>. In multi-tenant apps, the tenant's data cannot be shared in any circumstances among the other tenants. Business decision-makers sometimes want to share some entities with other tenants. If there's this requirement, you shouldn't start a multi-tenant architecture. You can simply group these tenants manually. Again, reply to this question; <strong>In the future, if I move a tenant physically to another environment, will my app still work properly?</strong> In this case, it will not!</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/shared-entity.png" alt="Shared entity" /></p>
<p>Let's say your app is <em>Amazon.com</em> and you have a product entity <em>iPhone</em> that you want to share with other sellers. This requirement violates the multi-tenant rule. While your <em>Amazon.com</em> is still SaaS, it shouldn't be multi-tenant.</p>
<p>On the other hand, if you serve several online shopping websites dedicated to different brands. Let's say Nike and Adidas want to have their own e-commerce websites. And your <strong><em>Amazon.com</em> provides these companies with their own subdomains: <em>nike.amazon.com</em> and <em>adidas.amazon.com</em></strong>. In this architecture, these companies will have their own user, roles, settings. Also these companies will have their own branding like custom login screen, custom logo, different theme layouts, menu items,  language options, payment gateways etc... Hence, <strong>this is %100 multi-tenant.</strong></p>
<h5><strong>3. Does your application break when you physically move one of the tenants?</strong></h5>
<p>If your answer is <strong>YES</strong>, you should <strong>stop making it multi-tenant</strong>. It is <strong>not a multi-tenant app</strong>! This means your tenants are tightly coupled with the application's infrastructure or database, and this requirement prevents you from making it multi-tenant because it disrupts the entire system when you take out a tenant.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/coupled-tenants.png" alt="Coupled Tenants" /></p>
<h5><strong>4. Do your customers need higher security and better GDPR enforcement?</strong></h5>
<p>If your answer is <strong>YES</strong>, you <strong>should not make it multi-tenancy.</strong>  When a <strong>hacker</strong> gets into your server, he can <strong>steal all your client data</strong>. Also, if you have a security hole, <strong>a tenant can gain access</strong> to other tenants' data. Especially your tenants' data is being shared in the same database... On the other hand, some customers, for example, government agencies or banks, may be required to locate the database in their own geo-location and make it unreachable from the main application. In this case, you should go with a single-tenant architecture. Another difficulty is that some tenants may have <strong>different data retention policies</strong>, so you must implement different strategies for each tenant. In this case, you should also consider making it a single-tenant.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2024-09-01-Do-You-Need-MultiTenancy/security-gdpr-db-retention.png" alt="Security GDPR Data Retention" /></p>
<h5><strong>5. Do you need cumulative queries over your tenants?</strong></h5>
<p>This question is not a clear decision parameter for multi-tenancy. But it can be a supportive parameter for your decision. Actually, this is a common feature in multi-tenant systems where aggregated reporting or analytics across tenants is required. In a virtually isolated multi-tenant environment, you can easily do this by just disabling the multi-tenancy filter. However, when some of your tenants have separate databases or application instances, it becomes harder to get aggregate reports.</p>
<p>Do you need cumulative queries over your tenants? If your answer is YES, then you should keep all your tenants' data in a shared database to easily query them. But if you still need to physically move some of the tenants, then you have the following strategies:</p>
<ul>
<li>First, all your databases need to be on the same network so that you can gather data from different databases.</li>
<li>Second, in some cases, according to the GDPR requirements or government agency regulations, you must locate the database in their geo-location. And you cannot connect to these databases. In this case, you can create a Web API in your application that gives you a report for this specific tenant. Later, you'll gather the reports from all your tenants like this and merge them.</li>
<li>Third; When the tenant databases are in different geo-location (inaccessible), then each tenant can send their report to your central server. So you can generate cumulative reports.</li>
</ul>
<h2>Conclusion</h2>
<ul>
<li><p>It's important to decide on the first day whether your application needs to be multi-tenant. To decide this, consider these topics;</p>
<ul>
<li><strong>Do my tenants really have a relationship with each other?</strong> No, they have nothing to do in common; <strong>OK, go with multi-tenancy</strong>.</li>
<li><strong>My tenants don't have a relationship</strong> with each other, and the only thing they have in common is sharing my application. <strong>OK, go with multi-tenancy</strong>.</li>
<li><strong>When a tenant leaves the system (by removing their data), the other tenants also stop working</strong> This means that the tenants are coupled. <strong>Do not do multi-tenancy!</strong></li>
</ul>
</li>
</ul>
<hr />
<p><img src="https://abp.io/assets/platform/img/logos/logo-abp-dark.svg" alt="Logo" /> </p>
<p>We’ve been working for a long time on multi-tenancy, microservices, modular development topics, and developing tools and frameworks for repetitive development tasks. Check out the amazing open-source <a href="https://github.com/abpframework/abp">ABP Framework</a>, which provides all the alternative solutions to implement a multi-tenant architecture. The multi-tenancy logic is seamlessly done at the core level, and you can simply focus on your business code. Keep it simple, nice and neat with ABP.</p>
<pre><code class="language-bash">ABP.IO: The Modern Way of Developing Web Apps for .NET Developers!
</code></pre>
<p>Alper Ebicoglu / <a href="https://x.com/alperebicoglu">x.com/alperebicoglu</a></p>
<p>— ABP Team</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a14bc83-bfdc-e8af-b510-dc2fe6694e48" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a14bc83-bfdc-e8af-b510-dc2fe6694e48" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/what-is-angular-schematics-2z4jusf5</guid>
      <link>https://abp.io/community/posts/what-is-angular-schematics-2z4jusf5</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>angular</category>
      <title>What is Angular Schematics?</title>
      <description>Angular Schematics is a tool within Angular CLI that automates code generation and modification, streamlining development and enhancing project consistency.</description>
      <pubDate>Thu, 29 Aug 2024 09:29:58 Z</pubDate>
      <a10:updated>2026-03-02T10:45:13Z</a10:updated>
      <content:encoded><![CDATA[<h1>What is Angular Schematics?</h1>
<p><strong>Angular Schematics</strong> is a powerful tool which is part of the Angular CLI that allows developers to automate various development tasks by <strong>generating and modifying code</strong>. Schematics provides a way to create <strong>templates and boilerplate code</strong> for Angular applications or libraries, enabling consistency and reducing the amount of repetitive work.</p>
<h3>Key Concepts of Angular Schematics:</h3>
<ol>
<li><p><strong>Code Generation:</strong></p>
<ul>
<li>Schematics can generate boilerplate code for various Angular artifacts, such as components, services, modules, pipes... For example, when you run a command like <code>ng generate component my-component</code>, Angular uses a schematic to create the component files and update the necessary modules.</li>
</ul>
</li>
<li><p><strong>Code Modification:</strong></p>
<ul>
<li>Schematics can also modify existing code in your project. This includes tasks like updating configuration files, adding new routes, or modifying Angular modules. They can be very useful when upgrading projects to a new version of Angular or adding new features that require changes to the existing codebase.</li>
</ul>
</li>
<li><p><strong>Custom Schematics:</strong></p>
<ul>
<li>Developers can create their own custom schematics to automate repetitive tasks specific to their projects. For example, if your team frequently needs to set up a certain type of service or configure specific libraries, you can create a schematic that automates these steps. In <a href="https://abp.io/suite">ABP Suite</a>, we use the custom schematics templates to generate CRUD pages for Angular UI.</li>
</ul>
</li>
<li><p><strong>Collection of Schematics:</strong></p>
<ul>
<li>Schematics are often grouped into collections. The Angular CLI itself is a collection of schematics. You can create your own collection or use third-party schematic collections created by the Angular community.</li>
</ul>
</li>
<li><p><strong>Integration with Angular CLI:</strong></p>
<ul>
<li>Schematics is integrated with the Angular CLI. The <code>ng generate</code> and <code>ng add</code> commands are examples of how schematics are used in everyday Angular development. When you use these commands, the Angular CLI runs the corresponding schematic to perform the desired operation.</li>
</ul>
</li>
<li><p><strong>Upgrade Tasks:</strong></p>
<ul>
<li>Schematics can be used to automate the process of upgrading Angular applications. For example, the Angular Update command (<code>ng update</code>) uses schematics to automatically apply necessary changes to your project when upgrading to a new version of Angular.</li>
</ul>
</li>
</ol>
<h3>Common Use Cases:</h3>
<ul>
<li><p><strong>Generating Components, Services, Modules.:</strong> Easily create Angular building blocks with commands like <code>ng generate component</code>, <code>ng generate service</code>, or <code>ng generate module</code>.</p>
</li>
<li><p><strong>Adding Libraries:</strong> Automatically set up and configure third-party libraries with <code>ng add</code>. For example, <code>ng add @angular/material</code> uses a schematic to install and configure Angular Material in your project.</p>
</li>
<li><p><strong>Automating Project Upgrades:</strong> Simplify the process of upgrading Angular versions by running <code>ng update</code>, which uses schematics to make necessary code changes.</p>
</li>
<li><p><strong>Custom Project Scaffolding:</strong> Create custom schematics to enforce your team's development standards and best practices by automating the creation of specific project structures.</p>
</li>
</ul>
<h3>How to Create a Custom Schematic:</h3>
<p>Creating a custom schematic involves several steps:</p>
<ol>
<li><p><strong>Install the Schematics CLI:</strong></p>
<pre><code class="language-bash">npm install -g @angular-devkit/schematics-cli
</code></pre>
</li>
<li><p><strong>Create a New Schematic Project:</strong></p>
<pre><code class="language-bash">schematics blank --name=my-schematic
cd my-schematic
</code></pre>
</li>
<li><p><strong>Define Your Schematic:</strong> Modify the files in the schematic project to define what your schematic will generate or modify.</p>
</li>
<li><p><strong>Test Your Schematic:</strong> You can run your schematic locally using the <code>schematics</code> command.</p>
</li>
<li><p><strong>Publish Your Schematic (Optional):</strong> Once your schematic is ready, you can publish it to npm or include it in your Angular projects.</p>
</li>
</ol>
<h4>Example:</h4>
<p>If you want to create a custom component with specific settings or styles, you can create a schematic to automate this. Every time a developer on your team needs to create this type of component, they can run the schematic, ensuring consistency across the project.</p>
<h3>Helpful Links</h3>
<p>Here are the direct links for the Angular Schematics resources:</p>
<ul>
<li><p><a href="https://angular.io/guide/schematics">Angular Official Documentation: Schematics Overview — angular.io</a></p>
</li>
<li><p><a href="https://angular.io/guide/schematics-for-libraries">Creating Custom Schematics — angular.io</a></p>
</li>
<li><p><a href="https://angular.io/cli/schematic">CLI Schematic Command — angular.io</a></p>
</li>
<li><p><a href="https://github.com/angular/angular-cli/tree/main/packages/angular_devkit/schematics">Devkit Schematics— github.com</a></p>
</li>
<li><p><a href="https://github.com/angular/angular-cli/tree/main/packages/schematics/angular">Schematics Examples — github.com</a></p>
</li>
<li><p><a href="https://dev.to/nikolasleblanc/debugging-angular-schematics-1ne0">Debugging Angular Schematics — dev.to</a></p>
</li>
<li><p><a href="https://nx.dev/guides/using-angular-schematics">Using Schematics with Nx — nx.dev</a></p>
</li>
<li><p><a href="https://angular.io/api/schematics">Schematics API — angular.io</a></p>
</li>
</ul>
<h3>Conclusion:</h3>
<p>Angular Schematics is a powerful tool for automating repetitive tasks, generating consistent code, and managing project upgrades. By leveraging schematics, Angular developers can save time, reduce errors, and enforce best practices across their projects.</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a14afa5-3a3d-4341-27e3-49cf7053f309" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a14afa5-3a3d-4341-27e3-49cf7053f309" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/understanding-angular-aot-vs-jit-compilations-0r0a0a3f</guid>
      <link>https://abp.io/community/posts/understanding-angular-aot-vs-jit-compilations-0r0a0a3f</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>angular</category>
      <title>Understanding Angular AOT vs JIT Compilations</title>
      <description>This article compares Angular's Ahead-of-Time (AOT) and Just-in-Time (JIT) compilations, detailing their benefits and when to use each. AOT is best for production, while JIT suits development.</description>
      <pubDate>Wed, 28 Aug 2024 12:10:36 Z</pubDate>
      <a10:updated>2026-03-02T18:02:20Z</a10:updated>
      <content:encoded><![CDATA[<p>Ahead-of-Time (AOT) compilation and Just-in-Time (JIT) compilation are two different methods for compiling Angular applications. Here's a breakdown of the differences between them:</p>
<h3><strong>Ahead-of-Time (AOT) Compilation</strong></h3>
<p><strong>What is AOT?</strong></p>
<ul>
<li>AOT compilation refers to the process of compiling your Angular application during the build phase, before the application is served to the browser.</li>
<li>The Angular compiler converts your TypeScript and HTML templates into efficient JavaScript code ahead of time.</li>
</ul>
<p><strong>Advantages:</strong></p>
<ol>
<li><strong>Faster Rendering:</strong> Since the compilation is done beforehand, the browser receives precompiled code, leading to faster rendering and better performance when the app loads.</li>
<li><strong>Smaller Bundle Size:</strong> AOT eliminates the need for the Angular compiler in the client-side bundle, which reduces the overall bundle size.</li>
<li><strong>Improved Security:</strong> AOT compilation checks your templates and bindings during the build process, catching errors early and reducing the risk of injection attacks.</li>
<li><strong>Early Error Detection:</strong> Errors related to templates and bindings are caught during the build time rather than at runtime, leading to more robust and error-free applications.</li>
</ol>
<p><strong>When to Use:</strong></p>
<ul>
<li>AOT is typically used in production builds because it provides better performance, smaller bundles, and more secure applications.</li>
</ul>
<p><strong>How to Use:</strong></p>
<ul>
<li>AOT is the default when you run <code>ng build --prod</code> in an Angular project.</li>
</ul>
<h3><strong>Just-in-Time (JIT) Compilation</strong></h3>
<p><strong>What is JIT?</strong></p>
<ul>
<li>JIT compilation occurs in the browser at runtime. The Angular compiler translates the TypeScript and HTML templates into JavaScript code just before the application runs in the browser.</li>
<li>The application is compiled on the fly as the user interacts with it.</li>
</ul>
<p><strong>Advantages:</strong></p>
<ol>
<li><strong>Faster Build Time:</strong> Since there’s no pre-compilation step, the build process is faster during development.</li>
<li><strong>More Flexible Development:</strong> JIT allows for rapid iteration during development, as changes can be quickly reflected without needing to rebuild the entire application.</li>
<li><strong>Dynamic Components:</strong> JIT allows for more flexibility in scenarios where components need to be dynamically created or compiled at runtime.</li>
</ol>
<p><strong>When to Use:</strong></p>
<ul>
<li>JIT is typically used in development environments because it allows for quicker build times and easier debugging.</li>
</ul>
<p><strong>How to Use:</strong></p>
<ul>
<li>JIT is the default compilation method when you run <code>ng serve</code> for development builds in Angular.</li>
</ul>
<h3><strong>Comparison Summary:</strong></h3>
<p>| Feature                | AOT (Ahead-of-Time)           | JIT (Just-in-Time)                 |
| ---------------------- | ----------------------------- | ---------------------------------- |
| <strong>Compilation Timing</strong> | At build time                 | At runtime                         |
| <strong>Performance</strong>        | Faster application startup    | Slower application startup         |
| <strong>Bundle Size</strong>        | Smaller (no Angular compiler) | Larger (includes Angular compiler) |
| <strong>Error Detection</strong>    | Catches template errors early | Errors caught at runtime           |
| <strong>Use Case</strong>           | Production                    | Development                        |
| <strong>Dynamic Components</strong> | Less flexible                 | More flexible                      |</p>
<h3><strong>Best Practices:</strong></h3>
<ul>
<li><strong>Use AOT</strong> for production builds to ensure faster load times, smaller bundle sizes, and more secure applications.</li>
<li><strong>Use JIT</strong> during development to take advantage of quicker builds and easier debugging.</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a14ab11-ee73-9ee9-ab6e-1c1f9c246c8a" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a14ab11-ee73-9ee9-ab6e-1c1f9c246c8a" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/the-new-abp-platform-is-live-0wl2y02d</guid>
      <link>https://abp.io/community/posts/the-new-abp-platform-is-live-0wl2y02d</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>abp-io</category>
      <title>The new ABP Platform is live!</title>
      <description>The new ABP Platform is live! We have unified all abp.io subdomains into abp.io. Docs in one place, easy navigation, modern design and ABP Studio Community Edition (free) is now available to everyone.</description>
      <pubDate>Wed, 24 Jul 2024 10:30:20 Z</pubDate>
      <a10:updated>2026-03-02T17:25:53Z</a10:updated>
      <content:encoded><![CDATA[<p>We're thrilled to announce that the <strong>new ABP.IO Platform is now live!</strong> Our team has been hard at unifying and enhancing the entire platform to deliver a seamless, user-friendly experience. Here's what's new:</p>
<h3>Unified domain and enhanced navigation 🌍</h3>
<p>All our services are now consolidated under a single domain; <a href="https://abp.io">abp.io</a>. This means you no longer need to navigate through multiple subdomains. The new mega menu makes finding what you need easier and faster.</p>
<h3>Modern design and improved UX 🎨</h3>
<p>The platform boasts a fresh, modern design aimed at improving both aesthetics and functionality. This redesign enhances usability, making your interaction with ABP.IO more intuitive.</p>
<h3>Documentation in one place 📃</h3>
<p>We’ve combined the ABP (open-source) and ABP Commercial (paid) documents into a single, comprehensive resource. This unified documentation will help you find what you're looking for more efficiently. The new documentation address is <a href="https://abp.io/docs">abp.io/docs</a>.  When you switch to old ABP versions before v8.3, you will see the old documents are still available.</p>
<h3>Introducing &quot;ABP Studio Community Edition&quot; 🪄</h3>
<p>We're excited to introduce the <strong>ABP Studio Community Edition</strong>, which is now <strong>available for free</strong>. This edition provides powerful tools to streamline your development process. You can easily create a new project with a configuration wizard in ABP Studio. It also provides module management, which means you can add/remove an ABP Module easily. You can also debug your microservice project and track the HTTP requests easily. Connecting your local development environment to a local or remote Kubernetes cluster is another cool feature of ABP Studio. We aim for ABP Studio to be the primary tool for ABP developers to manage their projects.</p>
<blockquote>
<p>Download ABP Studio 👉 <a href="https://abp.io/studio">abp.io/studio</a>.</p>
</blockquote>
<h3>Enhanced &quot;ABP CLI&quot; 🚀</h3>
<p>ABP CLI is also renewed. The new CLI is compatible with ABP Studio. It adds new commands. The new CLI is now available on NuGet at <a href="https://www.nuget.org/packages/Volo.Abp.Studio.Cli">nuget.org/packages/Volo.Abp.Studio.Cli</a>. It's a dotnet global tool. When you install ABP Studio, the new ABP CLI is automatically installed.  You can still use the old ABP CLI commands. To use the legacy ABP CLI commands just add <code>--old</code> parameter to your commands.</p>
<blockquote>
<p>The docs of the new ABP CLI 👉 <a href="https://abp.io/docs/latest/cli">abp.io/docs/latest/cli</a>.</p>
</blockquote>
<h3>20% Celebration discount 💰</h3>
<p>To celebrate the launch of the new platform, we're offering a <strong>20% discount</strong> for a limited time. This discount is valid for all new purchases, renewing existing licenses and buying additional developer seats.</p>
<blockquote>
<p>Discounted prices 👉 <a href="https://abp.io/pricing">abp.io/pricing</a>.</p>
</blockquote>
<h3>Existing customers 🛂</h3>
<p>In terms of licensing rules, existing customers will not be affected by this change. You can manage your license just like before at <a href="https://abp.io/my-organizations">abp.io/my-organizations</a>.</p>
<blockquote>
<p>The new support website address 👉 <a href="https://abp.io/support">abp.io/support</a>.</p>
</blockquote>
<hr />
<h3>Community Talk on the new ABP Platform</h3>
<p>We made a community talk on YouTube on August 1st, 2024,  and we explained these topics. You can watch it from the below link:</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/y5qXzdsxil0?si=gdiHSm6qAW0DmIb6" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
<hr />
<h3>Why choose the ABP Platform? 🙄</h3>
<p>ABP Platform simplifies modern software development with well-architected startup templates, modular design infrastructure, multi-tenancy support, comprehensive security features, and a vibrant community. If you are starting a new web project or transforming your legacy application, ABP is the perfect solution! If you still wonder why you need such a solution, see <a href="https://abp.io/why-choose-abp">abp.io/why-choose-abp</a>.</p>
<p>There are several startup ASP.NET Core templates for your requirements. Read <a href="https://abp.io/how-it-works">abp.io/how-it-works</a> page to understand ABP's approach. We have a FAQ page where you can find answers to many of your questions <a href="https://abp.io/faq">abp.io/faq</a>.</p>
<blockquote>
<p>Start your new ABP project -for free- 👉<a href="https://abp.io/get-started">abp.io/get-started</a>!</p>
</blockquote>
<h3>Join our community 👨‍👨‍👦</h3>
<p>We invite developers, IT professionals, and businesses to join the ABP Community. Our community website is now <a href="https://abp.io/community">abp.io/community</a>. On this website, you can read ABP-related posts, watch live community shows and core team's fundamental video courses...</p>
<hr />
<p>For more information, visit our newly unified platform at <a href="https://abp.io">abp.io</a>. We look forward to your feedback and continued support as we grow together!</p>
<blockquote>
<p>Found a bug in the new platform? Or if you have an idea, write to us 👉 <a href="https://abp.io/contact">abp.io/contact</a>.</p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a13f677-8fd5-da36-5d7d-754ecde1f1db" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a13f677-8fd5-da36-5d7d-754ecde1f1db" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/announcement-our-new-abp.io-unified-platform-ccs49kzq</guid>
      <link>https://abp.io/community/posts/announcement-our-new-abp.io-unified-platform-ccs49kzq</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <title>Announcement: Our New ABP.IO Unified Platform</title>
      <description>📢 We are unifying all our sub-domain services under a single platform address 👉 ABP.IO with a new user UI and behavior.</description>
      <pubDate>Sun, 31 Mar 2024 22:16:19 Z</pubDate>
      <a10:updated>2026-03-02T17:49:05Z</a10:updated>
      <content:encoded><![CDATA[<p>Hi ABP Community,</p>
<p>📢 We're excited to announce an improvement to your ABP.IO experience! In our ongoing effort to simplify and improve your interaction with our platform, we are working on a new design for ABP.IO and its subdomains. This update isn't just about aesthetics; it's a comprehensive enhancement aimed at unifying all our services under a single platform address: https://abp.io.</p>
<h2>Why are we making this change?</h2>
<p>Whether you're developing with our open-source framework or using our commercial product, or looking for support; our goal is always to deliver the best experience possible. The new design will improve several aspects:</p>
<p>🔹<strong>Simplifying Navigation</strong>: As the ABP.IO platform has grown rapidly, navigating through numerous subdomains has become challenging. We're transitioning to a well-structured mega menu system that will make navigation tidier and more straightforward. With everything under the ABP.IO domain, finding what you need will be easier.</p>
<p>🎨 <strong>Enhancing User Experience</strong>: We're introducing a fresh, modern design that not only looks better but also enhances functionality and ease of use.</p>
<p>🔎 <strong>Better SEO</strong>: A unified domain improves our platform's discoverability, making it easier for new users to find us and for you to share resources with your peers.</p>
<h2>Which services are being unified?</h2>
<p>✅ The following websites will now be unified under ABP.IO:</p>
<ul>
<li><p>blog.abp.io 👉 abp.io/blog</p>
</li>
<li><p>docs.abp.io 👉 abp.io/docs</p>
</li>
<li><p>support.abp.io 👉 abp.io/support</p>
</li>
<li><p>community.abp.io 👉 abp.io/community</p>
</li>
<li><p>commercial.abp.io 👉 abp.io</p>
</li>
</ul>
<blockquote>
<p>⛔ The following websites will not be unified during this transition:  admin.abp.io, account.abp.io, nuget.abp.io</p>
</blockquote>
<h2>What can you expect?</h2>
<p>The new ABP.IO platform is designed with you in mind. Here’s what to look forward to:</p>
<ul>
<li><p><strong>Seamless Integration</strong>: Transitioning from multiple subdomains to a single address without losing track of your favorite resources. We will keep many pages the same as before. Page-based transitions will be made over a longer period of time.</p>
</li>
<li><p><strong>Improved Support and Documentation</strong>: We will merge commercial and open-source docs into a single address so it'll be easier to access our documentation.</p>
</li>
</ul>
<h2>Your journey with us during this transition</h2>
<p>We know that change is overwhelming, but we are trying to provide a smooth transition. Here's how we're making it seamless for you:</p>
<p>🚩 <strong>No Immediate Action Required</strong>: Your existing bookmarks and links will continue to work, automatically redirecting you to the new unified platform.</p>
<p>🎗 <strong>Stay Informed</strong>: We will keep you updated with guides and support during the transition.</p>
<p>📧 <strong>We’re Here to Help</strong>: Our support team is ready to assist you with any questions or concerns.  If you have any issues, you can contact us at our Discord channel or send an email to info@abp.io.</p>
<h2>Looking Ahead</h2>
<p>This upgrade is another milestone in our journey together. Thank you for your support and feedback, which have been instrumental in making this transition possible. Stay tuned for more updates, and here's to a new chapter together at ABP.IO!</p>
<p>Happy coding 🫡</p>
<p>ABP.IO Team</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a11a8c2-936a-b039-47e7-8d9980deaebc" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a11a8c2-936a-b039-47e7-8d9980deaebc" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-supports-.net8-e4gve6ih</guid>
      <link>https://abp.io/community/posts/abp-supports-.net8-e4gve6ih</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>feature</category>
      <category>new-version</category>
      <title>ABP Supports .NET8</title>
      <description>This article is about the new .NET 8 support with ABP v8. Also, I summarized the new features of .NET 8.</description>
      <pubDate>Mon, 15 Jan 2024 16:33:01 Z</pubDate>
      <a10:updated>2026-03-02T17:31:33Z</a10:updated>
      <content:encoded><![CDATA[<h1>ABP Now Supports .NET 8</h1>
<p>Recently we have published ABP v8.0. With this version <a href="https://github.com/abpframework/abp/blob/dev/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyCompanyName.MyProjectName.Web.csproj#L6">the ABP Framework</a> and ABP Commercial both supports for .NET 8, aligning itself with the latest enhancements and new features of the ASP.NET's new version 8.</p>
<p>Here's the <a href="https://commercial.abp.io/releases/pr/15676">related PR</a> for this upgrade. This update ensures that developers using ABP can leverage the new features and improvements of .NET 8, enhancing the capability and performance of their applications. With .NET 8 support, ABP 8.0 likely offers improved performance, enhanced security, and greater efficiency, making it a robust choice for building modern web applications.
Here's the summary of .NET 8 features and enhancements:</p>
<h2>What's new in .NET 8</h2>
<h3>.NET Aspire</h3>
<p><a href="https://learn.microsoft.com/en-us/dotnet/aspire/">.NET Aspire</a> is a tool to observe and manage distributed web applications. It's still preview version. You can manage your containers, executables, logs, traces and metrics of your running web application. For more information see this article https://devblogs.microsoft.com/dotnet/introducing-dotnet-aspire-simplifying-cloud-native-development-with-dotnet-8/</p>
<h3>Serialization</h3>
<p>12 features have been implemented for <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json">System.Text.Json</a> serialization and deserialization library with .NET 8.  See these enhancements</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#built-in-support-for-additional-types">Built-in support for additional types</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#source-generator">Source generator</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#interface-hierarchies">Interface hierarchies</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#naming-policies">Naming policies</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#read-only-properties">Read-only properties</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#disable-reflection-based-default">Disable reflection-based default</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#new-jsonnode-api-methods">New JsonNode API methods</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#non-public-members">Non-public members</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#streaming-deserialization-apis">Streaming deserialization APIs</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#withaddedmodifier-extension-method">WithAddedModifier extension method</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#new-jsoncontentcreate-overloads">New JsonContent.Create overloads</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#freeze-a-jsonserializeroptions-instance">Freeze a JsonSerializerOptions instance</a></li>
</ul>
<h3>Time abstraction</h3>
<p>You may mock time in test scenarios with the new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.timeprovider?view=net-8.0">TimeProvider class</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threading.itimer?view=net-8.0">ITimer interface</a>, which add time abstraction functionality.</p>
<h3>UTF8 improvements</h3>
<p>The new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.iutf8spanformattable">IUtf8SpanFormattable</a> interface targets <code>UTF8</code> and <code>Span&lt;byte&gt;</code> instead of <code>UTF16</code> and <code>Span&lt;char&gt;</code>. Also the new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.unicode.utf8.trywrite">Utf8.TryWrite</a> methods provide a <code>UTF8</code> based counterpart to the existing <a href="https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.trywrite">MemoryExtensions.TryWrite</a> methods, which are UTF16-based.</p>
<h3>Data validation</h3>
<p>There are new validation attributes for cloud-native services. The new properties were added to the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute">RangeAttribute</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.requiredattribute">RequiredAttribute</a> types. See the list below for the new validation attributes:</p>
<p>| New Data Attribute                                           | Description                                                  |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute.minimumisexclusive#system-componentmodel-dataannotations-rangeattribute-minimumisexclusive">MinimumIsExclusive</a>, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute.maximumisexclusive#system-componentmodel-dataannotations-rangeattribute-maximumisexclusive">MaximumIsExclusive</a> | Checks whether bounds are included in the allowable range    |
| <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.lengthattribute">Length</a> | Checks both lower and upper bounds for strings or collections. For example, <code>[Length(5, 10)]</code> requires at least 5 elements and at most 10 elements in a collection |
| <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.base64stringattribute">Base64String</a> | Checks that a string is a valid Base64 format                |
| <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.allowedvaluesattribute">AllowedValues</a>, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.deniedvaluesattribute">DeniedValues</a> | Checks if values are from the allowed or disallowed list  eg: <code>[AllowedValues(&quot;man&quot;, &quot;woman&quot;, &quot;child&quot;)]</code> |</p>
<h3>Randomness methods</h3>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.random">System.Random</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator">System.Security.Cryptography.RandomNumberGenerator</a> types present 2 new approaches  to handling randomness.</p>
<h3>Performance-focused types</h3>
<ul>
<li>The new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen">System.Collections.Frozen</a> namespace includes the collection types <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozendictionary-2">FrozenDictionary</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozenset-1">FrozenSet</a>.</li>
<li>Methods like <a href="https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.indexofany">MemoryExtensions.IndexOfAny</a> look for the first occurrence of <em>any value in the passed collection</em>.</li>
<li>The new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.compositeformat">System.Text.CompositeFormat</a> type is useful for optimizing format strings that aren't known at compile time (for example, if the format string is loaded from a resource file).</li>
<li>New <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.hashing.xxhash3">System.IO.Hashing.XxHash3</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.hashing.xxhash128">System.IO.Hashing.XxHash128</a> types provide implementations of the fast XXH3 and XXH128 hash algorithms.</li>
</ul>
<h3>System.Numerics and System.Runtime.Intrinsics</h3>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics">System.Numerics</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics">System.Runtime.Intrinsics</a> namespaces introduces some hardware improvements with .NET 8. The following structs reimplemented for running with the best performance on ARM64.</p>
<p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector256-1">Vector256</a>, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix3x2">Matrix3x2</a>, and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix4x4">Matrix4x4</a> have improved</p>
<h3>Metrics</h3>
<p>New APIs let you attach key-value pair tags to <a href="https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.metrics.meter">Meter</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.metrics.instrument">Instrument</a> objects when you create them. Aggregators of published metric measurements can use the tags to differentiate the aggregated values.</p>
<h3>Cryptography</h3>
<p><a href="https://en.wikipedia.org/wiki/SHA-3">SHA-3</a> (Secure Hash Algorithm 3) is the latest member of the Secure Hash Algorithm family of standards. With .NET 8 SHA-3 is being supported.</p>
<h3>HTTPS proxy support</h3>
<p>Before  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient">HttpClient</a> allows hackers to make <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">man-in-the-middle attack</a> with .NET 8,  it creates an encrypted channel between the client and the proxy so all requests can be handled with full privacy.</p>
<h3>Stream-based ZipFile methods</h3>
<p>The new <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.compression.zipfile.extracttodirectory">ZipFile.ExtractToDirectory</a> provides a stream containing a zipped file and extract its contents into the filesystem.</p>
<h3>Hosted lifecycle services</h3>
<p>Hosted services now have more options for execution during the application lifecycle. <a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedservice">IHostedService</a> provided <code>StartAsync</code> and <code>StopAsync</code>, and now <a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedlifecycleservice">IHostedLifecycleService</a> provides these additional methods:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedlifecycleservice.startingasync#microsoft-extensions-hosting-ihostedlifecycleservice-startingasync(system-threading-cancellationtoken)">StartingAsync(CancellationToken)</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedlifecycleservice.startedasync#microsoft-extensions-hosting-ihostedlifecycleservice-startedasync(system-threading-cancellationtoken)">StartedAsync(CancellationToken)</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedlifecycleservice.stoppingasync#microsoft-extensions-hosting-ihostedlifecycleservice-stoppingasync(system-threading-cancellationtoken)">StoppingAsync(CancellationToken)</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.ihostedlifecycleservice.stoppedasync#microsoft-extensions-hosting-ihostedlifecycleservice-stoppedasync(system-threading-cancellationtoken)">StoppedAsync(CancellationToken)</a></li>
</ul>
<h3>Native AOT support</h3>
<p>The option to <a href="https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/">publish as Native AOT</a> was first introduced in .NET 7. Publishing an app with Native AOT creates a fully self-contained version of your app that doesn't need a runtime—everything is included in a single file. .NET 8 brings the following improvements to Native AOT publishing:</p>
<p>| Operating system                        | .NET 7  | .NET 8  |
| :-------------------------------------- | :------ | :------ |
| Linux x64 (with <code>-p:StripSymbols=true</code>) | 3.76 MB | 1.84 MB |
| Windows x64                             | 2.85 MB | 1.77 MB |</p>
<h3>Target iOS-like platforms with Native AOT</h3>
<p>.NET 8 starts the work to enable Native AOT support for iOS-like platforms. You can now build and run .NET iOS and .NET MAUI applications with Native AOT on the following platforms:</p>
<ul>
<li><code>ios</code></li>
<li><code>iossimulator</code></li>
<li><code>maccatalyst</code></li>
<li><code>tvos</code></li>
<li><code>tvossimulator</code></li>
</ul>
<h3>Performance improvements</h3>
<p>.NET 8 includes improvements to code generation and just-in time (JIT) compilation:</p>
<ul>
<li>Arm64 performance improvements</li>
<li>SIMD improvements</li>
<li>Support for AVX-512 ISA extensions (see <a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#vector512-and-avx-512">Vector512 and AVX-512</a>)</li>
<li>Cloud-native improvements</li>
<li>JIT throughput improvements</li>
<li>Loop and general optimizations</li>
<li>Optimized access for fields marked with <a href="https://learn.microsoft.com/en-us/dotnet/api/system.threadstaticattribute">ThreadStaticAttribute</a></li>
<li>Consecutive register allocation. Arm64 has two instructions for table vector lookup, which require that all entities in their tuple operands are present in consecutive registers.</li>
<li>JIT/NativeAOT can now unroll and auto-vectorize some memory operations with SIMD, such as comparison, copying, and zeroing, if it can determine their sizes at compile time.</li>
</ul>
<h3>.NET SDK</h3>
<p>This section contains the following subtopics:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#cli-based-project-evaluation">CLI-based project evaluation</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#terminal-build-output">Terminal build output</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#simplified-output-paths">Simplified output paths</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#dotnet-workload-clean-command">'dotnet workload clean' command</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#dotnet-publish-and-dotnet-pack-assets">'dotnet publish' and 'dotnet pack' assets</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#template-engine">Template engine</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#source-link">Source Link</a></li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#source-build-sdk">Source-build SDK</a></li>
</ul>
<h3>ASP.NET composite images</h3>
<p>As part of an effort to improve containerization performance, new ASP.NET Docker images are available that have a composite version of the runtime. This composite is built by compiling multiple MSIL assemblies into a single ready-to-run (R2R) output binary. Because these assemblies are embedded into a single image, jitting takes less time, and the startup performance of apps improves. The other big advantage of the composite over the regular ASP.NET image is that the composite images have a smaller size on disk.</p>
<h3>Source-generated COM interop</h3>
<p>.NET 8 includes a new source generator that supports interoperating with COM interfaces.</p>
<h3>Minimum support baselines for Linux</h3>
<p>The minimum support baselines for Linux have been updated for .NET 8. .NET is built targeting Ubuntu 16.04, for all architectures.</p>
<h3>AOT compilation for Android apps</h3>
<p>To decrease app size, .NET and .NET MAUI apps that target Android use <em>profiled</em> ahead-of-time (AOT) compilation mode when they're built in Release mode. Profiled AOT compilation affects fewer methods than regular AOT compilation. .NET 8 introduces the <code>&lt;AndroidStripILAfterAOT&gt;</code> property that lets you opt-in to further AOT compilation for Android apps to decrease app size even more.</p>
<h3>Code analysis</h3>
<p>.NET 8 includes several new code analyzers and fixers to help verify that you're using .NET library APIs correctly and efficiently. The following table summarizes the new analyzers.</p>
<h3>NuGet</h3>
<p>Starting in .NET 8, NuGet verifies signed packages on Linux by default. NuGet continues to verify signed packages on Windows as well.</p>
<h3>C# Hot Reload supports modifying generics</h3>
<p>Starting in .NET 8, C# Hot Reload <a href="https://devblogs.microsoft.com/dotnet/hot-reload-generics/">supports modifying generic types and generic methods</a>. When you debug console, desktop, mobile, or WebAssembly applications with Visual Studio, you can apply changes to generic classes and generic methods in C# code or Razor pages. For more information, see the <a href="https://github.com/dotnet/roslyn/blob/main/docs/wiki/EnC-Supported-Edits.md">full list of edits supported by Roslyn</a></p>
<p><em>References:</em></p>
<ul>
<li>https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a102024-f765-ac52-fe25-ed6e30d34614" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a102024-f765-ac52-fe25-ed6e30d34614" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/blazors-history-and-fullstack-web-ui-gvk8vwqr</guid>
      <link>https://abp.io/community/posts/blazors-history-and-fullstack-web-ui-gvk8vwqr</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>net8</category>
      <category>blazor</category>
      <title>Blazor's History and Full-stack Web UI</title>
      <description>The first version of Blazor was released on May 14, 2020. Since its initial release, Blazor has evolved into six different versions. In this post, I explain the history of Blazor and show you the new version that comes with .NET 8. It's called Blazor Fullstack UI (formerly known as Blazor United). </description>
      <pubDate>Tue, 07 Nov 2023 06:37:58 Z</pubDate>
      <a10:updated>2026-03-02T17:25:50Z</a10:updated>
      <content:encoded><![CDATA[<h1>Blazor's History and Full-stack Web UI</h1>
<p>Blazor is a web framework that allows developers to build interactive web applications using .NET instead of JavaScript. The first version of Blazor was released on May 14, 2020.  Since its initial release, Blazor has evolved with the new versions. Until now, six different versions have been declared. Sometimes, it can be not very clear to see the differences between these approaches. First, let's try to understand these.</p>
<ul>
<li><p><strong>Blazor-Server</strong>: &gt;&gt; <em>Loads fast at first</em> &gt;&gt; In this version, heavy things are done in the server. Browsers are thin clients and download a small page for the first load. The page updates are done via SignalR connection. This was released with .NET Core 3.</p>
</li>
<li><p><strong>Blazor WebAssembly (WASM):</strong> &gt;&gt; <em>Loads slow at first</em> &gt;&gt;  In this version, some binary files are being downloaded to the browser. This approach takes longer initialization time than the &quot;Server&quot; approach. The hard work is done on the browser.</p>
</li>
<li><p><strong>Blazor Hybrid:</strong> It's a combination of Blazor and Xamarin.Forms. It allows you to run your app on iOS, Android, macOS, and Windows. Blazor Hybrid uses a WebView component to host the  Blazor-based user interface within the mobile app.</p>
</li>
<li><p><strong>Blazor Native</strong>: It runs natively on the devices and uses a common UI abstraction to render native controls for that device. This is very  similar to how frameworks like Xamarin Forms or React Native work today. It has also been considered but has not reached <a href="https://devblogs.microsoft.com/dotnet/blazor-server-in-net-core-3-0-scenarios-and-performance/">the planning stage</a>.</p>
</li>
<li><p><strong>Blazor United</strong>: Recently, Microsoft updated this name to &quot;Fullstack web UI&quot;. Blazor-Server and Blazor WASM both have some disadvantages and advantages. So, Microsoft decided to combine these two approaches and find an optimum solution for the entire Blazor version. We can call it <em>Best of Blazor</em> 😀</p>
</li>
</ul>
<h2>Why is &quot;Blazor Fullstack Web UI&quot; the best?</h2>
<p>These apps are a combination of both Blazor Server and Blazor WASM. It provides the advantages of Blazor Server and WASM. Developers would be able to more fine-tune the rendering mode. <strong>This approach overcomes the large binary downloads of Blazor WASM, and it resolves the Blazor Server's problem, which always needs to be connected to the server via SignalR.</strong></p>
<blockquote>
<p>Blazor Fullstack Web UI comes with the .NET 8, and it will be published on November 14, 2023.</p>
</blockquote>
<p>I took the following photo from Steven Sanderson's talk at NDC Porto 2023. You can read my impressions of this conf at https://volosoft.com/blog/ndc-port-2023-impressions, but after reading this one.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106163046763-1699282281622-2.png" alt="image-20231106163046763" /></p>
<p>There are two basic page styles:</p>
<ul>
<li><strong>HTML</strong>; simple and loads fast! Eg: MVC, Razor Pages</li>
<li><strong>Single Page Apps (SPA):</strong> high interaction with the client and loads slower! Eg: Blazor WASM, Blazor Server...</li>
</ul>
<h2>HTML + SPA =&gt; Blazor Fullstack</h2>
<p>Blazor Fullstack (formerly United) is a technology that turns Blazor Server into a SPA style.</p>
<p>.NET 8 will combine Blazor Server's server-side rendering and WebAssembly's client-side interaction.</p>
<p>You can switch between two rendering modes and even mix them on the same page. With .NET 8 there also comes amazing features like;</p>
<ul>
<li><p><a href="https://github.com/dotnet/aspnetcore/issues/46352">Streaming rendering</a>: With this feature, most of the page will be rendered, and long async operations on the server will still be in progress.</p>
</li>
<li><p><a href="https://github.com/dotnet/aspnetcore/issues/46399">Progressive enhancement of form submission &amp; navigation</a>: With this feature, it doesn't fully reload the page after submitting the form. This gives the user a better and smoother experience.</p>
</li>
</ul>
<h2>How it works?</h2>
<h3>Rendering on Server</h3>
<p>You can add <code>WebComponentRenderMode.Server</code> to your Blazor components so that these components will run interactively. In the below example, the list editor will make AJAX requests to the server like single-page applications.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106172420148.png" alt="image-20231106172420148" /></p>
<p>And sure, you can add <code>WebComponentRenderMode.Server</code> to your page level, and the complete page will be rendered as a server component. All inputs on this page can work as an interactive server component like SPA mode.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106172638604.png" alt="image-20231106172638604" /></p>
<h3>Rendering on Client</h3>
<p>You can switch to WebAssembly mode by writing  <code>WebComponentRenderMode.WebAssembly</code> attribute to your page. By doing so, the whole page should run interactively using WebAssembly. This time there's no server connection anymore because it loads the binaries (WebAssembly runtimes) at the page load.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106173021958.png" alt="image-20231106173021958" /></p>
<h2>Enabling the Blazor Fullstack UI?</h2>
<p>To enable Blazor Full-stack Web UI, you need to write <code>net8.0;net7.0-browser</code> into the <code>TargetFrameworks</code> area of your <code>csproj</code> file. These two keywords change your app like this; <code>net8.0</code> framework renders on the server, and <code>net7.0-browser</code> framework renders on the browser.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106173411309.png" alt="image-20231106173411309" /></p>
<h2>Let the System Decide WebAssembly or Server Approach</h2>
<p>You can let the system decide whether it uses <code>WebAssembly</code> or <code>Server</code>. This can be done with the <code>Auto</code> mode of the <code>WebComponentRenderMode</code>. In this case, it will not load binary files (WebAssembly files) for the initial page that has  <code>WebComponentRenderMode.Server</code> attribute, but whenever the user navigates to a page that has <code>WebComponentRenderMode.WebAssembly</code>, it will download the runtimes. This will allow us to load the initial page very fast, and when we need interactivity, we can switch to <code>WebAssembly</code> and wait for the binaries to download. But this download will be done one time because it will be cached.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-11-06-Blazor-Fullstack-Web-Ui/image-20231106173849303.png" alt="image-20231106173849303" /></p>
<h2>Conclusion</h2>
<p>I summarized the new generation Blazor in a very simple way. This architecture will be useful to everyone who uses Blazor.</p>
<hr />
<p><em>Resources:</em></p>
<ul>
<li>You can check Dan Roth's GitHub issue 👉 <a href="https://github.com/dotnet/aspnetcore/issues/46636">github.com/dotnet/aspnetcore/issues/46636</a>.</li>
<li>Steven Sanderson's YouTube video is very good for understanding these concepts 👉 <a href="https://youtu.be/48G_CEGXZZM">Blazor United Prototype Video</a>.</li>
<li>&quot;Full Stack Web UI with Blazor&quot; — .NET Conf 2023 video 👉 <a href="https://learn.microsoft.com/en-us/shows/dotnetconf-2023/full-stack-web-ui-with-blazor-in-dotnet-8">learn.microsoft.com/en-us/shows/dotnetconf-2023/full-stack-web-ui-with-blazor-in-dotnet-8</a></li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0ebaad-63eb-3027-1dea-6ad1dd17d79c" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0ebaad-63eb-3027-1dea-6ad1dd17d79c" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/c-12-discover-the-exciting-new-features-improvements--sckpgqlt</guid>
      <link>https://abp.io/community/posts/c-12-discover-the-exciting-new-features-improvements--sckpgqlt</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>csharp</category>
      <category>technews</category>
      <title>C# 12 🔍 Discover the Exciting New Features &amp; Improvements 🆕🚀</title>
      <description>What's new in C# 12?  Check out new C# 12 preview features! · In this post, some of the C# 12 features have been introduced.</description>
      <pubDate>Tue, 02 May 2023 14:26:04 Z</pubDate>
      <a10:updated>2026-03-02T16:41:28Z</a10:updated>
      <content:encoded><![CDATA[<p>Several exciting new features come with C# 12 and the.NET 8 preview. C# is easier to use and more effective than <strong>previous</strong> versions thanks to changes made by the Microsoft development team.  <strong>In</strong> <strong>this</strong> <strong>post,</strong> <strong>we'll</strong> <strong>take</strong> <strong>a</strong> <strong>quick</strong> <strong>look</strong> <strong>at</strong> some of the <strong>major</strong> changes in C# <strong>12.</strong></p>
<h2>1. Improved Support for Interpolated Strings 🧩</h2>
<p>With the release of C# 12, you now have the option to incorporate expressions inside interpolated strings. With the help of this functionality, You can now create dynamic values for strings using complicated expressions and techniques.</p>
<p>For instance, you can use code like this:</p>
<pre><code>
int x = 10;

string message = $&quot;The value of x is {x}, and its square is {x*x}.&quot;;

</code></pre>
<p>This will result in a string value of &quot;<em>The value of x is 10, and its square is 100.</em>&quot;</p>
<h2>2. Primary Constructors 📝</h2>
<p>You can now create primary constructors in any class and struct. With primary constructors, developers can add parameters to the class declaration and use these values inside the class body.</p>
<p>Primary constructors were introduced in C# 9 as part of the record positional syntax. C# 12 extends these to all structs and classes.</p>
<pre><code class="language-csharp">
 public class Book(int pageSize, string authorName, IEnumerable&lt;float&gt; prices)

  {

      public Book(int pageSize, string authorName) : this(pageSize, authorName, Enumerable.Empty&lt;float&gt;()) { }

      public int pageSize =&gt; pageSize;

      public string authorName { get; set; } = authorName;

      public float totalPrice =&gt; prices.Sum();

  }

</code></pre>
<p>The good part is that you can avoid the pain of declaring private fields and, you know, binding parameter values to those fields in those tedious constructor bodies by using primary constructors instead.</p>
<h2>3. Improved Lambda Expressions 🐑</h2>
<p>Many of us are using Lambda expressions in our daily development to gain the code better readability.</p>
<p>With this version we see that many enhancements came to lambda expressions make them more effective.</p>
<p>For example, you can now create more complex expressions within lambda functions using the new <code>and</code> , <code>or</code> operators.</p>
<p>Besides, lambda expressions can now be transformed into expression trees, simplifying the construction of complex queries and optimizing performance.</p>
<h2>4. Async Streams 🌐</h2>
<p>You may iterate through asynchronous data sources thanks to the new <code>async</code> streams feature in C# 12.</p>
<p>This new iterator <code>await foreach</code> gains us to iterate over a set of async data.</p>
<p>See the following code snippet:</p>
<pre><code class="language-csharp">
await foreach (var record in FetchRecordsAsyncData())

{

   Console.WriteLine(record.text);

}

</code></pre>
<p>This will iterate over the asynchronous data returned by the <code>GetAsyncData()</code> method and writes each item's text to the console.</p>
<h2>5. Target-typed New Expressions 🎯</h2>
<p>Target-typed new expressions, a new feature in C# 12, make it simpler to construct new objects.</p>
<p>You can now declare new objects using the <code>var</code> keyword.</p>
<p>The object's type is inferred from the context.</p>
<p>Especially when dealing with complex types, it gives us better code readability.</p>
<p>An alternative to writing:</p>
<pre><code class="language-csharp">
AcmeClass thatObject = new AcmeClass();

</code></pre>
<p>You can now write:</p>
<pre><code class="language-csharp">
var thatObject = new AcmeClass();

</code></pre>
<h2>Conclusion 🎬</h2>
<p>As always Microsoft makes developers' life easier with every release of .NET and C#.</p>
<p>C# 12 comes with many features and improvements.</p>
<p>You now have new tools at your disposal to create more effective, concise, and durable code.</p>
<p>You may now design more potent and reliable applications with C# thanks to the increased support for interpolated strings, records, lambda expressions, target-typed new expressions, and async streams.</p>
<h2>Start C# 12 with the ABP Framework 📚</h2>
<p>ABP Framework offers an opinionated architecture to build enterprise  software solutions with ASP.NET Core best practices on top of the .NET  and the ASP.NET Core platforms. It is also a powerful infrastructure to  help you develop low-effort web-optimized applications. It provides the fundamental web application infrastructure,  production-ready dotnet startup templates, modules, asp.net core ui  themes, tooling, guides and documentation to implement that ASP.NET core architecture properly and automate the details and repetitive work as  much as possible.</p>
<p>If you are starting a new ASP.NET Core project and want a fast website <a href="https://abp.io/">abp.io</a> now...</p>
<p>🆓 <strong>It's FREE &amp; OPEN-SOURCE!</strong> 🔓</p>
<p>Happy coding 🍿✨</p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻\</p>
</blockquote>
<blockquote>
<p>ABP Framework Core Team Member\</p>
</blockquote>
<blockquote>
<p>Follow me for the latest news about .NET and software development:\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0aef08-0469-8443-c89a-897956402be0" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0aef08-0469-8443-c89a-897956402be0" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/top-10-.net-core-libraries-every-developer-should-know--49t30b4y</guid>
      <link>https://abp.io/community/posts/top-10-.net-core-libraries-every-developer-should-know--49t30b4y</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>technews</category>
      <category>dotnet</category>
      <title>Top 10 .NET Core Libraries Every Developer Should Know 🔥</title>
      <description>This article is intended for .NET Core developers who wish to create a robust and useful.NET core application. It is a list of the most popular and widely used .NET Core libraries that have been carefully vetted. Go up the GitHub reference link for the DotNet libraries and see how many stars the .NET community has rewarded.</description>
      <pubDate>Tue, 11 Apr 2023 02:18:20 Z</pubDate>
      <a10:updated>2026-03-02T14:05:48Z</a10:updated>
      <content:encoded><![CDATA[<blockquote>
<p><em>Brief Summary</em>:</p>
</blockquote>
<blockquote>
</blockquote>
<blockquote>
<p>This article is intended for .NET Core developers who wish to create a robust and useful.NET core application. It is a list of the most popular and widely used .NET Core libraries that have been carefully vetted. Go up the GitHub reference link for the DotNet libraries and see how many stars the .NET community has rewarded.</p>
</blockquote>
<h2>Best .NET libraries — Top useful libraries every .NET developers use</h2>
<p>.NET Core has become one of the most popular frameworks for developing modern applications. One of the reasons for its popularity is the wide range of libraries available to developers.  .NET Core got new updates in its features with lesser coding, deploying  high-accomplishment, and extremely scalable applications.  Making the underlying architecture functions more effective and efficient without having to reinvent the wheel will free up your time to focus on more crucial tasks, including making your application stand out from the competition.</p>
<p>In this article, we'll take a closer look at <strong>The Most Popular .NET Libraries Every Developer Should Know</strong>.  As a software developer, you're likely familiar with the .NET framework and the many libraries it offers. With so many options available, it can be overwhelming to know which ones to choose for your project. This is the main reason I have compiled a list of the <strong>Top 10 .NET Libraries That Developers Should Use</strong> to make their development process more efficient and effective. A list of Top 10 .NET Core Libraries will let developers understand these so that they can pick appropriate libraries for their projects.</p>
<p>If you're a .NET Core developer, there are <strong>10 important .NET Core libraries</strong> that you should be familiar with.  While creating these <strong>Essential 10 .NET Libraries Every Developer Must Know</strong>, I used NuGet and GitHub.com popular repositories. And all the libraries listed here are also open-source. The list is filtered with only to .NET Core related libraries. Also I excluded the Microsoft .NET Core Framework libraries from this <strong>Top 10 Unique .NET Core Libraries Developers Must Utilize</strong>.  So, without further ado, let’s get right into it:</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a87d836c4e1b10a280fbab982d55f.png" alt="Best .NET libraries with GitHub stars and download counts" /></p>
<h2>Top 10 best libraries for .NET developers</h2>
<p>Here's the list of the most popular open-source .NET tools:</p>
<ol>
<li><p><strong>Newtonsoft.Json:</strong> This library is widely used for working with JSON data in .NET applications. It provides high performance and ease of use, making it a go-to solution for serialization and deserialization of JSON data.</p>
</li>
<li><p><strong>Dapper:</strong> It is a simple and efficient ORM that offers high performance and flexibility when working with relational databases. It is easy to use and offers a fast and efficient way to interact with databases.</p>
</li>
<li><p><strong>Polly:</strong> Polly is a library that helps handle transient errors and faults in .NET applications. It offers an easy-to-use policy-based approach to handling retries, timeouts, and circuit breakers, making it a valuable tool for building reliable applications.</p>
</li>
<li><p><strong>AutoMapper</strong>: This .NET Core library simplifies object-to-object mapping by automatically mapping properties from one object to another. This library is especially useful in larger projects where mapping can become time-consuming and tedious.</p>
</li>
<li><p><strong>FluentValidation:</strong> It is a library that provides a fluent API for building validation rules. It makes it easy to create complex validation logic and supports a wide range of validation scenarios, making it a valuable tool for ensuring data integrity in your applications.</p>
</li>
<li><p><strong>Serilog</strong>: This library is a structured logging library that makes it easy to collect and analyze logs from your application. It offers flexibility and extensibility, and supports a variety of sinks for storing logs, including Elasticsearch, SQL Server, and more.</p>
</li>
<li><p><strong>Swashbuckle.AspNetCore.Swagger:</strong> This library generates OpenAPI documentation for your ASP.NET Core Web API. It makes it easy to understand the functionality of your API and allows you to easily generate client code for your API.</p>
</li>
<li><p><strong>NLog</strong>: It is is a free logging platform for .NET with rich log routing and management capabilities. It makes it easy to produce and manage high-quality logs for your application regardless of its size or complexity.</p>
</li>
<li><p><strong>Moq4</strong>: It is is a popular mocking framework for .NET applications. It makes it easy to create mock objects for unit testing, reducing the need for expensive and time-consuming integration testing.</p>
</li>
<li><p><strong>StackExchange.Redis</strong>: This is a library for working with Redis databases in .NET applications. It provides a simple and efficient way to interact with Redis, and offers high performance and scalability.</p>
</li>
</ol>
<hr />
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-11-top-10-net-core-libraries-every-developer-should-know-/3a0a80478f1cfd26d5802eff5361ba70.png" alt="10 important .NET Core Libraries" /></p>
<h2>Top 10 .NET Core Libraries List That Every Developer Must Know</h2>
<p>Here you can see them in the table with the GitHub stars, GitHub release counts, recent release frequency, NuGet download counts and per day NuGet download counts:</p>
<p>| GitHub URL                                                   | NuGet URL                                                    | Stars | Releases | Last release | Downloads | Download Per Day |</p>
<p>| ------------------------------------------------------------ | ------------------------------------------------------------ | ----- | -------- | ------------ | --------- | ---------------- |</p>
<p>| <a href="https://github.com/JamesNK/Newtonsoft.Json">Newtonsoft.Json</a> | <a href="https://www.nuget.org/packages/Newtonsoft.Json">Newtonsoft.Json</a> | 10K   | 65       | 1 month ago  | 3B        | 680K             |</p>
<p>| <a href="https://github.com/DapperLib/Dapper">Dapper</a>                | <a href="https://www.nuget.org/packages/Dapper">Dapper</a>              | 16K   | 70       | 2 years ago  | 216M      | 50K              |</p>
<p>| <a href="https://github.com/App-vNext/Polly">Polly</a>                  | <a href="https://www.nuget.org/packages/polly">Polly</a>                | 12K   | 26       | 1 year ago   | 335M      | 92K              |</p>
<p>| <a href="https://github.com/AutoMapper/AutoMapper">AutoMapper</a>       | <a href="https://www.nuget.org/packages/AutoMapper">AutoMapper</a>      | 9K    | 41       | 6 months ago | 400M      | 90K              |</p>
<p>| <a href="https://github.com/FluentValidation/FluentValidation">FluentValidation</a> | <a href="https://www.nuget.org/packages/FluentValidation">FluentValidation</a> | 8K    | 68       | 3 days ago   | 250M      | 56K              |</p>
<p>| <a href="https://github.com/serilog/serilog">Serilog</a>                | <a href="https://www.nuget.org/packages/Serilog">Serilog</a>            | 6K    | 15       | 1 month ago  | 722M      | 197K             |</p>
<p>| <a href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore">Swashbuckle.AspNetCore.Swagger</a> | <a href="https://www.nuget.org/packages/Swashbuckle.AspNetCore.Swagger">Swashbuckle.AspNetCore.Swagger</a> | 5K    | 28       | 4 months ago | 386M      | 168K             |</p>
<p>| <a href="https://github.com/NLog/NLog">NLog</a>                         | <a href="https://www.nuget.org/packages/Nlog">NLog</a>                  | 6K    | 125      | 1 week ago   | 217M      | 48K              |</p>
<p>| <a href="https://github.com/moq/moq4">Moq</a>                           | <a href="https://www.nuget.org/packages/Moq">Moq</a>                    | 5K    | 33       | 4 months ago | 418M      | 93K              |</p>
<p>| <a href="https://github.com/StackExchange/StackExchange.Redis">StackExchange.Redis</a> | <a href="https://www.nuget.org/packages/StackExchange.Redis">StackExchange.Redis</a> | 5K    | 34       | 11 days ago  | 244M      | 74K              |</p>
<p>In conclusion, these 10 .NET Core libraries are essential tools for any .NET Core developer. They offer a wide range of functionality, from handling errors to mocking for unit testing and simplifying object mapping. Whether you're working on a large-scale enterprise application or a small project, these libraries can help you build more reliable, efficient, and effective applications.</p>
<p>There's also a cool GitHub page that gathers all kinds of popular .NET tools. Check out https://github.com/quozd/awesome-dotnet</p>
<h3>What is ABP Framework?</h3>
<p>ABP Framework offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET and the ASP.NET Core platforms. It provides the fundamental infrastructure, production-ready startup templates, modules, themes, tooling, guides and documentation to implement that architecture properly and automate the details and repetitive work as much as possible.</p>
<p>If you are starting a new ASP.NET Core project, try <a href="https://abp.io">abp.io</a> now...</p>
<p><strong>IT IS FREE AND OPEN-SOURCE!</strong></p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻 \</p>
</blockquote>
<blockquote>
<p>ABP Framework Core Team Member\</p>
</blockquote>
<blockquote>
<p>Follow me for the latest news about .NET and software development:\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0a8048-3691-803f-2bb6-e93744d1e1e8" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0a8048-3691-803f-2bb6-e93744d1e1e8" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-framework-the-ultimate-.net-web-framework-for-rapid-application-development-n68umtpd</guid>
      <link>https://abp.io/community/posts/abp-framework-the-ultimate-.net-web-framework-for-rapid-application-development-n68umtpd</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>technews</category>
      <category>open source</category>
      <category>rapid application development</category>
      <category>dotnet web framework</category>
      <category>best practises</category>
      <category>aspnet core architecture</category>
      <category>domain driven design dotnet</category>
      <title>ABP Framework: The Ultimate .NET Web Framework for Rapid Application Development</title>
      <description>Are you a .NET developer? There not so many popular ASPNET Framework around. However, the ABP Framework has become popular for many developers due to its flexibility, scalability, feature set and performance. Let's mention what's ABP Framework and what it promises to .NET developers.</description>
      <pubDate>Fri, 07 Apr 2023 00:32:49 Z</pubDate>
      <a10:updated>2026-03-02T16:52:29Z</a10:updated>
      <content:encoded><![CDATA[<p>Building robust web applications has become more important than ever as the world is becoming more web-focused. Choosing the right web development framework can be challenging with the rise of new tools and frameworks. Especially if you are a .NET developer, there are not so many popular ASPNET Framework around. However, the ABP Framework has become popular for many developers due to its flexibility, scalability, feature set and performance. Let's mention what's ABP Framework and what it promises to .NET developers.</p>
<h2>ASP.NET Core Architecture Best Practices</h2>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b44fb2a208a89d3c9a56916d653.png" alt="ABP Key Features" /></p>
<p>ABP Framework is an application design framework that provides developers with a powerful set of tools to build web applications quickly and efficiently. It is an open-source, cross-platform framework supporting monolithic and microservices architectures. ABP Framework is built on top of the ASP.NET Core architecture and incorporates best practices for developing web applications.</p>
<h2>ASP.NET Platform</h2>
<p>The framework includes a wide range of features, such as an angular code generator with the help of <a href="https://commercial.abp.io/tools/suite">ABP Suite</a>, project templates, and web application themes. These features enable developers to create web applications that are both functional and visually appealing without spending much time on coding. Moreover, ABP Framework provides a common application framework that can be used for different applications, including SaaS, e-commerce, and social media platforms.</p>
<p>ABP Framework also supports the domain-driven design, which means that the framework is designed to be flexible and adaptable to different business requirements. This approach allows developers to build applications aligned with business needs, ensuring they are efficient and effective.</p>
<h2>Open Source Dot Net Framework</h2>
<p>One of the major advantages of ABP Framework is its open-source nature. Many developers continuously improve and update the framework, making it more reliable and secure. Moreover, the ABP Framework is compatible with multiple .NET frameworks, including ASP.NET and .NET Core. When starting your project on top of a solid Microsoft web framework, the ABP Framework is one of the best choices.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b45f7f68832d7a7f72262f3c216.png" alt="ABP is cross platform" /></p>
<p>Another advantage of ABP Framework is that it provides rapid web application development tools that are easy to use. The framework includes project templates that developers can use as a starting point for their web applications, which can significantly reduce the development time. ABP Framework also provides a web app builder that developers can use to create web applications quickly and efficiently.</p>
<h2>ASPNET Core Architecture</h2>
<p>ABP Framework is also compatible with Microsoft's Clean Architecture, a software design pattern that promotes separation of concerns and maintainability. This integration ensures that the applications developed using ABP Framework are well-structured, easy to maintain, and scalable. Many application marketplace reviewers commented about ABP as the best web application framework. While ABP supports multiple UI choices like MVC, Angular, Blazor Web Assembly, and Blazor Server, the most downloaded one is MVC microservice architecture. If you are here to find a NET application framework for your next NET Core application, you are in the right place!</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4812b27aa05c1159478175fa02.png" alt="ABP Framework Project Hierarchy" /></p>
<p>Clean Architecture is a design pattern emphasizing the separation of concerns, ensuring that the code is organized in independent layers. This helps developers to write code that is easy to maintain, test and refactor. ABP Framework uses this pattern to structure its application code and ensure it is easy to manage.</p>
<h2>Open Source Web Framework</h2>
<p>ABP Framework is an open-source web framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions.</p>
<p>ABP Framework provides different templates, which are ASPNET Core web app compatible with various platforms, including Windows, Linux, and macOS.</p>
<h2>Domain Driven Design DotNet</h2>
<p>The ABP Framework also implements Domain-Driven Design (DDD), a software design methodology that emphasizes the importance of the domain model. The framework provides a guide for implementing DDD through an implementing domain-driven design. It helps developers to create a domain model that is easy to understand, test, and maintain. As ABP is a C# framework, it supports most of the common application framework features for a core framework.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b492ee3cbf9482090fcc8473653.png" alt="ABP Framework - Domain Driven Design e-book" /></p>
<p>There is also a free PDF e-book for Dotnet developers that explains the Domain Driven Design principle with real-world examples. The book is written by the ABP Core Team. You can download this e-book at <a href="https://abp.io/books/implementing-domain-driven-design">abp.io/books/implementing-domain-driven-design</a></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b58d26f47970f6edd6f6fbee851.png" alt="The official book of ABP Framework: Mastering ABP Framework" /></p>
<p>You can also purchase the official Mastering ABP Framework book from Amazon. Check out <a href="https://www.amazon.com/Mastering-ABP-Framework-maintainable-implementing/dp/1801079242">amazon.com/Mastering-ABP-Framework-maintainable-implementing/dp/1801079242</a></p>
<h2>It's a Dotnet Web Framework</h2>
<p>ABP Framework is a dotnet web framework that is designed with C# and provides developers with a set of tools that makes it easy to build modern web applications. Whether you want to start a new dotnet monolithic solution or dotnet microservice solution, you can start with ABP. Creating your own dotnet framework architecture may be hard if you don't have many years of experience. The brain team of the ABP Framework specializes in ASP.NET framework architecture and ASP.NET application frameworks.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3c7807c882c1889c1f431b86b7.png" alt="ABP Framework is developer focused" /></p>
<h2>Essential Features of the ABP Framework:</h2>
<p>ASP.NET Core modularity, ASP.NET Core modular development, ASP.NET Core localization, ASP.NET Core SaaS framework, ASP.NET Core distributed, event, bus, ASP.NET Core cross-cutting concerns, ASP.NET Core blob storing, ASP.NET Core audit logging, ASP.NET Core microservice, ASP.NET Core microservice solution, ASP.NET Core microservice example, ASP.NET Core API gateway, ASP.NET Core domain, driven, design, ASP.NET Core layered architecture, ASP.NET Core layering, ASP.NET Core clean architecture, ASP.NET Core authentication, ASP.NET Core authorization, ASP.NET Core UI theme, ASP.NET Core tag helpers, ASP.NET Core identity, ASP.NET Core, identity, server, ASP.NET Core IdentityServer, ASP.NET Core payment module, ASP.NET Core best practices, ASP.NET Core design patterns, ASP.NET Core background jobs, ASP.NET Core exception handling, ASP.NET Core, background, workers, ASP.NET Core repository, ASP.NET Core repository pattern, ASP.NET Core unit of work, ASP.NET Core domain services, ASP.NET Core Swagger, ASP.NET Core content management system, ASP.NET Core CMS module, ASP.NET Core user management, ASP.NET Core Role management, ASP.NET Core permission management</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b4b7f00461297fbe88d4c34b831.png" alt="ABP Essential Features" /></p>
<h2>Open Source Web Application Framework</h2>
<p>ABP Framework is an open-source web application development framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b43a8bea7e8df7d2ff6b7f1aa8f.png" alt="ABP Framework is open-source" /></p>
<h2>C# Web Application Framework</h2>
<p>ABP Framework is built using C#, which is a modern programming language that is widely used in the development of web applications. C# provides developers with features that make it easy to write clean and maintainable code. ABP Framework is a web framework designed to work with C# and provides developers with tools that make it easy to build modern web applications.</p>
<h2>Key Features</h2>
<p>The following .NET features are available in the ABP Framework:</p>
<p>.NET modular development, .NET localization, .NET multi-tenancy, .NET SaaS framework, .NET distributed event bus, .NET cross-cutting concerns, .NET, microservice, .NET microservice solution, .NET microservice example, .NET Domain Driven Design, .NET clean architecture, .NET authentication, .NET authorization, .NET best practices, .NET design patterns, .NET exception handling, .NET background workers, .NET unit of work, .NET domain services, .NET user management, .NET role management, .NET permission management</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3d69a4f5b2b15674fc70e97ba2.png" alt="ABP Framework Features" /></p>
<p>The following keywords best describe the ABP Framework;</p>
<p>Open source backend framework, open source development framework, open source web app builder, open source web applications, open source web development, web application development framework, web application framework, web application framework software, web application infrastructure, web application open source, asp net framework, asp net open source, ASP.NET application, ASP.NET software, ASP.NET web app, ASP.NET web development, web app builder open source, web app framework, Dotnet framework, Dotnet UI framework, Dotnet web application themes.</p>
<h2>Conclusion</h2>
<p>ABP Framework is a powerful and flexible web application framework that provides developers with the tools to build high-quality web applications quickly and efficiently. It is an open-source, cross-platform framework that supports multiple .NET frameworks, including ASP.NET and .NET Core. ABP Framework provides rapid web application development tools, project templates, and web application themes that enable developers to create visually appealing and functional applications in no time.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-07-abp-framework-the-ultimate-net-web-framework-for-rapid-application-development/3a0a6b3dbc9eb0ada4effa3d06208fb4.png" alt="Try ABP Framework Now to be hero in the first day" /></p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻\</p>
</blockquote>
<blockquote>
<p>ABP Framework Core Team Member\</p>
</blockquote>
<blockquote>
<p>Follow me for the latest news about .NET and software development:\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0a6b4e-2ec3-c355-62f2-be86ad23aef5" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0a6b4e-2ec3-c355-62f2-be86ad23aef5" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-framework-open-source-web-application-development-framework-mmiypxei</guid>
      <link>https://abp.io/community/posts/abp-framework-open-source-web-application-development-framework-mmiypxei</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>technews</category>
      <category>open source</category>
      <category>web framework</category>
      <category>app builder</category>
      <category>clean architecture</category>
      <title>ABP Framework: Open Source Web Application Development Framework</title>
      <description>ABP Framework is an open-source web application development framework that provides developers with a set of tools to build modern, scalable, and maintainable web applications. </description>
      <pubDate>Mon, 03 Apr 2023 03:24:55 Z</pubDate>
      <a10:updated>2026-03-02T18:04:48Z</a10:updated>
      <content:encoded><![CDATA[<p>ABP Framework is an open-source web application development framework that provides developers with a set of tools to build modern, scalable, and maintainable web applications. ABP Framework is also a C# web framework that is based on the ASP.NET web framework. It is one of the <a href="https://github.com/abpframework/abp">most popular repository</a> for open source application framework.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5bccb0f41d45e97f2ff4d962d5fd.png" alt="ABP Framework is an open source web development framework " /></p>
<p>ABP Framework is a modular and extensible framework that uses clean architecture principles and is built on top of the latest .NET technologies. The framework comes with a set of pre-built modules, including user management, role management, permission management, and content management system (CMS) modules, which makes it easier for developers to create line of business applications.</p>
<h2>Clean Architecture</h2>
<p>When you want to start a new scratch project, you first google Dotnet Framework Architecture. There are some boilerplate dotnet startup templates, but these are only an orchestration of some popular tools. ABP is not a template, but it's a full stack open source application development framework.</p>
<p>When you say &quot;Clean Architecture ASP.NET Core&quot;, the first web development framework that comes to mind is undoubtedly the ABP Framework. It is built using clean architecture principles, which help developers build scalable and maintainable applications. The clean architecture separates the application into distinct layers, each with a clear responsibility. The dotnet architecture layers include the presentation layer, application layer, domain layer, and infrastructure layer. Each layer has a clear responsibility, which helps in separating concerns and keeping the code organized. This makes ABP Framework one of the best asp net frameworks.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d0d129822a1deb4f2f5b3310a.png" alt="Clean architecture - ABP Layers" /></p>
<h2>C# Web Framework for Web Development</h2>
<p>ABP Framework is built using C#, which is a modern programming language that is widely used in the development of web applications. C# provides developers with a set of features that make it easy to write clean and maintainable code. ABP Framework is a web framework that is designed to work with C# and provides developers with a set of tools that makes it easy to build modern web applications. If you are looking for an ASP NET Core shared framework download, then go to https://abp.io/get-started and create your project.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f237946f9746a99e2ef62fca8.png" alt="ABP Framework Essentials" /></p>
<h2>Yet another ASP.NET Web Framework</h2>
<p>There are a few full stack AspNet Core frameworks around. Many of them are one developer projects which can be risky for you to start a long running project.  ABP Framework is built on top of the latest ASP NET Core Framework, which provides developers with a set of features that makes it easy to build modern web applications. And most important part is, ABP is backed with a large group of developers and it has almost 10K stars on GitHub. ASP.NET provides developers with a set of tools that makes it easy to build web applications using a model-view-controller (MVC) architecture.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a575077ee05f6b67f1d05658457ff.png" alt="ABP.io Platform" /></p>
<h2>Implementing Domain Driven Design with C#</h2>
<p>ABP Framework provides developers with a set of tools that make it easy to implement domain-driven design principles. The framework comes with a set of pre-built modules, including user management, role management, permission management, and content management system (CMS) modules, which makes it easier for developers to create complex applications.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574e38a4fd3d6dda4f9884ecd502.png" alt="Implementing Domain Driven Design with C#" /></p>
<h2>Open Source Web Application</h2>
<p>ABP Framework is an open-source web application development framework that is free to use and distribute. The framework is licensed under the MIT license, meaning developers can use it for commercial and non-commercial purposes without any restrictions.</p>
<h2>.NET Application Framework with Pre-Built Modules</h2>
<p>ABP Framework is built using the latest .NET technologies and provides developers with a set of tools that makes it easy to build modern web applications. ABP contains several important modules of a line of business applications.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba4ffbab9c4d502284b08b92b18.png" alt="ABP Pre-built Modules" /></p>
<h2>C# Microservice Framework</h2>
<p>ABP Framework is a C# microservices framework that is designed to help developers build scalable and maintainable microservices. The framework is also known as .NET .net microservices framework. It provides developers with a set of tools that makes it easy to build microservices using clean architecture principles.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574dd6214b6de0cf998da277eb4d.png" alt="C# Microservice Framework" /></p>
<h2>CRUD Tool Dotnet</h2>
<p>ABP Framework has a commercial version as well. The paid version comes with premium support, rich themes and there's a very handy tool called <a href="https://commercial.abp.io/tools/suite">ABP Suite</a> for &quot;CRUD page generation ASP.NET&quot;. While ABP is not a low-code or no-code platform, ABP Suite provides ASP NET rapid application development. There are many ASP.NET rapid development tools but only tools without a framework support. If you are looking for web based rapid application development tools (also open-source), ABP is the way to go!</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a5ba45243aa36cf8878e3907f96a8.png" alt="ABP Suite" /></p>
<h2>Modular Development</h2>
<p>One of the best sides of the ABP Framework is the modular development side. It's born as a modular system. There are several open source web frameworks around but many of them lack of modularity.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574f7e65be09cff31cdfeacadb66.png" alt="Modular Development" /></p>
<p>Let's see the key features of the ABP Framework:</p>
<ul>
<li><p>Multi-tenancy support</p>
</li>
<li><p>Cross-cutting concerns implemented</p>
</li>
<li><p>Full-stack microservice solution</p>
</li>
<li><p>SaaS framework</p>
</li>
<li><p>ASP.NET modular monolith</p>
</li>
<li><p>Has an ASP.NET user management module</p>
</li>
<li><p>Distributed events</p>
</li>
<li><p>Layered architecture</p>
</li>
<li><p>Free framework for website</p>
</li>
<li><p>Several framework templates</p>
</li>
</ul>
<h2>The Essential Features of ABP</h2>
<p>ABP Framework is an open source SaaS framework. This crucial feature distinguishes it from other open source web development frameworks.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574edb1461fcb4a37a2cdd16783e.png" alt="Essential Features" /></p>
<p>The following essential ASP.NET features are available in the ABP Framework:</p>
<p>ASP.NET modularity, ASP.NET modular development, ASP.NET localization, ASP.NET multi-tenancy, ASP.NET SaaS, ASP.NET SaaS framework, ASP.NET distributed events, ASP.NET distributed event bus,  ASP.NET cross-cutting concerns, ASP.NET blob storing, ASP.NET audit logging, ASP.NET microservice, ASP.NET microservice solution, ASP.NET microservice example, ASP.NET API gateway, ASP.NET domain driven design, ASP.NET layered architecture, ASP.NET layering, ASP.NET clean architecture, ASP.NET authentication, ASP.NET authorization, ASP.NET identity, ASP.NET identity server, ASP.NET IdentityServer,  ASP.NET payment module, ASP.NET best practices, ASP.NET design patterns, ASP.NET background jobs, ASP.NET exception handling, ASP.NET background workers, ASP.NET repository, ASP.NET repository pattern, ASP.NET unit of work, ASP.NET domain services, ASP.NET swagger, ASP.NET content management system, ASP.NET user management, ASP.NET role management, ASP.NET permission management</p>
<h2>Microservice Example: eShopOnAbp</h2>
<p><a href="https://github.com/abpframework/eShopOnAbp">eShopOnAbp</a> is a microservice example built on top of ABP. It is a sample net application similar to Microsoft's <a href="https://github.com/dotnet-architecture/eShopOnContainers">eShopOnContainer</a> project. It is a reference microservice solution built with the ABP Framework and .NET,  runs on Kubernetes with Helm configuration and includes API Gateways,  Angular and ASP.NET Core MVC applications with PostgreSQL and MongoDB  databases. For more information, check out https://github.com/abpframework/eShopOnAbp.</p>
<blockquote>
<p>⚠️ <strong>Important Notice</strong></p>
</blockquote>
<blockquote>
<p>This project, &quot;eshoponabp,&quot; is outdated. It served as a reference project for microservice architecture using the ABP Framework, but we now recommend using the <a href="https://abp.io/docs/latest/solution-templates/microservice">ABP Microservice Solution Template</a> for new projects.</p>
</blockquote>
<blockquote>
</blockquote>
<blockquote>
<p>The new template offers a modernized and officially supported starting point for building microservices with ABP. Please consider transitioning to the new template for the latest features and improvements.</p>
</blockquote>
<h2>Conclusion</h2>
<p>In conclusion, ABP Framework is an open-source web development framework that offers many features and benefits for building modern and scalable web applications. Its modular and extensible architecture, implementation of Domain-Driven Design, and compatibility with various platforms make it a popular choice for developers. Whether you're building a web application, microservices, or modular monoliths, ABP Framework has everything you need to get started.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2023-04-03-abp-framework-open-source-web-application-development-framework/3a0a574d690031cc40f67400922eecfb.png" alt="conclusion" /></p>
<p>Whether you're building a dot net website, a web app infrastructure, or a webpage framework, open source web application frameworks are a cost-effective and flexible option for web development. If you are looking for an open source web application builder which contains a project framework template with web application development tools (open source), <a href="https://abp.io/">ABP Framework</a> is the right choice.</p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻\</p>
</blockquote>
<blockquote>
<p>ABP Framework Core Team Member\</p>
</blockquote>
<blockquote>
<p>Follow me for the latest news about .NET and software development:\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a>\</p>
</blockquote>
<blockquote>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0a5752-4f17-5974-166a-25c75aad862c" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0a5752-4f17-5974-166a-25c75aad862c" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/whats-new-in-.net-8-discover-all-.net-8-features-llcmrdre</guid>
      <link>https://abp.io/community/posts/whats-new-in-.net-8-discover-all-.net-8-features-llcmrdre</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>NET8</category>
      <category>new features</category>
      <category>dotnet</category>
      <title>What’s New in .NET 8 🧐 ? Discover ALL .NET 8 Features⚡🚀</title>
      <description>📢 In this post, we'll explore all the new features of .NET 8 and the changes in this new version. Grab your coffee ☕ and let's take a look at all the exciting new updates .NET 8 has in store for us.</description>
      <pubDate>Sun, 26 Mar 2023 23:47:43 Z</pubDate>
      <a10:updated>2026-03-02T12:35:23Z</a10:updated>
      <content:encoded><![CDATA[<h1>What’s New in .NET 8 🧐 ? Discover ALL .NET 8 Features⚡🚀</h1>
<p>In this post, I'll briefly mention the new features of .NET 8 and the changes.</p>
<h2><code>dotnet publish</code> and <code>dotnet pack</code> Release Mode 🏭</h2>
<p>With this new version, <code>dotnet publish</code> and <code>dotnet pack</code> commands will build and pack with the <code>Release</code> mode. Before it was producing in <code>Debug</code> mode. To be able to produce in Debug mode, you need to set this parameter <code>-p:PublishRelease</code> as false.</p>
<pre><code class="language-bash">dotnet publish -&gt; /app/bin/Release/net8.0/app.dll
dotnet publish -p:PublishRelease=false -&gt; /app/bin/Debug/net8.0/app.dll
</code></pre>
<hr />
<h2>System.Text.Json Serialization 🧱</h2>
<p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json">System.Text.Json</a> replaced Newtonsoft.Json in the recent versions. We are also using <code>System.Text.Json</code> in the <a href="https://abp.io">ABP Framework</a> now. There are several enhancements to object serialization and deserialization.</p>
<p>The latest version of the <a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation">source generator</a> now offers improved  performance and reliability for Native AOT apps when used with ASP.NET  Core. It also allows serializing types with <a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/required-properties"><code>required</code></a> and <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init"><code>init</code></a> properties already supported in reflection-based  serialization. Additionally, there is now an option to customize the  handling of members that are not present in the JSON payload, see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/missing-members. Support for serializing properties from interface hierarchies. The  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonnamingpolicy?view=net-8.0&amp;preserve-view=true#properties">JsonNamingPolicy</a> feature has been expanded to include new naming  policies for <code>snake_case</code> and <code>kebab-case</code> property name conversions.  Finally, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.makereadonly#system-text-json-jsonserializeroptions-makereadonly">JsonSerializerOptions.MakeReadOnly</a> method allows for explicit  control over when a <code>JsonSerializerOptions</code> instance is frozen, and you  can check its status using the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializeroptions.isreadonly#system-text-json-jsonserializeroptions-isreadonly">IsReadOnly</a>  property.</p>
<hr />
<h2>Randomness</h2>
<p>AI programming is very popular these days. And the need to produce more random content arose.</p>
<h3>GetItems<T>() 🧮</h3>
<p>Two new methods: <a href="https://learn.microsoft.com/en-us/dotnet/api/system.random.getitems">Random.GetItems</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator.getitems">RandomNumberGenerator.GetItems</a> have been introduced that enable developers to randomly select a set number  of items from a given input set. The example below demonstrates the  usage of the <code>System.Random.GetItems&lt;T&gt;()</code> method using an instance obtained from the <code>Random.Shared</code> property to randomly insert 31 items into an array.</p>
<pre><code class="language-csharp">private static ReadOnlySpan&lt;CountryPhoneCodePhoneCode&gt; countries = new[]
{
    new CountryPhoneCode(&quot;Turkey&quot;, &quot;90&quot;),
    new CountryPhoneCode(&quot;China&quot;, &quot;86&quot;),
    new CountryPhoneCode(&quot;Germany&quot;, &quot;49&quot;),
    new CountryPhoneCode(&quot;Finland&quot;, &quot;358&quot;),
    new CountryPhoneCode(&quot;Spain&quot;, &quot;34&quot;)
};

var randomValues = Random.Shared.GetItems(countries, 2);
foreach (var x in randomValues)
{
    Console.WriteLine(x.Name + &quot; -&gt; &quot; + x.CountryPhoneCode);
}

/**************
- Output -
Germany -&gt; 49
Finland -&gt; 358
**************/
</code></pre>
<hr />
<h3>Shuffle<T>() 🔀</h3>
<p>If you need to randomize the order of a span in your application, you can take advantage of two new methods: <a href="https://learn.microsoft.com/en-us/dotnet/api/system.random.shuffle">Random.Shuffle</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator.shuffle?view=net-8.0">RandomNumberGenerator.Shuffle</a>. These methods are particularly handy when you want to minimize the impact of training bias in machine learning by varying the order in which training and testing data are presented. Using these methods, you can ensure that the first thing in your dataset is only sometimes used for training, and the last is only sometimes reserved for testing.</p>
<pre><code class="language-csharp">var trainingData = GetData();
Random.Shared.Shuffle(trainingData);

IDataView source = mlContext.Data.LoadFromEnumerable(trainingData);

DataOperationsCatalog.TrainTestData splittedData = mlContext.Data.TrainTestSplit(source);
model = chain.Fit(splittedData.TrainSet);

IDataView resultPredictions = model.Transform(split.TestSet);
</code></pre>
<hr />
<h2>Performance Improvements 🚀</h2>
<p>In .NET 8, various new types have been introduced to enhance application performance.</p>
<ul>
<li><p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen">System.Collections.Frozen</a> namespace in .NET 8 includes the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozendictionary-2">FrozenDictionary</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.collections.frozen.frozenset-1">FrozenSet</a> collection types. These types are designed to prevent changes to keys  and values once a collection is created, resulting in faster read  operations such as <code>TryGetValue()</code>. They are particularly useful for  collections populated on first use and then persisted for a long-lived service.</p>
<pre><code class="language-csharp">private static readonly FrozenDictionary&lt;string, bool&gt; frozenData = LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true); 
//////
if (frozenData.TryGetValue(key, out bool setting) &amp;&amp; setting) 
{
Process();
}
</code></pre>
</li>
<li><p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.buffers.indexofanyvalues-1">Buffers.IndexOfAnyValues</a> is a new type in .NET 8, designed to be passed to methods that search for the first occurrence of any value in a passed collection. The new overloads of methods like <a href="https://learn.microsoft.com/en-us/dotnet/api/system.string.indexofany?view=net-8.0#system-string-indexofany(system-char())">String.IndexOfAny</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.indexofany">MemoryExtensions.IndexOfAny</a> accept an instance of the new type. When you create an instance of <a href="https://learn.microsoft.com/en-us/dotnet/api/system.buffers.indexofanyvalues-1">Buffers.IndexOfAnyValues</a>, all the necessary data for optimizing subsequent searches is derived at that time.</p>
</li>
<li><p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.compositeformat">Text.CompositeFormat</a> is a new type in .NET 8 useful for optimizing format strings that aren't known at compile time (such as format strings loaded from a resource file). While some extra time is spent upfront to perform tasks like parsing the string, it saves the work from being done each time the format string is used.</p>
<pre><code class="language-csharp">private static readonly CompositeFormat range = CompositeFormat.Parse(Load());
//////////
static string GetMessage(int min, int max) =&gt;
    string.Format(CultureInfo.InvariantCulture, range, min, max);
</code></pre>
</li>
<li><p>In .NET 8, two new types are introduced to implement the fast  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.hashing.xxhash3">XxHash3</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.io.hashing.xxhash128">XxHash128</a> hash algorithms.</p>
</li>
</ul>
<hr />
<h2>Improvements in System.Numerics  and System.Runtime.Intrinsics 🔥</h2>
<p>There are several enhancements made to the  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics">System.Numerics</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics">System.Runtime.Intrinsics</a>  namespaces. These improvements include better  hardware acceleration for <a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector256-1">Vector256</a>, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix3x2">Matrix3x2</a>, and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix4x4">Matrix4x4</a>  in .NET 8.</p>
<p><a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector256-1">Vector256</a> was redesigned to utilize <code>2x Vector128&lt;T&gt;</code> operations internally to achieve partial acceleration of certain  functions on <code>Arm64</code> processors where <code>Vector128.IsHardwareAccelerated == true</code> but <code>Vector256.IsHardwareAccelerated == false</code>. The introduction of  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector512-1">Vector512</a> is also included in .NET 8.</p>
<p>Additionally, the  <code>ConstExpected</code> attribute has been added to hardware intrinsic to alert  users when a non-constant value might cause unexpected performance  issues.</p>
<p>Lastly, the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.ifloatingpointieee754-1.lerp#system-numerics-ifloatingpointieee754-1-lerp(-0-0-0)">Lerp(TSelf, TSelf, TSelf)</a> API has been added to  <a href="https://learn.microsoft.com/en-us/dotnet/api/system.numerics.ifloatingpointieee754-1">IFloatingPointIeee754</a>, enabling the efficient and accurate linear interpolation of two values in <code>float</code>(<a href="https://learn.microsoft.com/en-us/dotnet/api/system.single">Single</a>), <code>double</code> (<a href="https://learn.microsoft.com/en-us/dotnet/api/system.double">Double</a>), and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.half">Half</a>.</p>
<hr />
<h2>New Data Validation Attributes 🛡️</h2>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations">DataAnnotations</a> namespace, aimed specifically for  validation in cloud-native services. The existing <code>DataAnnotations</code> validators are primarily used for validating user data, like form fields. However, the new attributes are meant to validate data, not entered by users, like <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/options#options-validation">configuration options</a>. Apart from the new attributes, the <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute">RangeAttribute</a> and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.requiredattribute">RequiredAttribute</a> types also received new properties.</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.requiredattribute.disallowalldefaultvalues#system-componentmodel-dataannotations-requiredattribute-disallowalldefaultvalues">RequiredAttribute.DisallowAllDefaultValues</a>: The attribute forces that structs for inequality with their default values.</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute.minimumisexclusive#system-componentmodel-dataannotations-rangeattribute-minimumisexclusive">RangeAttribute.MinimumIsExclusive</a> &amp; <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute.maximumisexclusive#system-componentmodel-dataannotations-rangeattribute-maximumisexclusive">RangeAttribute.MaximumIsExclusive</a>: Specifies whether the allowable range includes its boundaries or not.</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.lengthattribute">DataAnnotations.LengthAttribute</a>: Specifies the lower and upper limits for strings or collections using the <code>Length</code> attribute. For instance, the <code>[Length(5, 100)]</code> attribute specifies that a collection must have at least 5 elements and at most 100 elements.</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.base64stringattribute">DataAnnotations.Base64StringAttribute</a>: Validates a valid <code>Base64</code> format.</li>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.allowedvaluesattribute">DataAnnotations.AllowedValuesAttribute</a> &amp; <a href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.deniedvaluesattribute">DataAnnotations.DeniedValuesAttribute</a>: Specifies accepted allow lists or not allowed deny lists. For instance: <code>[AllowedValues(&quot;red&quot;, &quot;green&quot;, &quot;blue&quot;)]</code> or <code>[DeniedValues(&quot;yellow&quot;, &quot;purple&quot;)]</code>.</li>
</ul>
<hr />
<h2>Function Pointers Introspection Support ↩️</h2>
<p><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/unsafe-code#function-pointers">Function pointers</a> were released with .NET 5. There was no support for reflection at that time. As a result, using <code>typeof</code> or reflection on a function pointer, such as <code>typeof(delegate*&lt;void&gt;())</code> or <code>FieldInfo.FieldType</code>, respectively, would return an <a href="https://learn.microsoft.com/en-us/dotnet/api/system.intptr">IntPtr</a>. However, in .NET 8, a <a href="https://learn.microsoft.com/en-us/dotnet/api/system.type">System.Type</a> object is returned instead, providing access to function pointer  metadata, such as calling conventions, return type, and parameters. This functionality is implemented only in the <code>CoreCLR</code> runtime and <a href="https://learn.microsoft.com/en-us/dotnet/api/system.reflection.metadataloadcontext">MetadataLoadContext</a>.</p>
<hr />
<h2>Native AOT 🏭</h2>
<p>The <a href="https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/">publishing as native AOT</a> was initially introduced in .NET 7, the option to publish an application as native AOT enables the creation of a self-contained version of the app that does not require a separate runtime, bundling everything into a single file.</p>
<p>In .NET 8, the support for native AOT now encompasses the <code>x64</code> and <code>Arm64</code> architectures on macOS. Moreover, native AOT applications on Linux are now up to 50% smaller in size. Here's the table, illustrates the size of a minimal app published with native AOT, containing the entire .NET runtime:</p>
<ul>
<li><strong>Linux x64</strong> (with <code>-p:StripSymbols=true</code>)
<ul>
<li>.NET 7 ➡ 3.76MB</li>
<li>.NET 8 ➡ 1.84 MB</li>
</ul>
</li>
<li><strong>Windows x64</strong>
<ul>
<li>.NET 7 ➡ 2.85 MB</li>
<li>.NET 8 ➡ 1.77 MB</li>
</ul>
</li>
</ul>
<hr />
<h2>Code Generation Improvements 📃</h2>
<p>.NET 8 includes enhancements to code generation and just-in-time (<em>JIT</em>) compilation:</p>
<ul>
<li>JIT throughput improvements</li>
<li>Arm64 performance improvements</li>
<li>Profile-guided optimization (PGO) improvements</li>
<li>Support for AVX-512 ISA extensions</li>
<li>SIMD improvements</li>
<li>Cloud-native improvements</li>
<li>Loop and general optimizations</li>
</ul>
<hr />
<h2>.NET 8 DevOps Improvements 📦</h2>
<h3>NET Container Image Changes</h3>
<p>There are some changes with .NET 8 on image containers. First, <a href="https://wiki.debian.org/DebianBookworm">Debian 12</a> is the <strong>default Linux distribution</strong> in the container images.</p>
<p>Secondly, the images include a <code>non-root</code> user to make the images <code>non-root</code> capable. To run as <code>non-root</code>, add the line <code>USER app</code> at the end of your <code>Dockerfile</code>.</p>
<p>Besides, the <strong>default port has also changed</strong> from <code>80</code> to <code>8080</code> and a <strong>new environment variable</strong> <code>ASPNETCORE_HTTP_PORTS</code> is available to change ports easily.</p>
<p>Also, the format for the <code>ASPNETCORE_HTTP_PORTS</code> variable is easier compared to the format required by <code>ASPNETCORE_URLS</code>, and it accepts a list of ports. If you change the port back to <code>80</code> using one of these variables, it won’t be possible to run as <code>non-root</code>.</p>
<p>Finally, .NET 8 is now supported on <strong>Chiseled Ubuntu</strong> images, available at the [Ubuntu/DotNet-deps Docker Hub](Ubuntu/DotNet-deps Docker Hub). Chiseled images are  designed to have a smaller attack surface as they are stripped down to  be ultra-compact, and do not include a package manager or shell.  Chiseled images are non-root, making them ideal for developers looking for the benefits of appliance-style computing. These  images are regularly published to the <a href="https://mcr.microsoft.com/product/dotnet/nightly/aspnet/tags">.NET nightly artifact registry</a> for easy access.</p>
<h3>Building Your .NET on Linux</h3>
<p>Previously, building .NET from source in earlier versions required  creating a <code>source tarball</code> from the corresponding release commit in the [dotnet/installer repository](dotnet/installer repository). However, in .NET 8, this step is no longer necessary as the <a href="https://github.com/dotnet/dotnet">dotnet/dotnet repository</a>  allows building .NET directly on Linux using  <a href="https://github.com/dotnet/source-build">dotnet/source-build</a> to create runtimes, tools, and SDKs. Red Hat and Canonical also use this build for .NET. Building in a container is the easiest approach for most people since the <code>dotnet-buildtools/prereqs</code> container images have all the necessary dependencies. <a href="">The build instructions</a> provide more information.</p>
<h3>Minimum support baselines for Linux</h3>
<p>The support requirements for Linux have been updated for .NET 8, with changes to the minimum support baselines:</p>
<ol>
<li>All architectures will target Ubuntu 16.04 for building .NET, which is important for setting the minimum required version of <code>glibc</code> for .NET 8. Versions of Ubuntu earlier than 16.04, such as 14.04, will not even allow .NET 8 to start.</li>
<li><strong>Red Hat Enterprise Linux 7 is no longer supported</strong> with .NET 8.  Only supporting RHEL 8 and later.</li>
</ol>
<p>For further details, please refer to the <a href="https://github.com/dotnet/core/blob/main/linux-support.md#red-hat-enterprise-linux-family-support">support for Red Hat Enterprise Linux Family</a> page.</p>
<hr />
<p>Become a pioneer and try the new features of .NET 8 now.
Adapt it to your project or start a new .NET 8 project.
<a href="https://dotnet.microsoft.com/next">Claim your copy of .NET 8</a> today 🏎️ !</p>
<p>〰️〰️〰️</p>
<p>Happy Coding ⌨️</p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻 ABP Framework Core Team Member
Follow me for the latest news about .NET and software development:
📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a>
📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a>
📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a>
📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/3a0a327e-f07f-cedd-5816-b2253ea4a05c" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/3a0a327e-f07f-cedd-5816-b2253ea4a05c" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/inheritance-strategies-in-entity-framework-core-7-hg82tp4h</guid>
      <link>https://abp.io/community/posts/inheritance-strategies-in-entity-framework-core-7-hg82tp4h</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>entity-framework-core</category>
      <category>dotnet7</category>
      <category>dotnet</category>
      <title>Inheritance Strategies in Entity Framework Core 7</title>
      <description>In this article, I'll show you all the object inheritance mapping strategies in Entity Framework Core, especially the new one: TPC Inheritance Mapping, which is introduced with EF Core 7.</description>
      <pubDate>Fri, 25 Nov 2022 18:57:40 Z</pubDate>
      <a10:updated>2026-03-02T14:40:53Z</a10:updated>
      <content:encoded><![CDATA[<h1>Inheritance Strategies in Entity Framework Core 7</h1>
<p>In this article, I'll show you all the object mapping strategies of EF Core and especially the new one: <strong>TPC Inheritance Mapping</strong>.  TPC mapping is the new feature introduced with Entity Framework Core 7. It's called Table Per Concrete type inheritance mapping. I'll explain the EF Core's inheritance mapping strategies with how the inherited entity and the specific information are saved into a relational database. I'll also explain which strategy is best for your case.</p>
<p>By default, EF Core maps an inheritance hierarchy of .NET types to a single database table. And it's called TPH (table-per-hierarchy) mapping.</p>
<p>In the previous versions EF Core , Table Per Hierarchy (TPH) or Table Per Type (TPT) were supported. And now TPC came!</p>
<p>To explain in a more clear way, I'll use the following entity model.
<code>Car</code>, <code>Bus</code> and <code>Motorcylce</code> are inherited from the <code>Vehicle</code> object.</p>
<pre><code class="language-csharp">public abstract class Vehicle
{
    public int Id { get; set; }
    public string VehicleModel { get; set; }
}

//////////////////////////////////////

public class Car : Vehicle
{
    public string Segment { get; set; }
}

//////////////////////////////////////

public class Bus : Vehicle
{
    public int? SeatCount { get; set; }
}

//////////////////////////////////////

public class Motorcycle : Vehicle
{
    public int CylinderCount { get; set; }
}
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2022-11-25-EFCore-Mapping-Strategies/inheritance.png" alt="inheritance" /></p>
<p>Here's the list of available strategies to map <code>Car</code>, <code>Bus</code> and <code>Motorcylce</code>:</p>
<h2>TPH (Table Per Hierarchy)</h2>
<p>TPH maps an inheritance hierarchy of .NET types to <strong>a single database table</strong>. So a single table is created for all types. This is the default behavior of EF Core. If you explicitly want to use this strategy, you can write <code>UseTphMappingStrategy()</code> to the root entity in the <code>OnModelCreating()</code> method in the <code>DbContext</code> class.  As you see from the following table, it adds an extra column, <code>Discriminator</code> to separate the <code>Car</code>, <code>Bus</code> and <code>Motorcycle</code>. This way of persistence is an unnormalized form.</p>
<pre><code class="language-sql">CREATE TABLE [Vehicles] (
    [Id] int NOT NULL IDENTITY,   
    [Discriminator] nvarchar(max) NOT NULL,  -- &quot;Car&quot;, &quot;Bus&quot;, &quot;Motorcylce&quot;
    [VehicleModel] nvarchar(max) NOT NULL,
    [Segment] nvarchar(max) NULL,
    [SeatCount] int NULL,
    [CylinderCount] int NOT NULL
);
</code></pre>
<h2>TPT (Table per Type)</h2>
<p>With the TPT strategy, a different table is created for every type. The table itself is used to determine the type of the object saved, and each table contains only columns for the properties of that type. The data is saved in multiple tables, and this way of persistence is normalized form.</p>
<pre><code class="language-sql">CREATE TABLE [Vehicles] (
    [Id] int NOT NULL IDENTITY,
    [VehicleModel] nvarchar(max) NOT NULL
); 

CREATE TABLE [Car] (
    [Id] int NOT NULL,
    [Segment] nvarchar(max) NULL
);

CREATE TABLE [Bus] (
    [Id] int NOT NULL,
    [SeatCount] int NULL,
);

CREATE TABLE [Motorcycle] (
    [Id] int NOT NULL,
    [CylinderCount] int NOT NULL
);
</code></pre>
<p>If you explicitly want to use this strategy, you can write <code>UseTptMappingStrategy()</code> to the root entity in the <code>OnModelCreating()</code> method in the <code>DbContext</code> class.</p>
<h2>TPC (Table Per Concrete type)</h2>
<p>It's the new strategy that has been introduced with EF Core 7. In this way, a different table is created for each concrete type. While in the TPT, the table itself indicates the type of the object saved, in TPC, each table contains columns for every property in the concrete type <em>and its base types</em>. As you see from the following tables, no <code>Vehicles</code> table is being created. The <code>VehicleModel</code> field is common in each table.</p>
<pre><code class="language-sql">CREATE TABLE [Car] (
    [Id] int NOT NULL DEFAULT (NEXT VALUE FOR [VehicleIds]),
    [VehicleModel] nvarchar(max) NOT NULL, -- common field for each type
    [Segment] nvarchar(max) NULL
);

CREATE TABLE [Bus] (
    [Id] int NOT NULL DEFAULT (NEXT VALUE FOR [VehicleIds]),
    [VehicleModel] nvarchar(max) NOT NULL, -- common field for each type
    [SeatCount] int NULL 
);

CREATE TABLE [Motorcycle] (
    [Id] int NOT NULL DEFAULT (NEXT VALUE FOR [VehicleIds]),
    [VehicleModel] nvarchar(max) NOT NULL, -- common field for each type
    [CylinderCount] int NOT NULL
);
</code></pre>
<p>This strategy maps each .NET type to <strong>a different database table</strong>. You write <code>UseTpcMappingStrategy()</code> to the root entity in the root entity in the <code>OnModelCreating()</code> method in the <code>DbContext</code> class.</p>
<h2>How do you choose which mapping type is best for you?</h2>
<ul>
<li><p><strong>TPH:</strong> In most cases, the TPH mapping is a good choice which is the default one. This way, the table columns increase because all the properties are saved in the same table, but it's easy to query in a single table.</p>
</li>
<li><p><strong>TPT</strong>  In this form, data is persisted in a normalized form. For this reason, you can choose TPT, but generally, it's not being used. But the disadvantage is when you filter by <code>VehicleModel</code> column, it must join <code>Vehicles</code>, <code>Bus</code>, <code>Car</code>, <code>Motorcycle</code> tables. So it's not a feasible fetching way.</p>
</li>
<li><p><strong>TPC:</strong> This new strategy is similar to TPT but resolves some of the TPT problems. Because it stores the data in its own table, it doesn't divide across multiple tables. This option can be chosen when the mapped hierarchy is large and has many concrete types, each with many properties.</p>
</li>
</ul>
<p>For example, if <code>Car</code>, <code>Bus</code>, or <code>Motorcycle</code> have 20 properties for each type, then it's better to store them in a separate table, so we should use TPC. But if these entities have only 3-5 properties, then TPH is the way to go.</p>
<blockquote>
<h3>Jeremy Likness says;</h3>
<ul>
<li>If your code mostly queries entities of a single leaf type, then use TPC because the storage requirements are smaller since there are no null columns and no discriminator no index is ever needed on the discriminator column, which would slow down updates and possibly also queries. An index may not be needed when using TPH either, but that depends on various factors. If your code mostly queries for entities of many types, such as writing queries against the base type, lean towards TPH. If your database system supports it (for example SQL Server), then consider using sparse columns for columns that will be rarely populated. Use TPT only if constrained to do so by external factors.</li>
</ul>
</blockquote>
<p><em>References:</em></p>
<ul>
<li>https://devblogs.microsoft.com/dotnet/announcing-ef7-preview5/#primary-keys</li>
</ul>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/212dbe4a-9179-0d65-5e21-3a07c253e4f6" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/212dbe4a-9179-0d65-5e21-3a07c253e4f6" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/upgrade-your-existing-projects-to-.net7-nmx6vm9m</guid>
      <link>https://abp.io/community/posts/upgrade-your-existing-projects-to-.net7-nmx6vm9m</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>update</category>
      <category>dotnet7</category>
      <category>dotnet</category>
      <title>Upgrade Your Existing Projects to .NET7</title>
      <description>In this article, I will share our experiences while upgrading to .NET 7.</description>
      <pubDate>Thu, 27 Oct 2022 16:05:21 Z</pubDate>
      <a10:updated>2026-03-02T16:36:21Z</a10:updated>
      <content:encoded><![CDATA[<h1>Upgrade Your Existing  Projects to .NET7</h1>
<p>A new .NET version has come. As open-source contributors, we are tracking the latest libraries and adopting them to our existing projects. In this sense, we completed our .NET 7 upgrade in our repositories for ABP Framework and ABP Commercial. In this article, I'll share the experiences we faced while upgrading to the new .NET version 👉  .NET 7.</p>
<p>When I wrote this article, the latest .NET version was <code>7.0.0-rc.2</code>. So some of the version statements I wrote below must be changed due to the stable version release.</p>
<p><strong>To see the latest and greatest stuff, let's see how to upgrade our existing projects to .NET 7!</strong></p>
<h2>Install .NET7 SDK</h2>
<p>If you are on your development computer, then you need to install the .NET7 SDK <code>7.x.x</code>. For the production servers, you need to install the .NET 7 runtime. Download link for the .NET7 SDK and runtime is:</p>
<ul>
<li>https://dotnet.microsoft.com/en-us/download/dotnet/7.0</li>
</ul>
<h2>Update Your *.csproj Files</h2>
<p>First, you need to update all your <code>*.csproj</code> files to support .NET7. Find and replace all your <code>&lt;TargetFramework&gt;*&lt;/TargetFramework&gt;</code> in the <code>*.csproj</code> files to support .NET 7:</p>
<pre><code class="language-xml">&lt;TargetFramework&gt;net7.0&lt;/TargetFramework&gt;
</code></pre>
<p>We already did this in ABP Framework, see this commit as an example <a href="https://github.com/abpframework/abp/blob/dev/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj#L4">github.com/abpframework/abp/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.csproj</a>.</p>
<h3>Microsoft Package Updates</h3>
<p>You must be using Microsoft packages as well; then you need to update them to the latest .NET 7 version.
At the time, I wrote this article, the latest version was <code>7.0.0-rc.2.22476.2</code>, so I'll update them to this version including minor version changes.</p>
<p>Here's the list of all package reference updates I did:</p>
<pre><code class="language-xml">&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Authentication.JwtBearer&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Authentication.OpenIdConnect&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components.Authorization&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components.Web&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components.WebAssembly&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components.WebAssembly.Authentication&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Components.WebAssembly.DevServer&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.DataProtection.StackExchangeRedis&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Mvc.NewtonsoftJson&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.AspNetCore.TestHost&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;

&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore.Design&quot; Version=&quot;7.0.0-rc.2.*&quot;&gt;
&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore.Proxies&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore.Sqlite&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore.SqlServer&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.EntityFrameworkCore.Tools&quot; Version=&quot;7.0.0-rc.2.*&quot;&gt;
    
&lt;PackageReference Include=&quot;Microsoft.Extensions.Caching.Memory&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Caching.StackExchangeRedis&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Configuration.UserSecrets&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.DependencyInjection&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.DependencyInjection.Abstractions&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.FileProviders.Composite&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.FileProviders.Embedded&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.FileSystemGlobbing&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Hosting&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Http&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Identity.Core&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Localization&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Extensions.Logging.Console&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
    
&lt;PackageReference Include=&quot;System.Text.Encoding.CodePages&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;System.Text.Encodings.Web&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;System.Text.Json&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt; 

&lt;PackageReference Include=&quot;Microsoft.VisualStudio.Web.CodeGeneration.Design&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;System.Collections.Immutable&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Bcl.AsyncInterfaces&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
&lt;PackageReference Include=&quot;Microsoft.Data.Sqlite&quot; Version=&quot;7.0.0-rc.2.*&quot; /&gt;
</code></pre>
<hr />
<h2>Entity Framework Core Updates</h2>
<p>If you use EF Core as your data access library, you should update your <code>dotnet-ef</code> CLI tool. Here's the terminal command to update it:</p>
<pre><code class="language-bash">dotnet tool update dotnet-ef --global --prerelease
</code></pre>
<p>We already did the the EF Core package reference update in the <em>Microsoft Package Updates</em> section.</p>
<h3>Breaking Change: OrderBy</h3>
<p>This release makes a breaking change in an EF Core query running behavior.  We faced this issue in some of our queries that were missing <code>OrderBy</code> statement. It throws an exception and does not run the query. Here's the explanation of a EF Core team member for this issue: <a href="https://github.com/dotnet/efcore/issues/21202#issuecomment-913206415">github.com/dotnet/efcore/issues/21202#issuecomment-913206415</a>.</p>
<p>The following exception is being thrown:</p>
<blockquote>
<p>InvalidOperationException: The query uses 'Skip' without specifying ordering and uses split query mode. This generates incorrect results. Either provide ordering or run query in single query mode using AsSingleQuery(). See https://go.microsoft.com/fwlink/?linkid=2196526 for more information</p>
</blockquote>
<p>If you don't want to add <code>OrderBy</code> statement to solve the issue, you can also use  <code>AsSingleQuery()</code>.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2022-10-27-Dotnet7-Upgrade/./as-single-query.jpg" alt="AsSingleQuery" /> </p>
<h3>EF Core - SQL Client Connection String Update</h3>
<p>With this version, the behavior of the SQL connection has been changed. There is a keyword in the SQL connection string called <code>TrustServerCertificate</code>. This keyword indicates whether the channel will be encrypted while bypassing walking the certificate chain to validate  trust.</p>
<blockquote>
<p>When <code>TrustServerCertificate</code> is set to <code>True</code>, the transport layer will use SSL to encrypt the channel and bypass walking the certificate chain to validate trust. If <code>TrustServerCertificate</code> is set to <code>true</code> and encryption is turned on, the encryption level specified on the server will be used even if <code>Encrypt</code> is set to <code>false</code>. The connection will fail otherwise.</p>
</blockquote>
<p>After the .NET7 update, it just started to throw the following exception:</p>
<blockquote>
<p>A connection was successfully established with the server, but then an error occurred during the login process.</p>
</blockquote>
<p>We fixed this problem by adding the <code>TrustServerCertificate=true</code> to your connection string. Here's an example connection string that supports,</p>
<pre><code class="language-sql">Server=localhost; Database=MyProjectName; Trusted_Connection=True; TrustServerCertificate=True
</code></pre>
<p>See our commit for this fix:</p>
<ul>
<li><a href="https://github.com/abpframework/abp/commit/96f17e67918eb87edd2baf876d4a7598281fe608">github.com/abpframework/abp/commit/96f17e67918eb87edd2baf876d4a7598281fe608</a></li>
</ul>
<p>Related docs:</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes#encrypt-true">learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-7.0/breaking-changes#encrypt-true</a></li>
<li><a href="https://stackoverflow.com/questions/34430550/a-connection-was-successfully-established-with-the-server-but-then-an-error-occ">stackoverflow.com/questions/34430550/a-connection-was-successfully-established-with-the-server-but-then-an-error-occ</a></li>
</ul>
<hr />
<h2>Blazor Update</h2>
<p>Ensure that you have updated your Blazor project's csproj to support .NET7:</p>
<pre><code class="language-xml">&lt;TargetFramework&gt;net7.0&lt;/TargetFramework&gt;
</code></pre>
<h3>Install Blazor Workloads</h3>
<h4>.NET Web Assembly build tools</h4>
<p>If you have a Blazor-WASM project, install the workloads by running the following in a command shell:</p>
<pre><code class="language-bash">dotnet workload install wasm-tools
</code></pre>
<p><strong>OR</strong>  you can update your workloads by running the following command in your Blazor project directory:</p>
<pre><code class="language-bash">dotnet workload restore
</code></pre>
<hr />
<h2>.NET MAUI Update</h2>
<p>Ensure that you have updated your Blazor project's csproj to support .NET7:</p>
<pre><code class="language-xml">&lt;TargetFrameworks&gt;net7.0-android;net7.0-ios;net7.0-maccatalyst&lt;/TargetFrameworks&gt;
&lt;TargetFrameworks Condition=&quot;$([MSBuild]::IsOSPlatform('windows'))&quot;&gt;$(TargetFrameworks);net7.0-windows10.0.19041.0&lt;/TargetFrameworks&gt;
</code></pre>
<h3>Install MAUI Workloads</h3>
<p>If you have .NET MAUI project, then you also need to update your <code>TargetFramework</code> as below:</p>
<p>If you have a .NET MAUI project, after installing the .NET 7 SDK, install the latest workloads with the following command:</p>
<pre><code class="language-bash">dotnet workload install maui
</code></pre>
<p><strong>OR</strong>  run the following command in your existing .NET MAUI project directory</p>
<pre><code class="language-bash">dotnet workload restore
</code></pre>
<p>Further information, check out https://github.com/dotnet/maui/wiki/.NET-7-and-.NET-MAUI</p>
<hr />
<h4>Dotnet Maui Check Tool</h4>
<p>Alternatively, there's a 3rd party tool for .NET MAUI to install the required workloads. This tool installs the missing SDK packs. You can reach the tool's repository at <a href="https://github.com/Redth/dotnet-maui-check">github.com/Redth/dotnet-maui-check</a>.</p>
<p>Installation:</p>
<pre><code class="language-bash">dotnet tool install -g Redth.Net.Maui.Check
</code></pre>
<p>Run:</p>
<pre><code class="language-bash">maui-check
</code></pre>
<hr />
<h2>Docker Image Update</h2>
<p>If you are using Docker to automate the deployment of applications, you also need to update your images. We were using <code>aspnet:6.0.0-bullseye-slim</code> base and after the .NET 7 update, we started using <code>aspnet:7.0-bullseye-slim</code> in our Docker files.</p>
<pre><code>FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim AS base
</code></pre>
<p>For this update, you can check out the following commit as an example:</p>
<ul>
<li><a href="https://github.com/abpframework/abp/commit/2d07b9bd00152bef4658c48ff9b2cbee5788d308">github.com/abpframework/abp/commit/2d07b9bd00152bef4658c48ff9b2cbee5788d308</a></li>
</ul>
<h2>ABP Framework .NET 7 Update</h2>
<p>In <a href="https://github.com/abpframework/abp">ABP Framework repository</a>, we updated all our dependencies from .NET 6 to .NET 7.
Not all the changes are here, but you can check out the following PR of the .NET 7 update:</p>
<ul>
<li><a href="https://github.com/abpframework/abp/pull/13626/files">github.com/abpframework/abp/pull/13626/files</a></li>
</ul>
<p>〰️〰️〰️</p>
<p>Happy Coding 🤗</p>
<hr />
<blockquote>
<p>I'm Alper Ebicoglu 🧑🏽‍💻 ABP Framework Core Team Member
Follow me for the latest news about .NET and software development:
📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a></p>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a></p>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a></p>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a>https://medium.com/@alperonline)\</p>
</blockquote>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/f9bffe6f-9f83-d93b-8905-3a072c5db759" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/f9bffe6f-9f83-d93b-8905-3a072c5db759" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/videos/build-a-simple-todo-app-with-abp-framework-in-15-minutes-kk4wo7i9</guid>
      <link>https://abp.io/community/videos/build-a-simple-todo-app-with-abp-framework-in-15-minutes-kk4wo7i9</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>to-do-app</category>
      <category>app-template</category>
      <title>Build a simple TODO app with ABP Framework in 15 minutes</title>
      <description>In this tutorial, we'll build a very simple application to warm up for the ABP Framework.  🚀 In 15 minutes, you'll create a TODO application on top of ABP Framework that has list, delete, and create features.</description>
      <pubDate>Thu, 21 Jul 2022 14:31:22 Z</pubDate>
      <a10:updated>2026-02-25T04:08:17Z</a10:updated>
      <content:encoded><![CDATA[In this tutorial, we'll build a very simple application to warm up for the ABP Framework.  🚀 In 15 minutes, you'll create a TODO application on top of ABP Framework that has list, delete, and create features. <br \> <a href="https://www.youtube.com/watch?v=Qb-hsf1ID7k" rel="nofollow noopener noreferrer" title="Go to the Video">Go to the Video</a>]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/21e89a94-e325-8fc5-cb21-3a0533587529" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/21e89a94-e325-8fc5-cb21-3a0533587529" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/all-about-.net-maui-gb4gkdg5</guid>
      <link>https://abp.io/community/posts/all-about-.net-maui-gb4gkdg5</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>maui</category>
      <title>All about .NET MAUI</title>
      <description>In this article, I’ll tell about .NET MAUI the new generation of Xamarin. This article is based on my talk at https://www.youtube.com/watch?v=qBOzRqzq7xA</description>
      <pubDate>Wed, 15 Jun 2022 13:42:20 Z</pubDate>
      <a10:updated>2026-02-19T11:02:01Z</a10:updated>
      <content:encoded><![CDATA[In this article, I’ll tell about .NET MAUI the new generation of Xamarin. This article is based on my talk at https://www.youtube.com/watch?v=qBOzRqzq7xA<br \><a href="https://medium.com/volosoft/all-about-net-maui-5a1e774803ac" rel="nofollow noopener noreferrer" title="Go to the Post">Go to the Post</a>]]></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/create-a-windows-service-with-abp-framework-hop4dtra</guid>
      <link>https://abp.io/community/posts/create-a-windows-service-with-abp-framework-hop4dtra</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>windows-service</category>
      <title>Create a Windows Service with ABP Framework</title>
      <description>I will show you how to create a Windows Service with ABP Framework. The service will access to the database with ABP repositories.</description>
      <pubDate>Mon, 04 Oct 2021 14:56:21 Z</pubDate>
      <a10:updated>2026-03-02T18:18:28Z</a10:updated>
      <content:encoded><![CDATA[<h1>ABP Windows Service</h1>
<p>This is a simple <strong>Windows Service</strong> built on the <strong>ABP Framework (open source)</strong> (.NET5 and ABP 4.4.2). The Windows Service uses a local SQL database.</p>
<p>Project Structure:</p>
<ul>
<li><strong>AbpWindowsService</strong>: This is the Windows Service. You will install this service as Windows Service.</li>
<li><strong>AbpWindowsService.DbMigrator</strong>: You can create your database and update it with DbMigrator.</li>
<li><strong>AbpWindowsService.Domain</strong>: Your domain objects like your entities are in this project.</li>
<li><strong>AbpWindowsService.Domain.Shared</strong>: Shared objects like your entity consts, enums are in this project.</li>
<li><strong>AbpWindowsService.EntityFrameworkCore</strong>: The EFCore referenced project has DbContext and Migrations.</li>
</ul>
<p>For more information see https://docs.abp.io/en/commercial/latest/startup-templates/application/solution-structure</p>
<h2>How to install and run?</h2>
<p>Clone <a href="https://github.com/ebicoglu/AbpWindowsService">this repository</a> to your disk.</p>
<p>Build the solution.</p>
<p>Run the <code>DbMigrator</code> project to create the database.</p>
<p>Start a command prompt as an administrator and run <a href="https://github.com/ebicoglu/AbpWindowsService/blob/main/install-service.bat">install-service.bat</a>. This will install the Window Service. Your service name will be <code>AbpWindowsService</code>. You can change the service name <a href="https://github.com/ebicoglu/AbpWindowsService/blob/main/src/AbpWindowsService/Program.cs#L52">from this code line</a>.</p>
<p><img src="https://user-images.githubusercontent.com/9526587/132733812-a042f301-d766-4e6e-95c5-5a80aa58deb2.png" alt="" /> </p>
<p>The database connection string is</p>
<pre><code class="language-bash">Server=(LocalDb)\\MSSQLLocalDB;Database=MyDatabase;Trusted_Connection=True
</code></pre>
<p>The <code>Trusted_Connection</code> allows connecting the database with your active Windows user account. But the default user account for Windows Services is a local <code>System</code> user. Therefore you need to set your active account to the service. To do this; Open the <em>Services</em> window by running <code>C:\Windows\System32\services.msc</code> and right-click your service, go to &quot;<em>Properties</em>&quot;. Go to the &quot;<em>LogOn</em>&quot; tab, choose &quot;<em>This Account</em>&quot; and write your <em>username &amp; password</em>. To learn your logon username, start a command prompt and write <code>whoami</code>.</p>
<p><img src="https://user-images.githubusercontent.com/9526587/132734210-d6982cc9-fda5-4dd4-b49f-eb59401e9445.png" alt="" /> </p>
<p>Start the service. And that's it!</p>
<p>To check if it's working, open the following logfile</p>
<pre><code class="language-shell"> src\AbpWindowsService\bin\Debug\net5.0\win-x64\Logs\Log.txt
</code></pre>
<p>I already added 4 database records (books) with <a href="https://github.com/ebicoglu/AbpWindowsService/blob/main/src/AbpWindowsService.Domain/IdentityServer/IdentityServerDataSeedContributor.cs#L69">the data seeder</a>, so you'll see the following lines in the logs when the service starts. These are the records fetched from the <code>Books</code> table.</p>
<pre><code>[INF] *** Book name: George Orwell 1984
[INF] *** Book name: Lord of the Flies
[INF] *** Book name: Harry Potter
[INF] *** Book name: The Great Gatsby
</code></pre>
<h2>How to uninstall?</h2>
<p>Start a command prompt as an administrator and run <a href="https://github.com/ebicoglu/AbpWindowsService/blob/main/uninstall-service.bat">uninstall-service.bat</a>. This will uninstall the Window Service. This batch runs the following operations:</p>
<ul>
<li>Stops the service if it's running</li>
<li>Closes <code>mmc.exe</code> if it's open. (<em>because the service cannot be uninstalled if this window is open</em>)</li>
<li>Removes service with <code>sc delete</code> command</li>
</ul>
<p><img src="https://user-images.githubusercontent.com/9526587/132734406-a1204e90-d66d-491e-b294-d3fea95a852b.png" alt="" /> </p>
<h2>Creating your own Windows Service in .NET CORE using ABP Framework</h2>
<h3>Create an ABP console application</h3>
<p>To create your own Windows Service, you can start with creating an ABP console application with the following command:</p>
<pre><code class="language-bash">abp new AbpWindowsService -t console -csf
</code></pre>
<h3>Add Windows Service middleware</h3>
<p>Add the <a href="https://www.nuget.org/packages/Microsoft.Extensions.Hosting.WindowsServices">Microsoft.Extensions.Hosting.WindowsServices</a> package to your console application by adding the following line to the csproj:</p>
<pre><code class="language-xml">&lt;PackageReference Include=&quot;Microsoft.Extensions.Hosting.WindowsServices&quot; Version=&quot;5.0.1&quot; /&gt;
</code></pre>
<p>Open the <strong>Program.cs</strong> and add the <code>UseWindowsService()</code> to <code>CreateHostBuilder</code> method. You can also set a service name to be shown in the services window.</p>
<pre><code class="language-c#">  Host.CreateDefaultBuilder(args)
  .UseAutofac()
  .UseSerilog()
  .UseWindowsService(x =&gt; x.ServiceName = &quot;AbpWindowsService&quot;) //// add this line /////
  .ConfigureAppConfiguration((context, config) =&gt;
  {
      //setup your additional configuration sources
  })
  .ConfigureServices((hostContext, services) =&gt;
  {
  services.AddApplication&lt;AbpWindowsServiceModule&gt;();
  });
</code></pre>
<p><code>UseWindowsService</code> makes 3 things:</p>
<ul>
<li>Sets the host lifetime to <em>WindowsServiceLifetime</em></li>
<li>Sets the Content Root</li>
<li>Enables logging to the event log with the application name as the default source name</li>
</ul>
<h3>Set log file path</h3>
<p>By default, Windows Service runs as a local System account and Serilog will write the logs under <code>C:\Windows\System32</code>. To overcome this, you can set the log file as the static path. The below code lets Serilog write to the Logs folder under your Windows Service installation directory.</p>
<pre><code>Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override(&quot;Microsoft&quot;, LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Async(c =&gt; c.File(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), &quot;Logs/Log.txt&quot;)))
.CreateLogger();
</code></pre>
<h3>Write your business logic</h3>
<p>In your Windows Service, there is an ABP module class <code>AbpWindowsServiceModule.cs</code>. This class adds the hosted service <code>*HostedService.cs</code>. Hosted service is an implementation of <code>IHostedService</code>. It has <code>StartAsync()</code> and <code>StopAsync()</code> methods. <code>StartAsync</code> the method will run when you start your Windows Service and <code>StopAsync</code> will run when you stop your Windows Service. The application will not end unless you stop it. You can create a domain service from <code>IDomainService</code>. And write your code in this domain service. Call your method inside the Hosted Service <code>StartAsync</code> method. Dependency Injection will work without any problem as long as you implement your classes from <code>ITransientDependency</code> or <code>ISingletonDependency</code>.</p>
<h3>Accessing the database</h3>
<p>To access your database and repositories you can move your Windows Service into your main ABP Web Application solution. To do this, copy the service project to the src folder of your main web solution. Add project reference of *<strong>.EntityFrameworkCore</strong> project to your Windows Service as shown below:</p>
<pre><code class="language-xml">&lt;ProjectReference Include=&quot;..\AbpWindowsService.EntityFrameworkCore\AbpWindowsService.EntityFrameworkCore.csproj&quot; /&gt;
</code></pre>
<p>Add the <code>DependsOn</code> attribute of <code>EntityFramework</code> module to your Windows Service as shown below:</p>
<pre><code class="language-csharp"> [DependsOn(
    typeof(AbpAutofacModule),
    typeof(AbpWindowsServiceEntityFrameworkCoreModule)) /// added this line ///
 ]
 public class AbpWindowsServiceModule : AbpModule
 {
      //....
 }
</code></pre>
<p>Now you can inject your repositories into your domain service.</p>
<p>Don't forget to add the database connection string to the <a href="https://github.com/ebicoglu/AbpWindowsService/blob/main/src/AbpWindowsService/appsettings.json">appsettings.json</a> of your Windows Service.</p>
<pre><code class="language-xml">{
  &quot;ConnectionStrings&quot;: {
    &quot;Default&quot;: &quot;Server=(LocalDb)\\MSSQLLocalDB;Database=MyDatabase;Trusted_Connection=True&quot;
  }
}
</code></pre>
<p>Note that we are using <code>Trusted_Connection=True</code> which means, Windows Authentication (the active Windows user) will be used.</p>
<blockquote>
<p><code>Trusted_Connection=True</code> will cause a small problem! The default user of a Windows Service is local System account. Therefore you cannot connect your database with the System account. To solve this, apply the <strong>5th</strong> step of <strong>How to install and run?</strong> section in this document. Alternative way; You can create a user in your database and use the UserId-Password credential in the connection string.</p>
</blockquote>
<p>And you are ready to install your new service! See the <a href="#how-to-install-and-run">How to install and run?</a> section to install your new service.</p>
<p><a href="https://github.com/ebicoglu/AbpWindowsService">Click here to download the sample project</a></p>
<p>And happy coding!</p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/a0f38cb7-9400-9353-2179-39ff5dfb1a0c" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/a0f38cb7-9400-9353-2179-39ff5dfb1a0c" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/realtime-notifications-via-signalr-in-abp-project-tsp2uqd3</guid>
      <link>https://abp.io/community/posts/realtime-notifications-via-signalr-in-abp-project-tsp2uqd3</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>signalr</category>
      <category>real-time-notifications</category>
      <title>Real-time Notifications via SignalR in ABP Project</title>
      <description>We will implement a basic SignalR engine for real-time notifications in an ABP project. Thus, we will enable the server-side code to instantly send content to clients without refreshing the page.</description>
      <pubDate>Mon, 15 Mar 2021 09:09:41 Z</pubDate>
      <a10:updated>2026-03-02T17:40:42Z</a10:updated>
      <content:encoded><![CDATA[<h1>Send Real-time Notifications via SignalR in ABP Project</h1>
<p>SignalR is an open source library that adds real-time operation functionality to applications. Real-time web functionality enables server-side code to instantly send content to clients without refreshing the page. I'll show you how to add SignalR and use it to send notifications from backend. I'll implement this functionality in MVC template of ABP Framework.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/signalr-architecture.png" alt="signalr-architecture" /></p>
<h2>Implement Backend</h2>
<h3>Create Notification Hub</h3>
<p>Create a new folder named <code>SignalR</code> in your root directory of your Web project.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/signalr-folder.jpg" alt="SignalR Folder" /></p>
<p>Then add the following classes to the folder:</p>
<ol>
<li><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-inotificationclient-cs">INotificationClient.cs</a></li>
<li><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-uinotificationclient-cs">UiNotificationClient.cs</a></li>
<li><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-uinotificationhub-cs">UiNotificationHub.cs</a></li>
</ol>
<h3>Configure Module</h3>
<p>These 3 steps will be done in your web module class.</p>
<h4>1- Add SignalR</h4>
<p>Open <code>YourProjectWebModule.cs</code> class and add the following line to the <code>PreConfigureServices</code> method:</p>
<pre><code class="language-csharp"> context.Services.AddSignalR();
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/preconfigureservices.jpg" alt="PreConfigureServices" /></p>
<h4>2- Add Client Scripts</h4>
<p>2- In the <code>ConfigureServices</code> method of your web module add the following code to add the <code>signalr.js</code> and <code>notification-hub.js</code>. We'll add these packages in the next steps. If you are not using Lepton Theme you can add the files to <code>StandardBundles.Scripts.Global</code>.</p>
<pre><code class="language-csharp"> Configure&lt;AbpBundlingOptions&gt;(options =&gt;
  {
      options
          .ScriptBundles
          .Get(LeptonThemeBundles.Scripts.Global) //or -&gt; Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.Bundling.StandardBundles.Scripts.Global
          .AddFiles(&quot;/libs/signalr/signalr.js&quot;)
          .AddFiles(&quot;/Pages/notification-hub.js&quot;);
  });
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/add-script-bundles.jpg" alt="Script Bundles" /></p>
<h4>3- Add Hub Endpoint</h4>
<p>Add the following code to add the notification hub endpoint in <code>OnApplicationInitialization</code>  method:</p>
<pre><code class="language-csharp">app.UseEndpoints(endpoints =&gt;
{
   endpoints.MapHub&lt;UiNotificationHub&gt;(&quot;/notification-hub&quot;);
});
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/add-endpoint.jpg" alt="Add endpoint" /></p>
<h3>Implement Frontend</h3>
<p>We'll write the client-side code to be able to handle the SignalR response.</p>
<h4>1- Add Notification Hub</h4>
<p>Add the following JavaScript class into your <code>Pages</code> folder in your Web project. We already added this script to our global scripts.</p>
<p><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-notification-hub-js">notification-hub.js</a></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/notification-hub.jpg" alt="notification-hub.js" /></p>
<h4>2- Add SignalR NPM package</h4>
<p>Add <a href="https://www.npmjs.com/package/@microsoft/signalr">Microsoft.SignalR</a> JavaScript package to the <code>package.json</code> which is located in your root folder of the Web project. After you add it, run <code>yarn</code> command in your Web directory to be able to install this package.</p>
<p>You can install the latest version (3.1.13 will be old)</p>
<pre><code>  &quot;@microsoft/signalr&quot;: &quot;^3.1.13&quot;
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/signalr-package.jpg" alt="Add SignalR package" /></p>
<h4>3- Add resource Mapping</h4>
<p>We added SignalR to the <code>package.json</code> but it comes into your <code>node_modules</code> folder. We need to copy the related files to <code>wwwroot/libs</code> folder. To do this copy the content of the following file to your <code>abp.resourcemappings.js</code> file. It's in your root directory of Web folder. After you do this, go to your web directory and run <code>abp install-libs</code> command. By doing this, it'll copy the related files into your <code>wwwroot/libs</code> folder.</p>
<p><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-abp-resourcemapping-js"><code>abp.resourcemappings.js</code></a></p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/resource-mappings.jpg" alt="Resource mappings" /></p>
<h4>4- Usage</h4>
<p>We have completed the implementation part. Let's check if it's running...
We will show the current time which comes from server.
To do this replace the <code>Index.cshtml</code> and <code>Index.cshtml.cs</code> with the followings:</p>
<ul>
<li><p><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml">Index.cshtml</a></p>
</li>
<li><p><a href="https://gist.github.com/ebicoglu/f7dc22cca2d353f8bf7f68a03e3395b8#file-index-cshtml-cs">Index.cshtml.cs</a></p>
</li>
</ul>
<h4>5- See it in action</h4>
<p>Run your web project and in the Index page you'll Server Time will be updated every second. The time information comes from backend via SignalR.
This is a very basic usage of SignalR notification system.
You can implement your own SignalR notification system based on your requirements.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2021-03-12-Simple-SignalR-Notification/result.jpg" alt="Result" /></p>
]]></content:encoded>
      <media:thumbnail url="https://abp.io/api/posts/cover-picture-source/84f543a1-bb65-e7d7-491b-39fb4752c562" />
      <media:content url="https://abp.io/api/posts/cover-picture-source/84f543a1-bb65-e7d7-491b-39fb4752c562" medium="image" />
    </item>
    <item>
      <guid isPermaLink="true">https://abp.io/community/posts/abp-suite-how-to-add-the-user-entity-as-a-navigation-property-of-another-entity-furp75ex</guid>
      <link>https://abp.io/community/posts/abp-suite-how-to-add-the-user-entity-as-a-navigation-property-of-another-entity-furp75ex</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>abp-suite</category>
      <title>ABP Suite: How to Add the User Entity as a Navigation Property of Another Entity</title>
      <description>How to add a user navigation property to your new entity using the ABP Suite.</description>
      <pubDate>Mon, 31 Aug 2020 12:51:28 Z</pubDate>
      <a10:updated>2026-03-02T17:32:15Z</a10:updated>
      <content:encoded><![CDATA[<h1>ABP Suite: How to Add the User Entity as a Navigation Property of Another Entity</h1>
<h2>Introduction</h2>
<p><a href="https://commercial.abp.io/tools/suite">ABP Suite</a>, a part of the <a href="https://commercial.abp.io/">ABP Commercial</a>, is a productivity tool developed by the team behind the ABP Framework. The main functionality of the ABP Suite is to generate code for you.</p>
<p>In this post, I'll show you how to add the user entity as a navigation property in your new entity, by the help of the ABP Suite.</p>
<blockquote>
<p>In the sample project MVC UI is used, but the same steps are applicable to the Angular UI as well.</p>
</blockquote>
<h2>Code Generation</h2>
<h3>Create a New Entity</h3>
<p>Open the ABP Suite (<a href="https://docs.abp.io/en/commercial/latest/abp-suite/index">see how</a>). Create a new entity called <code>Note</code>, as an example entity.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/create-note-entity.jpg" alt="create-note-entity" /></p>
<p>Then add a string property called <code>Title</code>, as an example property.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/add-simple-property.jpg" alt="add-simple-property" /></p>
<h3>Create AppUserDto</h3>
<p><em>Note that, creating <code>AppUserDto</code> is not necessary after ABP v4.X</em></p>
<p>ABP Suite needs a DTO for the target entity (user, in this case) in order to define a navigation property.</p>
<p>To do this, create a new folder called &quot;Users&quot; in <code>*.Application.Contracts</code> then add a new class called <code>AppUserDto</code> inherited from <code>IdentityUserDto</code>.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/create-appuserdto.jpg" alt="create-appuserdto" /></p>
<p>We should define the <a href="https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping">object mapping</a> to be able to convert the <code>AppUser</code> objects to <code>AppUserDto</code> objects. To do this, open <code>YourProjectApplicationAutoMapperProfile.cs</code> and add the below line:</p>
<pre><code class="language-csharp">CreateMap&lt;AppUser, AppUserDto&gt;().Ignore(x =&gt; x.ExtraProperties);
</code></pre>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/create-mapping.jpg" alt="create-mapping" /></p>
<blockquote>
<p>Creating such a DTO class may not be needed for another entity than the <code>AppUser</code>, since it will probably be already available, especially if you had created the other entity using the ABP Suite.</p>
</blockquote>
<h3>Define the Navigation Property</h3>
<p>Get back to ABP Suite, open the <strong>Navigation Properties</strong> tab of the ABP Suite, click the <strong>Add Navigation Property</strong> button. Browse <code>AppUser.cs</code> in <code>*.Domain\Users</code> folder. Then choose the <code>Name</code> item as display property. Browse <code>AppUserDto.cs</code> in <code>*.Contracts\Users</code> folder. Choose <code>Users</code> from Collection Names dropdown.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/add-user-navigation.jpg" alt="add-user-navigation" /></p>
<h3>Generate the Code!</h3>
<p>That's it! Click <strong>Save and generate</strong> button to create your page. You'll see the following page if everything goes well.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/final-page.jpg" alt="final-page" /></p>
<p>This is the new page that has been created by the ABP Suite. It can perform the fundamental CRUD operations. Also, it has the &quot;App user&quot; column that shows the related user name (you can easily change the automatically created &quot;App user&quot; title from the <strong>Entity Name</strong> field of the navigation property creation screen).</p>
<p><strong>Picking Users from Look Up Table</strong></p>
<p>We used dropdown element to select a user from the user list. If you have a lot of users, then it's good to pick a user from a look up table. A look up table is a modal window that lets you filter data and pick one. To do this, get back to Suite and click <strong>Edit</strong> button of user navigation which is set as <code>AppUserId</code> name. Choose &quot;Modal&quot; from the &quot;UI Pick Type&quot; field. Then click <strong>Save and generate</strong> button to recreate your page.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/ui-pick-type-modal.jpg" alt="ui-pick-type-modal" /></p>
<p>After successful code generation, you'll see the the user can be picked from user table.</p>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-31-Adding-User-Navigation-In-Suite/ui-pick-type-modal2.jpg" alt="ui-pick-type-modal2" /></p>
<h2>About the ABP Commercial RC</h2>
<p>This example has been implemented with <strong>ABP Commercial 3.1.0</strong>. If you have not installed the ABP CLI and ABP Suite, follow the next steps:</p>
<p>1- Uninstall the current version of the CLI and install:</p>
<pre><code class="language-bash">dotnet tool install --global Volo.Abp.Cli --version 3.1.0
</code></pre>
<p>2- Uninstall the current version of the Suite and install:</p>
<pre><code class="language-bash">dotnet tool uninstall --global Volo.Abp.Suite &amp;&amp; dotnet tool install -g Volo.Abp.Suite --version 3.1.0 --add-source https://nuget.abp.io/&lt;YOUR-API-KEY&gt;/v3/index.json
</code></pre>
<p>Don't forget to replace the <code>&lt;YOUR-API-KEY&gt;</code> with your own key!</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/patch-for-chrome-login-issue-identityserver4-samesite-cookie-problem-weypwp3n</guid>
      <link>https://abp.io/community/posts/patch-for-chrome-login-issue-identityserver4-samesite-cookie-problem-weypwp3n</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>identityserver4</category>
      <category>samesite-cookie-problem</category>
      <title>Patch for Chrome login issue (IdentityServer4 + SameSite cookie problem)</title>
      <description>Configures "SameSite" cookie policy to properly for set the SameSite attribute when Identity Server 4 is being used in HTTP schema.</description>
      <pubDate>Wed, 12 Aug 2020 13:38:28 Z</pubDate>
      <a10:updated>2026-03-02T16:35:34Z</a10:updated>
      <content:encoded><![CDATA[<h1>How to fix the Chrome login issue for the  IdentityServer4</h1>
<h2>Introduction</h2>
<p>When you use HTTP on your Identity Server 4 enabled website, users may not login because of the changes made by Chrome in the version 8x. This occurs when you use HTTP schema in your website. The issue is explained here https://docs.microsoft.com/en-gb/dotnet/core/compatibility/3.0-3.1#http-browser-samesite-changes-impact-authentication</p>
<h2>How to solve it?</h2>
<h3>Step-1</h3>
<p>Create the below extension in your  *<strong>.Web</strong> project.</p>
<pre><code class="language-csharp">using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class SameSiteCookiesServiceCollectionExtensions
    {
        public static IServiceCollection AddSameSiteCookiePolicy(this IServiceCollection services)
        {
            services.Configure&lt;CookiePolicyOptions&gt;(options =&gt;
            {
                options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
                options.OnAppendCookie = cookieContext =&gt; 
                    CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
                options.OnDeleteCookie = cookieContext =&gt; 
                    CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            });

            return services;
        }
        
        private static void CheckSameSite(HttpContext httpContext, CookieOptions options)
        {
            if (options.SameSite == SameSiteMode.None)
            {
                var userAgent = httpContext.Request.Headers[&quot;User-Agent&quot;].ToString();
                if (!httpContext.Request.IsHttps || DisallowsSameSiteNone(userAgent))
                {
                    // For .NET Core &lt; 3.1 set SameSite = (SameSiteMode)(-1)
                    options.SameSite = SameSiteMode.Unspecified;
                }
            }
        }

        private static bool DisallowsSameSiteNone(string userAgent)
        {
            // Cover all iOS based browsers here. This includes:
            // - Safari on iOS 12 for iPhone, iPod Touch, iPad
            // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
            // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
            // All of which are broken by SameSite=None, because they use the iOS networking stack
            if (userAgent.Contains(&quot;CPU iPhone OS 12&quot;) || userAgent.Contains(&quot;iPad; CPU OS 12&quot;))
            {
                return true;
            }

            // Cover Mac OS X based browsers that use the Mac OS networking stack. This includes:
            // - Safari on Mac OS X.
            // This does not include:
            // - Chrome on Mac OS X
            // Because they do not use the Mac OS networking stack.
            if (userAgent.Contains(&quot;Macintosh; Intel Mac OS X 10_14&quot;) &amp;&amp; 
                userAgent.Contains(&quot;Version/&quot;) &amp;&amp; userAgent.Contains(&quot;Safari&quot;))
            {
                return true;
            }

            // Cover Chrome 50-69, because some versions are broken by SameSite=None, 
            // and none in this range require it.
            // Note: this covers some pre-Chromium Edge versions, 
            // but pre-Chromium Edge does not require SameSite=None.
            if (userAgent.Contains(&quot;Chrome/5&quot;) || userAgent.Contains(&quot;Chrome/6&quot;))
            {
                return true;
            }

            return false;
        }
    }
}
</code></pre>
<h3>Step-2</h3>
<p>Assume that your project name is <em>Acme.BookStore</em>. Then open <code>AcmeBookStoreWebModule.cs</code> class.</p>
<p>Add the following line to <code>ConfigureServices()</code> method.</p>
<pre><code class="language-csharp"> context.Services.AddSameSiteCookiePolicy(); // cookie policy to deal with temporary browser incompatibilities
</code></pre>
<h3>Step-3</h3>
<p>Go to<code>OnApplicationInitialization()</code> method in <code>AcmeBookStoreWebModule.cs</code> add <code>app.UseCookiePolicy();</code></p>
<pre><code class="language-csharp">public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
        var app = context.GetApplicationBuilder();
        var env = context.GetEnvironment();

        if (env.IsDevelopment())
        {
                app.UseDeveloperExceptionPage();
        }
        else
        {
                app.UseErrorPage();
                app.UseHsts();
        }

        app.UseCookiePolicy(); // added this, Before UseAuthentication or anything else that writes cookies.
	
	//....
}
</code></pre>
<p>It's all! You are ready to go!</p>
<blockquote>
<p>Attention: This problem can't be solved if the user/browser/operating system blocked third-party cookies.</p>
</blockquote>
<p><img src="https://raw.githubusercontent.com/abpframework/abp/dev/docs/en/Community-Articles/2020-08-12-Patch-Chrome-Login-Issue-For-IdentityServer4/Block-Third-Party-Cookies.png" alt="Block-Third-Party-Cookies" /></p>
<hr />
<p>Referenced from https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/</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/implementing-passwordless-authentication-with-asp.net-core-identity-c25l8koj</guid>
      <link>https://abp.io/community/posts/implementing-passwordless-authentication-with-asp.net-core-identity-c25l8koj</link>
      <a10:author>
        <a10:name>alper</a10:name>
        <a10:uri>https://abp.io/community/members/alper</a10:uri>
      </a10:author>
      <category>passwordless-authentication</category>
      <title>Implementing Passwordless Authentication with ASP.NET Core Identity</title>
      <description>In this tutorial, we will show you how to add a custom token provider to authenticate a user with a link, instead of entering a password.</description>
      <pubDate>Fri, 07 Aug 2020 10:58:25 Z</pubDate>
      <a10:updated>2026-03-02T12:19:29Z</a10:updated>
      <content:encoded><![CDATA[<h1>Implementing Passwordless Authentication in ASP.NET Core Identity</h1>
<h2>Introduction</h2>
<p>In this tutorial, we will show you how to add a custom token provider to authenticate a user with a link, instead of entering the password.</p>
<p>This can be useful especially if you want to make someone login to the application with your user, without sharing your secret password. The generated link will be for a single use.</p>
<h3>Source Code</h3>
<p>The completed sample is available on <a href="https://github.com/abpframework/abp-samples/tree/master/PasswordlessAuthentication">GitHub repository</a>.</p>
<h2>Creating the Solution</h2>
<p>Before starting the development, create a new solution named <code>PasswordlessAuthentication</code> and run it by following the <a href="https://docs.abp.io/en/abp/latest/Getting-Started?UI=MVC&amp;DB=EF&amp;Tiered=No">getting started tutorial</a>.</p>
<h2>Step-1</h2>
<p>Create a class named <strong>PasswordlessLoginProvider</strong> in your *<strong>.Web</strong> project:</p>
<pre><code class="language-csharp">using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;

namespace PasswordlessAuthentication.Web
{
    public class PasswordlessLoginProvider&lt;TUser&gt; : TotpSecurityStampBasedTokenProvider&lt;TUser&gt;
        where TUser : class
    {
        public override Task&lt;bool&gt; CanGenerateTwoFactorTokenAsync(UserManager&lt;TUser&gt; manager, TUser user)
        {
            return Task.FromResult(false);
        }

        //We need to override this method as well.
        public async override Task&lt;string&gt; GetUserModifierAsync(string purpose, UserManager&lt;TUser&gt; manager, TUser user)
        {
            var userId = await manager.GetUserIdAsync(user);

            return &quot;PasswordlessLogin:&quot; + purpose + &quot;:&quot; + userId;
        }
    }
}
</code></pre>
<h2>Step-2</h2>
<p>Create <strong>IdentityBuilderExtensions.cs</strong> in your *<strong>.Web</strong> project. We will use this extension method in the <code>ConfigureServices</code>.</p>
<pre><code class="language-csharp">using Microsoft.AspNetCore.Identity;

namespace PasswordlessAuthentication.Web
{
    public static class IdentityBuilderExtensions
    {
        public static IdentityBuilder AddPasswordlessLoginProvider(this IdentityBuilder builder)
        {
            var userType = builder.UserType;
            var totpProvider = typeof(PasswordlessLoginProvider&lt;&gt;).MakeGenericType(userType);
            return builder.AddTokenProvider(&quot;PasswordlessLoginProvider&quot;, totpProvider);
        }
    }
}
</code></pre>
<h2>Step-3</h2>
<p>Add the token provider to the <code>Identity</code> middleware. To do this, find the module class (eg: <code>PasswordlessAuthenticationWebModule.cs</code> in here) in your *<strong>.Web</strong> project and add the below into the <code>ConfigureServices()</code> method.</p>
<pre><code class="language-csharp">public override void ConfigureServices(ServiceConfigurationContext context)
{
	//...
	context.Services
		.GetObject&lt;IdentityBuilder&gt;()
		.AddDefaultTokenProviders()
		.AddPasswordlessLoginProvider();
}
</code></pre>
<h2>Step-4</h2>
<p>We need to create a user interface to be able to generate the magic login link. To do this quickly, open your existing <strong>Index.cshtml.cs</strong> in your *<strong>.Web</strong> project. It's under <code>Pages</code> folder. And copy-paste the below content.</p>
<p><strong>Index.cshtml.cs</strong></p>
<pre><code class="language-csharp">using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Identity;

namespace PasswordlessAuthentication.Web.Pages
{
    public class IndexModel : PasswordlessAuthenticationPageModel
    {
        protected IdentityUserManager UserManager { get; }

        private readonly IIdentityUserRepository _userRepository;

        public string PasswordlessLoginUrl { get; set; }

        public string Email { get; set; }

        public IndexModel(IdentityUserManager userManager, IIdentityUserRepository userRepository)
        {
            UserManager = userManager;
            _userRepository = userRepository;
        }

        public ActionResult OnGet()
        {
            if (!CurrentUser.IsAuthenticated)
            {
                return Redirect(&quot;/Account/Login&quot;);
            }

            return Page();
        }

        //added for passwordless authentication
        public async Task&lt;IActionResult&gt; OnPostGeneratePasswordlessTokenAsync()
        {
            var adminUser = await _userRepository.FindByNormalizedUserNameAsync(&quot;admin&quot;);

            var token = await UserManager.GenerateUserTokenAsync(adminUser, &quot;PasswordlessLoginProvider&quot;,
                &quot;passwordless-auth&quot;);

            PasswordlessLoginUrl = Url.Action(&quot;Login&quot;, &quot;Passwordless&quot;,
                new {token = token, userId = adminUser.Id.ToString()}, Request.Scheme);

            return Page();
        }
    }
}
</code></pre>
<p>We added <code>OnPostGeneratePasswordlessTokenAsync()</code> action to generate the link. We will generate a link for the <strong>admin</strong> user. Therefore, we injected <code>IIdentityUserRepository</code> to get admin user Id. Using the <code>UserManager.GenerateUserTokenAsync()</code> method, we generated a token. After that, we created the URL with the admin user Id and the token. Now we will show the <code>PasswordlessLoginUrl</code> on the page.</p>
<h2>Step-5</h2>
<p>Create a class named <strong>PasswordlessAuthenticationMenus</strong> under <code>Menus</code> folder in your *<strong>.Web</strong> project. And set the content as below.</p>
<pre><code class="language-csharp">namespace PasswordlessAuthentication.Web.Menus
{
    public class PasswordlessAuthenticationMenus
    {
        public const string GroupName = &quot;PasswordlessAuthentication&quot;;

        public const string Home = GroupName + &quot;.Home&quot;;
    }
}
</code></pre>
<h2>Step-6</h2>
<p>Open your <strong>Index.cshtml</strong> and set the content as below. We added a form that posts to <code>GeneratePasswordlessToken</code> action in the razor page. And it will set the <code>PasswordlessLoginUrl</code> field.</p>
<pre><code class="language-html">@page
@using MyBookStore.Web.Menus
@using Volo.Abp.AspNetCore.Mvc.UI.Layout
@model MyBookStore.Web.Pages.IndexModel
@using Microsoft.AspNetCore.Mvc.Localization
@using MyBookStore.Localization
@inject IHtmlLocalizer&lt;MyBookStoreResource&gt; L
@{
    ViewBag.PageTitle = &quot;Home&quot;;
}
@inject IPageLayout PageLayout
@{
    PageLayout.Content.Title = L[&quot;Home&quot;].Value;
    PageLayout.Content.BreadCrumb.Add(L[&quot;Menu:Home&quot;].Value);
    PageLayout.Content.MenuItemName = MyBookStoreMenus.Home;
}
&lt;abp-card&gt;
    &lt;abp-card-body&gt;
        &lt;form asp-page-handler=&quot;GeneratePasswordlessToken&quot; method=&quot;post&quot;&gt;

            &lt;abp-button button-type=&quot;Dark&quot; type=&quot;submit&quot;&gt;Generate passwordless token link&lt;/abp-button&gt;

            @if (Model.PasswordlessLoginUrl != null)
            {
                &lt;abp-card class=&quot;mt-3 p-3&quot;&gt;
                    &lt;a href=&quot;@Model.PasswordlessLoginUrl&quot;&gt;@Model.PasswordlessLoginUrl&lt;/a&gt;
                &lt;/abp-card&gt;
            }
        &lt;/form&gt;
    &lt;/abp-card-body&gt;
&lt;/abp-card&gt;
</code></pre>
<h2>Step-7</h2>
<p>We implemented token generation infrastructure, now it's time validate the token and let the user in. To do this create a folder named <code>Controllers</code> in your *<strong>.Web</strong> project and create a controller, named <strong>PasswordlessController</strong> inside it:</p>
<pre><code class="language-csharp">using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Identity;
using Volo.Abp.Identity.AspNetCore;

namespace PasswordlessAuthentication.Web.Controllers
{
    public class PasswordlessController : AbpController
    {
        protected IdentityUserManager UserManager { get; }

        protected AbpSignInManager SignInManager { get; }

        public PasswordlessController(IdentityUserManager userManager, AbpSignInManager signInManager)
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }

        public virtual async Task&lt;IActionResult&gt; Login(string token, string userId)
        {
            var user = await UserManager.FindByIdAsync(userId);

            var isValid = await UserManager.VerifyUserTokenAsync(user, &quot;PasswordlessLoginProvider&quot;, &quot;passwordless-auth&quot;, token);
            if (!isValid)
            {
                throw new UnauthorizedAccessException(&quot;The token &quot; + token + &quot; is not valid for the user &quot; + userId);
            }

            await UserManager.UpdateSecurityStampAsync(user);

            await SignInManager.SignInAsync(user, isPersistent: false);

            return Redirect(&quot;/&quot;);
        }
    }
}
</code></pre>
<p>We created an endpoint for <code>/Passwordless/Login</code> that gets the token and the user Id.  In this action, we find the user via repository and validate the token via <code>UserManager.VerifyUserTokenAsync()</code> method. If it's valid, we call <code>SignInManager.SignInAsync</code> to be able to create an encrypted cookie and add it to the current response.  Finally we redirect the page to the root URL.</p>
<p>That's all! We created a passwordless login with 7 steps.</p>
<h2>Source Code</h2>
<p>The completed sample is available on <a href="https://github.com/abpframework/abp-samples/tree/master/PasswordlessAuthentication">GitHub repository</a>.</p>
<p>〰️〰️〰️</p>
<p>Happy Coding 🤗</p>
<hr />
<p>I'm Alper Ebicoglu 🧑🏽‍💻 ABP Framework Core Team Member</p>
<p>Follow me for the latest news about .NET and software development:</p>
<p>📌 <a href="https://twitter.com/alperebicoglu">twitter.com/alperebicoglu</a></p>
<p>📌 <a href="https://github.com/ebicoglu">github.com/ebicoglu</a></p>
<p>📌 <a href="https://www.linkedin.com/in/ebicoglu">linkedin.com/in/ebicoglu</a></p>
<p>📌 <a href="https://medium.com/@alperonline">medium.com/@alperonline</a></p>
<hr />
]]></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>