﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://community.devexpress.com/feed-stylesheets/rss.xsl" media="screen"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dx="https://www.devexpress.com/" xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>News</title>
    <link>https://community.devexpress.com/Blogs/news/default.aspx</link>
    <description />
    <language>en-US</language>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388296</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/07/12/migrating-winforms-amp-wpf-from-net-framework-to-net-10.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+10">.net 10</category>
      <category domain="https://community.devexpress.com/Tags/ai">ai</category>
      <category domain="https://community.devexpress.com/Tags/AI+Skills">AI Skills</category>
      <category domain="https://community.devexpress.com/Tags/copilot">copilot</category>
      <category domain="https://community.devexpress.com/Tags/MCP">MCP</category>
      <category domain="https://community.devexpress.com/Tags/net+core">net core</category>
      <category domain="https://community.devexpress.com/Tags/NuGet">NuGet</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/WPF">WPF</category>
      <title>Migrating WinForms &amp; WPF from .NET Framework to .NET 10</title>
      <description> &lt;h2&gt;What This Guide Covers&lt;/h2&gt;
  &lt;p&gt;I&amp;#39;ve hand-migrated more legacy codebases than I care to count, back when &amp;quot;modernisation&amp;quot; meant a fortnight of find-and-replace, a wall of compiler errors, and a knot in your stomach every time you hit Build. So when I recently took a fifteen-year-old WinForms line-of-business app from .NET Framework 4.8 to .NET 10 in a matter of days, with an AI agent doing the grunt work and me keeping my hands on the decisions, I paid attention to what actually worked. This guide is that method, written up as steps you can follow.&lt;/p&gt;
  &lt;p&gt;It assumes a real codebase: a non-SDK project, &lt;code&gt;packages.config&lt;/code&gt;, a commercial control suite referenced the old way, and a decade of dependencies that were sensible in 2012 and a bit embarrassing now. If you&amp;#39;ve worked on real enterprise software, you&amp;#39;ve met this codebase. Odds are you maintain one. The app I&amp;#39;ll keep referring to is WinForms, so the specifics lean that way, but the process is the same for WPF and I&amp;#39;ll flag where the two part company.&lt;/p&gt;
  &lt;p&gt;The migration is rarely &lt;em&gt;hard&lt;/em&gt;. It&amp;#39;s vast and fiddly: thousands of small mechanical changes where one wrong move turns a working app into a non-compiling mystery you&amp;#39;ll spend a day unpicking. It&amp;#39;s tedious and easy to get wrong, which is exactly the kind of work worth automating, as long as you keep checking what it produces. Follow the steps below in order, commit after each one, and a job that&amp;#39;s sat in the &amp;quot;someday&amp;quot; pile for years turns into this week&amp;#39;s work.&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;&lt;strong&gt;Before you start:&lt;/strong&gt; you need Visual Studio 2026 (or Visual Studio 2022 17.14.17+), your source in Git so every step is reversible, access to your DevExpress and NuGet feeds, and a paid GitHub Copilot plan if you want to run the modernization agent. With DevExpress v26.2 setting .NET 10 as the minimum supported target, this is the version to aim at.&lt;/p&gt;
  &lt;/blockquote&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 0: Pick the Right Target (LTS vs STS)&lt;/h2&gt;
  &lt;p&gt;Decide the target framework before you touch anything, because it&amp;#39;s one line in a project file that decides whether you do this again next year. Microsoft alternates its releases. The even-numbered ones (8, 10, 12) are Long-Term Support with a three-year window; the odd numbers in between are Standard-Term Support and shorter-lived (&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-sts-releases-supported-for-24-months/" target="_blank"&gt;24 months now&lt;/a&gt;).&lt;/p&gt;
  &lt;p&gt;The first useful thing the AI did on my migration wasn&amp;#39;t code. My obvious target was .NET 8. It pointed out that 8&amp;#39;s support window was nearly up (&lt;a href="https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core" target="_blank"&gt;November 2026&lt;/a&gt;), while .NET 10 was the current LTS with years of runway ahead of it. That&amp;#39;s one line in a project file standing between &amp;quot;done&amp;quot; and &amp;quot;doing this again next year,&amp;quot; and most juniors wouldn&amp;#39;t have raised it. For an app that has to sit stable for years, you want the LTS. Right now that&amp;#39;s &lt;strong&gt;.NET 10&lt;/strong&gt;, which also happens to be the minimum DevExpress sets in v26.2.&lt;/p&gt;&lt;div class="Note"&gt;&lt;span&gt;Since&amp;nbsp;.NET 10, .NET Framework 4.7.2, and Visual Studio 2022&amp;nbsp;will be minimally supported versions for DevExpress libraries in v26.2, we are also planning to update &lt;a href="https://docs.devexpress.com/GeneralInformation/2529/updates/project-converter#target-devexpress-based-projects-to-net-8-and-net-framework-462" target="_blank"&gt;the DevExpress Project Converter&lt;/a&gt; accordingly: it will re-target DevExpress-based projects to&amp;nbsp;.NET 10&amp;nbsp;and .NET Framework 4.7.2 and update 3rd party NuGet packages to the latest compatible versions (optionally and very similar to what we did &lt;a href="https://community.devexpress.com/blogs/news/archive/2024/10/15/net-easy-automatic-upgrade-of-net-and-external-dependency-versions-converting-assembly-to-package-references-and-more-v24-2.aspx" target="_blank"&gt;for .NET 6 to 8 migration in 2024&lt;/a&gt;).&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 1: Run an Assessment&lt;/h2&gt;
  &lt;p&gt;Before changing code, get an honest picture of what stands between you and .NET 10. This is the job of &lt;a href="https://learn.microsoft.com/en-us/dotnet/core/porting/github-copilot-app-modernization/overview"&gt;GitHub Copilot app modernization for .NET&lt;/a&gt;, the Copilot agent that took over from &lt;a href="https://developercommunity.visualstudio.com/t/NET-Upgrade-Assistant-extension-is-no-l/10971375" target="_blank"&gt;the old Microsoft .NET Upgrade Assistant&lt;/a&gt;. In Visual Studio, right-click the solution in Solution Explorer and choose &lt;strong&gt;Modernize&lt;/strong&gt;, or open Copilot Chat and invoke the agent:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Modernize upgrade this solution to .NET 10&lt;/code&gt;&lt;/pre&gt;
  &lt;p&gt;In VS Code or the Copilot CLI the agent is &lt;code&gt;@modernize-dotnet&lt;/code&gt;. However you start it, the first thing it produces is an &lt;code&gt;assessment.md&lt;/code&gt; in your repo: outdated NuGet packages, APIs with no modern equivalent, and the likely blockers. Read it before you agree to anything. That&amp;#39;s the difference between planning a migration and discovering one.&lt;/p&gt;
  &lt;p&gt;Two caveats. Running the agent needs a paid GitHub Copilot plan, and if the Modernize option isn&amp;#39;t there you&amp;#39;ll need the GitHub Copilot app modernization component from the Visual Studio installer, so factor both in. And treat the assessment as a briefing, not a verdict: it&amp;#39;s very good at finding the mechanical work, but the judgement calls are still yours.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 2: Review and Edit the Plan&lt;/h2&gt;
  &lt;p&gt;Once the assessment&amp;#39;s done, the agent writes a &lt;code&gt;plan.md&lt;/code&gt; that sequences the upgrade into steps. The thing that matters about this file is that it&amp;#39;s yours to edit. Reorder it, pull out steps you&amp;#39;d rather do by hand, and split anything that looks too big into smaller moves.&lt;/p&gt;
  &lt;p&gt;This is where you impose the one rule that keeps migrations safe, and I&amp;#39;ve learned it the hard way: never do it as a big bang. Work in small, reversible, committed steps, so a bad change is a &lt;code&gt;git revert&lt;/code&gt; away rather than an afternoon of unpicking. A sensible plan for a DevExpress desktop app usually runs in this order:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;Convert the project to SDK-style, targeting &lt;code&gt;net10.0-windows&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;Move dependencies from &lt;code&gt;packages.config&lt;/code&gt; to &lt;code&gt;PackageReference&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;Prove the restore works against your feeds before attempting a build.&lt;/li&gt;
    &lt;li&gt;Fix what modern .NET rejects, then clear the build, then clear the warnings.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p&gt;Approve the plan only when it reads like something you&amp;#39;d have written yourself. Then let the agent start executing, one step at a time.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 3: SDK-Style, PackageReference and CPM&lt;/h2&gt;
  &lt;p&gt;The first executed step converts the old project format and moves your references. A couple of things are worth watching, because they catch you out.&lt;/p&gt;&lt;p&gt;&lt;span&gt;If your .NET Framework project relied on assembly references, DevExpress assembly names do not match the DevExpress NuGet package names (for example, for the DevExpress.XtraGrid assembly there is a DevExpress.Win.Grid NuGet package). If you do not want to trust AI for this important conversion, we recommend that you use our Project Converter and its deterministic &lt;a href="https://docs.devexpress.com/WindowsForms/405091/net-net-core-support/migrate-net-framework-app-to-net#step-1-convert-devexpress-assemblies-to-nuget-packages" target="_blank"&gt;Convert DevExpress assembly references to NuGet packages&lt;/a&gt;&amp;nbsp;option before you trigger actual project conversion.&lt;/span&gt;&lt;/p&gt;
  &lt;p&gt;If the project sits at the repository root, default file-globbing in an SDK-style project can hoover up source from other projects nearby. This is one the AI caught that I&amp;#39;d have walked straight into: my project sat at the repo root, so the default globbing would&amp;#39;ve pulled in source from the projects around it. It turned globbing off and carried the explicit file lists across. Keep an eye out for it, because it&amp;#39;s easy to miss and a pain to debug.&lt;/p&gt;
  &lt;p&gt;If your solution has more than one project, this is the moment to adopt &lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management" target="_blank"&gt;Central Package Management (CPM)&lt;/a&gt;, so every project shares one set of versions. Drop a &lt;code&gt;Directory.Packages.props&lt;/code&gt; at the repository root:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-xml"&gt;&amp;lt;Project&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;ManagePackageVersionsCentrally&amp;gt;true&amp;lt;/ManagePackageVersionsCentrally&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageVersion Include=&amp;quot;DevExpress.Win&amp;quot; Version=&amp;quot;26.2.*&amp;quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;&lt;/code&gt;&lt;/pre&gt;
  &lt;p&gt;That example pins the WinForms meta-package; for a WPF app you&amp;#39;d use &lt;code&gt;DevExpress.Wpf&lt;/code&gt; instead. Individual projects then reference the package without a version, and your DevExpress and framework versions stop drifting apart across the solution. Prove &lt;code&gt;dotnet restore&lt;/code&gt; succeeds against your component feed before you try to compile. Get restore green first and you skip a whole category of confusing build errors.&lt;/p&gt;&lt;p&gt;&lt;span&gt;For more information on how your projects can benefit from CPM, please also review a related article&amp;nbsp;&lt;a href="https://community.devexpress.com/Blogs/news/archive/2026/04/24/application-security-project-dependency-version-bumps-demystified-modern-security-realities-in-net-nuget-ecosystem.aspx" target="_blank"&gt;Application Security — Project Dependency &amp;quot;Version Bumps&amp;quot; Demystified or Modern Security Realities in .NET / NuGet Ecosystem&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 4: Fix What Modern .NET Rejects&lt;/h2&gt;
  &lt;p&gt;Now the code itself. On my migration the first compile threw 36 errors and roughly 1,795 warnings. That sounds alarming, and mostly it isn&amp;#39;t: the errors collapsed to a handful of root causes, and the warnings came down to one. Clear them in that order, errors first and then warnings, committing as you go. These are the ones you&amp;#39;re most likely to meet on a DevExpress desktop app.&lt;/p&gt;
  &lt;h3&gt;Retire APIs with no modern equivalent&lt;/h3&gt;
  &lt;p&gt;Swap out the usual suspects: an old zip library for &lt;code&gt;System.IO.Compression&lt;/code&gt;, LINQ-to-SQL screens for a supported data path, dead &lt;code&gt;app.config&lt;/code&gt; sections for their modern equivalents. The assessment will have flagged most of them.&lt;/p&gt;
  &lt;h3&gt;Watch for namespace clashes&lt;/h3&gt;
  &lt;p&gt;A properly sneaky one on my app: a bare &lt;code&gt;Windows.Forms…&lt;/code&gt; reference stopped resolving on the new framework, thanks to a namespace collision that didn&amp;#39;t exist on Framework. Fully qualify it and the error vanishes. One line, but a baffling one until you spot it.&lt;/p&gt;
  &lt;h3&gt;The screens look wrong: fix DPI awareness&lt;/h3&gt;
  &lt;p&gt;The app compiled and launched, but the forms came up subtly wrong: controls a touch out of place, spacing not quite right. That&amp;#39;s the DPI-awareness default changing between frameworks, and it&amp;#39;s the sort of thing you can stare at for a while before the penny drops. The AI worked it out from a screenshot and a description, pointed me at the DevExpress high-DPI docs to back it up, and one setting put the screens back exactly as they were. That trap is a WinForms one; WPF scales differently and won&amp;#39;t hit it, though it has its own breaking changes to watch for, the removal of &lt;code&gt;BinaryFormatter&lt;/code&gt; being the one that bites most often (&lt;a href="https://supportcenter.devexpress.com/ticket/details/t1263793/deprecation-of-microsoft-s-binaryformatter-and-its-impact-on-drag-drop-operations" target="_blank"&gt;learn more&lt;/a&gt;).&lt;/p&gt;
  &lt;h3&gt;Collapse the warning storm&lt;/h3&gt;
  &lt;p&gt;The warning count after a big migration can look terrifying and usually is anything but. Two moves cleared most of mine: declaring the assembly&amp;#39;s supported-platform attribute to keep the compatibility analyser happy, and pinning a data-access package to the last version before it was marked obsolete. That second change alone dropped 500-plus warnings without touching a line of generated code.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 5: Lean on Compatibility Shims&lt;/h2&gt;
  &lt;p&gt;You don&amp;#39;t have to migrate everything before you can run. I&amp;#39;d assumed I would need to move my two in-house .NET Framework libraries first. I didn&amp;#39;t. The modernised app compiled and ran on .NET 10 while still referencing those libraries through the .NET Framework compatibility shim. One thing to be clear about: that only holds while those libraries stick to APIs modern .NET still provides. You&amp;#39;ll get a build warning, and any code path that calls an API .NET 10 has dropped will fail at runtime rather than at compile time, so exercise the paths that go through them before you call it done. Even so, if you&amp;#39;ve got in-house libraries pinned to Framework, leave them where they are for now. Get the main application onto .NET 10 first, confirm it runs, and book the deeper library work as a separate job that blocks nothing.&lt;/p&gt;
  &lt;p&gt;This is the single biggest reason these migrations stall for no good reason. Teams assume every dependency has to move first, and give up. It doesn&amp;#39;t, and they don&amp;#39;t. You don&amp;#39;t have to boil the ocean. Get a working, current-LTS application in place, then chip away at the rest without holding the whole project hostage.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Where AI Fits, and Where You Stay in Charge&lt;/h2&gt;
  &lt;p&gt;The reason this workflow holds up is that the agent proposes and you dispose. The &lt;code&gt;assessment.md&lt;/code&gt; and &lt;code&gt;plan.md&lt;/code&gt; aren&amp;#39;t decoration; they&amp;#39;re your checkpoints. You read the assessment, you edit the plan, you approve each step, and every change lands as a described commit you can review or revert. The AI carries the vast, repetitive sweep across dozens of files with no fatigue and no typos. The judgement and the checking stay with you. I never once typed &amp;quot;trust me,&amp;quot; and that&amp;#39;s the whole point.&lt;/p&gt;
  
    &lt;a&gt;
      &lt;img src="https://community.devexpress.com/blogs/news/2026/upgrade-workflow-diagram.png" width="820" alt="The upgrade workflow runs in three reviewable stages: assessment (assessment.md), then an editable plan (plan.md), then execution in small commits, ending with the app running on .NET 10. You review and approve at every stage."&gt;
    &lt;/a&gt;
    Assess, plan, execute. The agent does the work; you sign off each stage.
  
  &lt;hr&gt;
  &lt;h2&gt;Keep the Component Code Current: AI Skills and the MCP Server&lt;/h2&gt;
  &lt;p&gt;The modernization agent is built to move your framework, not to know your component vendor&amp;#39;s latest API surface. That gap does the most damage during a migration, because a migration is when you touch the most component code in the shortest time. Ask a general-purpose model to update a DevExpress grid or report and it&amp;#39;ll often reach for an older namespace it saw more of in training. The code looks right, compiles, and sits there on a superseded API. Two DevExpress tools close that gap, and they&amp;#39;re worth adding to the same IDE for the fix-up work.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/DevExpress/agent-skills"&gt;DevExpress AI Skills&lt;/a&gt;&lt;/strong&gt; hand the assistant current DevExpress namespaces, entry points and configuration patterns before it writes a line. They install into the coding assistant you already use (GitHub Copilot, Claude Code, Cursor or JetBrains), they work even without a live documentation connection, and they keep the component code on supported APIs rather than remembered ones. On a migration that pays off directly: fewer convincing-but-stale suggestions to catch in review, and a first answer you can build on instead of unpick. Call the relevant skill explicitly at the start of a task rather than trusting auto-detection, with &lt;code&gt;#&lt;/code&gt; in Copilot or &lt;code&gt;/&lt;/code&gt; in Cursor and Claude Code.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;&lt;a href="https://docs.devexpress.com/GeneralInformation/405551"&gt;The DevExpress MCP Server&lt;/a&gt;&lt;/strong&gt; adds the other half: live access to current documentation and version-sensitive detail when a task gets specific. Where a Skill sets the right starting point, the MCP Server supplies the authoritative reference to finish the job, so the assistant spends its lookups on real implementation questions instead of working out which API it should&amp;#39;ve used in the first place. Adding it is a one-line job in most assistants; in Claude Code, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;claude mcp add --transport http dxdocs https://api.devexpress.com/mcp/docs&lt;/code&gt;&lt;/pre&gt;
  &lt;p&gt;Put them together and the split is clean: the modernization agent carries the framework move, the Skills keep your DevExpress code correct, and the MCP Server fills in the detail on demand. It&amp;#39;s the same partnership principle as the rest of this guide, pointed at your component layer. I went deeper on why this matters, and how the two work together, with worked before-and-after examples in an earlier post: &lt;a href="https://community.devexpress.com/Blogs/news/archive/2026/07/09/beyond-prompts-teaching-ai-how-to-build-with-devexpress.aspx"&gt;Beyond Prompts: Teaching AI How to Build with DevExpress&lt;/a&gt;. If you haven&amp;#39;t read it, that&amp;#39;s the companion piece to this guide.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Step 6: Verify You Are Actually Done&lt;/h2&gt;
  &lt;p&gt;&amp;quot;It compiles&amp;quot; isn&amp;#39;t the finish line. Before you call it migrated, confirm the app launches and the main workflows behave, the screens render correctly at your users&amp;#39; DPI settings, the warning count is down to something you actually understand, and each step is a clean commit in history. Only then start building new features on the modern foundation, which you can now do this week rather than someday.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;The Takeaway&lt;/h2&gt;
  &lt;p&gt;The blocker on most legacy migrations isn&amp;#39;t capability. It&amp;#39;s the sheer volume of small changes, and the fear of breaking an app that&amp;#39;s quietly worked for years. This workflow deals with both. The modernization agent carries the tedium and surfaces the landmines as an assessment you approve, DevExpress AI Skills keep the component code on current APIs, compatibility shims stop a single old dependency holding everything hostage, and small reversible commits keep the risk low at every step.&lt;/p&gt;
  &lt;p&gt;With DevExpress v26.2 aiming to make .NET 10 the minimum, now is the time to plan this migration, not a reason to panic. The app I did this on was fifteen years old and threw 36 errors and getting on for 1,800 warnings on its first .NET 10 compile. It was running clean within days, and I was building new features on it the same week. The migration is the part everyone dreads. Worked in small steps, with the tooling doing the legwork and you making the calls, it turns out to be the manageable bit.&lt;/p&gt;
  &lt;hr&gt;
  &lt;h2&gt;Further Reading&lt;/h2&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/porting/github-copilot-app-modernization/overview"&gt;GitHub Copilot app modernization for .NET (overview)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/porting/github-copilot-app-modernization/how-to-upgrade-with-github-copilot"&gt;How to upgrade a .NET app with Copilot modernization&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://dotnet.microsoft.com/platform/support/policy/dotnet-core"&gt;.NET Support Policy: LTS vs STS release cadence&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://learn.microsoft.com/nuget/consume-packages/central-package-management"&gt;Central Package Management (NuGet)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://learn.microsoft.com/dotnet/desktop/winforms/high-dpi-support-in-windows-forms"&gt;High DPI support in Windows Forms&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/DevExpress/agent-skills"&gt;DevExpress AI Skills for coding agents&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://community.devexpress.com/Blogs/news/archive/2026/07/09/beyond-prompts-teaching-ai-how-to-build-with-devexpress.aspx"&gt;Beyond Prompts: Teaching AI How to Build with DevExpress (companion post)&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p class="dx-tags"&gt;
    &lt;a href="https://community.devexpress.com/Tags/WinForms"&gt;WinForms&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/WPF"&gt;WPF&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/NET"&gt;.NET&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/Migration"&gt;Migration&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/Legacy+Modernization"&gt;Legacy Modernization&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/AI"&gt;AI&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/AI-Assisted+Development"&gt;AI-Assisted Development&lt;/a&gt;
    &lt;a href="https://community.devexpress.com/Tags/NuGet"&gt;NuGet&lt;/a&gt;
  &lt;/p&gt;</description>
      <pubDate>Sun, 12 Jul 2026 22:05:00 Z</pubDate>
      <dc:creator>Paul Usher (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388295</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/07/09/beyond-prompts-teaching-ai-how-to-build-with-devexpress.aspx</link>
      <category domain="https://community.devexpress.com/Tags/ai">ai</category>
      <category domain="https://community.devexpress.com/Tags/AI+Skills">AI Skills</category>
      <category domain="https://community.devexpress.com/Tags/AI-Assistant">AI-Assistant</category>
      <category domain="https://community.devexpress.com/Tags/Featured">Featured</category>
      <category domain="https://community.devexpress.com/Tags/MCP">MCP</category>
      <category domain="https://community.devexpress.com/Tags/Office+File+API">Office File API</category>
      <category domain="https://community.devexpress.com/Tags/productivity">productivity</category>
      <category domain="https://community.devexpress.com/Tags/Reporting">Reporting</category>
      <category domain="https://community.devexpress.com/Tags/skills">skills</category>
      <title>Beyond Prompts: Teaching AI How to Build with DevExpress</title>
      <description>&lt;h2&gt;AI Needs More Than Good Prompts&lt;/h2&gt;

&lt;p&gt;If you&amp;#39;ve paired Claude Code, GitHub Copilot or Cursor with DevExpress, you already know the moment I&amp;#39;m about to describe. It&amp;#39;s the same one the team kept running into while building the &lt;a href="https://www.devexpress.com/products/net/office-file-api/" target="_blank" title="DevExpress Office &amp;amp; PDF File API"&gt;DevExpress Office &amp;amp; PDF File API&lt;/a&gt; and &lt;a href="https://www.devexpress.com/subscriptions/reporting/" target="_blank" title="DevExpress Reports"&gt;DevExpress Reports&lt;/a&gt;&amp;nbsp;Skills, and their evaluation notes are what this post is really about. The assistant starts strong. Clean C#, sensible class names, code that looks like it belongs in your solution. Then you read it a second time and something&amp;#39;s off: the namespace is from a release two versions back, the API has been superseded, or the whole thing has quietly wandered off to a third-party library because that&amp;#39;s what the model saw most often in training.&lt;/p&gt;

&lt;p&gt;The interesting part wasn&amp;#39;t that the AI got things wrong. Everyone expects that. What struck me about the team&amp;#39;s findings was how &lt;em&gt;convincing&lt;/em&gt; the wrong answers were. The ones that failed to compile cost them nothing; those get spotted immediately. The expensive ones looked completely reasonable right up until someone compared them with the current documentation. More often than not, they were yesterday&amp;#39;s best practice dressed up as today&amp;#39;s.&lt;/p&gt;

&lt;p&gt;That single observation ended up shaping how the team designed the Skills.&lt;/p&gt;

&lt;p&gt;As they worked through the results, the same theme kept coming back. When the generated code missed, the problem was almost never C#, and it certainly wasn&amp;#39;t the model&amp;#39;s ability to reason. It was product knowledge. The model didn&amp;#39;t have the current namespaces, the right entry points or the small amount of framework-specific context it needed before it started typing. Hand it those things and the quality of the output jumped straight away.&lt;/p&gt;

&lt;p&gt;We spend a lot of energy on prompt engineering, and good prompts genuinely help. But a prompt can only work with what the model already knows. No amount of clever wording fills a gap in product knowledge that isn&amp;#39;t there to begin with. Every time, giving the assistant accurate context &lt;em&gt;before&lt;/em&gt; it wrote anything beat trying to talk it back from a bad first answer.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the whole idea behind &lt;a href="https://github.com/DevExpress/agent-skills" target="_blank" title="DevExpress AI Skills — GitHub"&gt;DevExpress AI Skills&lt;/a&gt;. They don&amp;#39;t replace the model&amp;#39;s reasoning, and they don&amp;#39;t try to re-host the documentation. They hand the assistant a concise, product-specific starting point before it writes the first line of code, so it can spend its effort solving your actual problem instead of reconstructing an unfamiliar API from scraps of training data.&lt;/p&gt;

&lt;p&gt;The easiest way to show you what I mean is to walk through the same prompts the team used during the review, with and without the Skill.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;When Good Code Is Still Wrong&lt;/h2&gt;

&lt;p&gt;This showed up early in the team&amp;#39;s evaluation. Completely made-up APIs were never the issue, because you catch those instantly. The answers that slowed them down were the believable ones: code that read like it came from someone who knew the framework reasonably well, but carried just enough stale or incorrect detail to send you chasing the wrong problem for half an hour.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the trap with specialised frameworks. They move constantly. Namespaces get reorganised, newer APIs replace older programming models, and products grow in directions that simply aren&amp;#39;t in the model&amp;#39;s training data yet. The assistant has no way of knowing a better approach exists unless something tells it, so it does the reasonable thing and fills the gap with the closest match it can find. Most of the time that match looks plausible enough to trust.&lt;/p&gt;

&lt;p&gt;Across the Office &amp;amp; PDF File API and DevExpress Reports review, the team watched this happen again and again. Same prompt, same model, same task. The only thing they changed was what the assistant knew before it started. And the moment it started from accurate DevExpress guidance rather than memory, the code changed.&lt;/p&gt;

&lt;p&gt;Here are three examples straight from that work.&lt;/p&gt;

&lt;h2&gt;Example 1: Generating a QR Code&lt;/h2&gt;

&lt;p&gt;Start with something ordinary.&lt;/p&gt;

&lt;div style="background:#f7f9fb;border-left:4px solid #fa6432;border-radius:0 6px 6px 0;padding:14px 18px;margin:0 0 22px;"&gt;
&lt;p style="margin:0 0 6px;"&gt;&lt;strong&gt;Prompt&lt;/strong&gt;&lt;/p&gt;
&lt;p style="margin:0;"&gt;&lt;em&gt;Generate a QR Code containing &lt;code&gt;https://community.devexpress.com&lt;/code&gt; and save it as a PNG using DevExpress.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Without the Barcode Skill, the assistant reached for an older DevExpress API. The important thing to note, the Barcode functionality was NOT removed, simply improved and updated.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using DevExpress.BarCodes;

BarCode barCode = new BarCode();
barCode.Symbology = Symbology.QRCode;
barCode.CodeText = url;
barCode.Save(&amp;quot;qr.png&amp;quot;);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;There&amp;#39;s almost nothing to object to here. It reads cleanly, it follows normal C# conventions, and if you didn&amp;#39;t already know the current Barcode API you&amp;#39;d have every reason to assume it was fine. That&amp;#39;s exactly what makes this kind of error awkward. It doesn&amp;#39;t look absurd. It looks sensible.&lt;/p&gt;

&lt;p&gt;The trouble is the historical &lt;code&gt;DevExpress.BarCodes&lt;/code&gt; namespace and an object model that no longer reflects the current API. The model hasn&amp;#39;t invented nonsense; it has rebuilt a solution out of older fragments that showed up often enough in training to feel right.&lt;/p&gt;

&lt;p&gt;With the Barcode Skill loaded, the same prompt lands on the current API.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using System.IO;
using DevExpress.Docs.Barcode;
using DevExpress.Drawing;

var qrOptions = new QRCodeOptions {
    ModuleSize = 4f,
    Dpi = 96
};

using var generator = new BarcodeGenerator(qrOptions);
using var output = new FileStream(&amp;quot;qr.png&amp;quot;, FileMode.Create, FileAccess.Write);
generator.Export(&amp;quot;https://community.devexpress.com&amp;quot;, output, DXImageFormat.Png);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nothing changed except what the assistant knew going in. That matters more than it first appears, because the first answer becomes the foundation for everything after it. Start the conversation on an obsolete namespace and every follow-up (styling the barcode, switching the output format, dropping the image into another document) tends to stay on that same dead branch.&lt;/p&gt;

&lt;p&gt;I&amp;#39;ll be honest: these errors worry me more than a broken build ever has. A bad method name announces itself. Convincing code built on an old API doesn&amp;#39;t, and it&amp;#39;s easiest to trust precisely when you&amp;#39;re moving fast and not looking closely. The Skill heads that off by putting the assistant on the right API before the conversation picks up speed.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Example 2: Exporting Large Excel Files&lt;/h2&gt;

&lt;p&gt;This one&amp;#39;s trickier, because the &amp;quot;wrong&amp;quot; code isn&amp;#39;t wrong in the usual sense. It compiles. It produces a perfectly valid workbook. The problem is that the assistant picked the wrong DevExpress product for the job.&lt;/p&gt;

&lt;div style="background:#f7f9fb;border-left:4px solid #fa6432;border-radius:0 6px 6px 0;padding:14px 18px;margin:0 0 22px;"&gt;
&lt;p style="margin:0 0 6px;"&gt;&lt;strong&gt;Prompt&lt;/strong&gt;&lt;/p&gt;
&lt;p style="margin:0;"&gt;&lt;em&gt;Export 100,000 rows to an Excel workbook efficiently using DevExpress.&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Without the &lt;a href="https://docs.devexpress.com/OfficeFileAPI/114031/excel-export-library" target="_blank" title="Excel Export Library"&gt;Excel Export Library&lt;/a&gt; Skill, most assistants reach for the Spreadsheet API.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using var workbook = new Workbook();

Worksheet sheet = workbook.Worksheets[0];

for (int i = 0; i &amp;lt; 100_000; i++)
{
    sheet.Cells[i, 0].Value = data[i];
}

workbook.SaveDocument(&amp;quot;output.xlsx&amp;quot;, DocumentFormat.Xlsx);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Functionally, this is a fair answer. It builds a workbook and writes data into it, and for most day-to-day work the DevExpress Spreadsheet API is exactly what you want: it gives you a rich in-memory object model for creating, editing, formatting, calculating and analysing content.&lt;/p&gt;

&lt;p&gt;But look at the prompt again. It says &lt;strong&gt;efficiently&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Building an Excel document and streaming out a large dataset are related jobs, not the same job. The Spreadsheet API holds the whole workbook in memory so everything stays editable for the life of the document. That&amp;#39;s a strength when you&amp;#39;re editing. At 100,000 rows it&amp;#39;s mostly overhead, because once a row is written you&amp;#39;re never going back to touch it, the formulas usually don&amp;#39;t need recalculating mid-generation, and what you actually care about is memory that stays flat as the row count climbs. That&amp;#39;s the exact problem the DevExpress Excel Export Library was built for.&lt;/p&gt;

&lt;p&gt;With the Excel Export Skill in play, the assistant switches to the streaming API.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using DevExpress.Export.Xl;

IXlExporter exporter = XlExport.CreateExporter(XlDocumentFormat.Xlsx);

using var document = exporter.CreateDocument(stream);
using var sheet = document.CreateSheet();

foreach (var customer in customers)
{
    using var row = sheet.CreateRow();
    using var cell = row.CreateCell();
    cell.Value = customer.Name;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These two libraries aren&amp;#39;t rivals. They solve different problems. One hands you a full workbook object model for manipulation; the other writes rows straight to the stream and keeps memory predictable no matter how big the export gets. On its own, the assistant has no real basis for preferring one over the other, because both technically satisfy the loose wording of the prompt.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the gap the Skill fills. It isn&amp;#39;t fixing syntax; it&amp;#39;s supplying the engineering judgement to match the API to the workload.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Example 3: Report Viewer Setup and Customization&lt;/h2&gt;

&lt;p&gt;DevExpress Reports is a great stress test for AI-assisted development, because so much of it hinges on small platform-specific details. The code can look structurally perfect and still be missing the one registration call, callback or client-side API that makes the viewer actually work.&lt;/p&gt;

&lt;p&gt;One evaluation prompt asked for the native DevExpress Report Viewer in a Blazor Server app. Without the DevExpress Blazor Reports Skill, the assistant registered services for the JavaScript-based viewer family instead of the native Blazor one.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;builder.Services.AddDevExpressBlazorReporting();&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Easy mistake to make. The method name sounds right, it slots neatly into the ASP.NET Core service registration pipeline, and nothing about it raises a flag. But native Blazor Reporting needs a different call.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;builder.Services.AddDevExpressServerSideBlazorReportViewer();&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is the kind of thing that costs a disproportionate amount of pain. The app compiles, the page loads, and you&amp;#39;re left staring at a blank viewer wondering what you did wrong. Nothing failed at the C# level. It failed at knowing which DevExpress Reports viewer family the prompt was even talking about.&lt;/p&gt;

&lt;p&gt;The same story plays out when you customise the viewer. Say you want to hide the Print button and limit exports to PDF. With no product guidance, assistants tend to invent APIs that feel plausible but don&amp;#39;t exist.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;previewModel.GetToolbarItemCommands().forEach(command =&amp;gt; {
    if (command.id === &amp;quot;print&amp;quot;) {
        command.visible = false;
    }
});

previewModel.GetExportFormatItems().forEach(item =&amp;gt; {
    if (item.format !== &amp;quot;pdf&amp;quot;) {
        item.visible = false;
    }
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It reads like it belongs in a reporting viewer: sensible names, a clean split between toolbar and export customisation, the shape of a real client-side API. But the actual DevExpress callbacks use different entry points.&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-javascript"&gt;function customizeMenuActions(s, e) {
    var printAction = e.GetById(DevExpress.Reporting.Viewer.ActionId.PrintPage);
    if (printAction) {
        printAction.visible = false;
    }
}

function customizeExportOptions(s, e) {
    e.HideFormat(DevExpress.Reporting.Viewer.ExportFormatID.XLS);
    e.HideFormat(DevExpress.Reporting.Viewer.ExportFormatID.XLSX);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is why specialised frameworks are hard for general-purpose assistants. The answer has the right shape and the wrong product knowledge, and in reporting, where so much of the setup is declarative or callback-driven, one wrong method name is the difference between a working viewer and a dead end.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;When the Best Answer Is Another Question&lt;/h2&gt;

&lt;p&gt;Not every win comes from better code. Some of my favourite Skill behaviour shows up when the assistant decides &lt;em&gt;not&lt;/em&gt; to write code yet.&lt;/p&gt;

&lt;p&gt;AI assistants are heavily biased towards answering the prompt in front of them. When a requirement is underspecified, they&amp;#39;ll usually make an assumption and press on. That keeps things moving, but it also produces software that satisfies the words of the prompt rather than what you actually meant.&lt;/p&gt;

&lt;p&gt;Picture asking for &amp;quot;a chart using DevExpress.&amp;quot; From a developer&amp;#39;s point of view that request is wide open. Bar, line, pie, scatter? What&amp;#39;s the data source? Who&amp;#39;s the audience? Any experienced developer would ask a question or two before writing a line.&lt;/p&gt;

&lt;p&gt;Most assistants won&amp;#39;t. They&amp;#39;ll pick whatever chart type seems most likely and start generating.&lt;/p&gt;

&lt;p&gt;Several DevExpress Skills nudge the assistant the other way: when something essential is missing, ask first.&lt;/p&gt;

&lt;div style="background:#f7f9fb;border-left:4px solid #fa6432;border-radius:0 6px 6px 0;padding:14px 18px;margin:0 0 22px;"&gt;
&lt;p style="margin:0 0 6px;"&gt;&lt;strong&gt;Developer&lt;/strong&gt;&lt;/p&gt;
&lt;p style="margin:0 0 12px;"&gt;&lt;em&gt;Create a chart using DevExpress.&lt;/em&gt;&lt;/p&gt;
&lt;p style="margin:0 0 6px;"&gt;&lt;strong&gt;AI with the Skill&lt;/strong&gt;&lt;/p&gt;
&lt;p style="margin:0;"&gt;&lt;em&gt;Which chart type would you like to create? For example, Bar, Line, Pie, Area or Scatter?&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;That small shift makes the whole thing feel less like poking a code generator and more like working with a colleague. And it saves you the classic time-sink of unwinding an implementation built on an assumption nobody ever made.&lt;/p&gt;

&lt;p&gt;You could bake this into your own prompts, of course, but then you&amp;#39;re on the hook to remember it, repeat it across every assistant you use, and keep it in step with how your team works. Putting it in a Skill makes it part of the workflow instead of one more line you have to paste into every request.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Skills and the DevExpress MCP Server&lt;/h2&gt;

&lt;p&gt;One question comes up almost every time I talk about this:&lt;/p&gt;

&lt;div style="background:#f7f9fb;border-left:4px solid #fa6432;border-radius:0 6px 6px 0;padding:14px 18px;margin:0 0 22px;"&gt;
&lt;p style="margin:0;"&gt;&lt;em&gt;If the DevExpress MCP Server already gives AI agents access to the documentation, why do we need Skills too?&lt;/em&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Because they&amp;#39;re solving different problems.&lt;/p&gt;

&lt;p&gt;A Skill is the focused guidance the assistant gets &lt;em&gt;before&lt;/em&gt; it starts: enough to recognise the right product area, follow the common implementation patterns, and sidestep the mistakes that come from leaning on training data alone. Skills are deliberately small, so they load fast and cover a lot of everyday work without sending the assistant off on several rounds of exploration.&lt;/p&gt;

&lt;p&gt;The MCP Server plays a different role. It gives compatible agents live access to the current documentation, API details and examples. That&amp;#39;s the shipping product, not whatever the model happened to memorise.&lt;/p&gt;


&lt;img src="https://community.devexpress.com/blogs/paulu/skill-mcp-flow.png" alt="A developer prompt passes through a DevExpress Skill to the AI coding assistant, which exchanges requests and authoritative detail with the DevExpress MCP Server before producing generated code." style="max-width:100%;height:auto;"&gt;
A Skill points the assistant to the right product area up front; the MCP Server supplies authoritative detail once the task gets specific.


&lt;p&gt;In practice they hand off to each other. The Skill gets the assistant to the right place; when the task needs more depth, the MCP Server supplies the authoritative reference to carry it through. Together they cut the guesswork at both ends: the Skill keeps the assistant out of the wrong product area, and the MCP Server fills in the specifics once the work gets detailed.&lt;/p&gt;

&lt;p&gt;That pairing also trims a lot of back-and-forth. Without a Skill, an agent can burn several tool calls just working out which API it should be using. With the right Skill loaded, those MCP calls go towards real implementation questions instead of correcting the assistant&amp;#39;s starting assumptions.&lt;/p&gt;

&lt;p&gt;There&amp;#39;s a discoverability angle here too. In a recent customer survey, roughly a third of respondents didn&amp;#39;t know the DevExpress MCP Server existed. Skills give us a natural way to reintroduce it as part of a broader AI-assisted workflow, rather than leaving it as a separate tool people may never stumble across.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Why Smaller Models Benefit Even More&lt;/h2&gt;

&lt;p&gt;The big frontier models are impressive even when their product knowledge is patchy. Claude Opus, Claude Sonnet and the latest GPT-class models can often reason their way to something that works, especially with documentation access or a patient developer steering. They still slip up, but they tend to recover.&lt;/p&gt;

&lt;p&gt;Smaller and older models have a harder time. Compact models like Claude Haiku and Gemini Flash (and the local models more teams are running now) are built to be fast, responsive and cheap. They&amp;#39;re a great fit for plenty of coding work, but they carry less specialised product knowledge out of training.&lt;/p&gt;

&lt;p&gt;This is where Skills earn their keep. Rather than asking a compact model to reverse-engineer an unfamiliar API from a handful of examples, the Skill hands it the essentials up front: current namespaces, recommended entry points, the usual patterns and the traps worth avoiding, all dropped straight into its working context.&lt;/p&gt;

&lt;p&gt;And it matters beyond the hosted services. More teams are looking at local models for privacy, compliance or cost reasons. Those models will keep improving, but they&amp;#39;re never going to hold detailed knowledge of every commercial framework or every recently shipped API. Skills close that gap by supplying the DevExpress-specific context regardless of whether the model runs in the cloud or on the developer&amp;#39;s own machine.&lt;/p&gt;

&lt;p&gt;The aim isn&amp;#39;t to make a small model behave like a large one. It&amp;#39;s to let you choose the model that suits your workflow without giving up confidence that it understands the DevExpress APIs you&amp;#39;re working with.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Skills Versus Custom Instructions&lt;/h2&gt;

&lt;p&gt;Most AI assistants already give you a way to shape their behaviour. Copilot has custom instructions, Cursor has rule files, Claude Code has project instructions, and just about every other agent has its own flavour. Useful, all of them, but also fragmenting: each one wants its guidance in a different format.&lt;/p&gt;

&lt;p&gt;Work across a few tools and you end up maintaining the same advice in several places at once. Coding conventions, preferred APIs, project-specific practices, all copied between config files and quietly drifting out of sync.&lt;/p&gt;

&lt;p&gt;Skills take a more portable route. They load when they&amp;#39;re relevant and stay out of the way when they&amp;#39;re not: a DevExpress Reports&amp;nbsp;Skill turns up for reporting work, a Barcode Skill for barcode generation, spreadsheet guidance when you&amp;#39;re in Excel territory. The assistant gets what it needs without dragging a giant instruction file into every unrelated conversation.&lt;/p&gt;

&lt;p&gt;That on-demand behaviour is the point. Loading everything into every request eats context and pulls the assistant&amp;#39;s attention off the task at hand. Progressive disclosure keeps the working context tight, which really shows when you&amp;#39;ve got several DevExpress products installed, or a project that mixes reporting, document processing and web UI.&lt;/p&gt;

&lt;p&gt;Portability is just as valuable. Because Skills aren&amp;#39;t tied to one assistant, the same guidance travels across every supported agent. And as plugin-based distribution matures, Skills give updates a path to evolve alongside DevExpress products, instead of leaving each developer to hand-maintain their own instruction files.&lt;/p&gt;

&lt;p&gt;The takeaway is simple: you shouldn&amp;#39;t have to teach every AI assistant how to use DevExpress from scratch. Install the relevant Skills, pair them with the MCP Server when you need more depth, and let the tooling carry consistent guidance wherever the work happens.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Looking Beyond the Prompt&lt;/h2&gt;

&lt;p&gt;A year ago, most of the conversation around AI-assisted development was about prompt engineering, with whole posts hunting for the magic phrasing that would unlock better code. Prompts matter, no argument. But they&amp;#39;re only part of the story. An assistant can only work with what it knows, and no amount of elegant wording makes up for knowledge that isn&amp;#39;t there.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the lesson that runs through the team&amp;#39;s work on the Office File &amp;amp; PDF API and DevExpress Reports Skills. When the assistant only half-knew DevExpress, it papered over the gaps with educated guesses. When it started from accurate context, the output was more reliable, more current, and a lot closer to what an experienced DevExpress developer would actually write.&lt;/p&gt;

&lt;p&gt;The MCP Server rounds out the picture, handing compatible agents the current documentation, examples and API details whenever the task needs more depth. Skills get the assistant to the right starting point; the MCP Server keeps it honest from there.&lt;/p&gt;

&lt;p&gt;Assistants will keep getting better. New models, stronger reasoning, today&amp;#39;s rough edges smoothing out. What won&amp;#39;t change is the value of context. General-purpose models will always do better when they understand the frameworks they&amp;#39;re building on, especially frameworks that move faster than any training run can keep up with.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s the thinking behind both DevExpress AI Skills and the DevExpress Documentation MCP Server. Between them, the assistant gets immediate guidance and access to current product knowledge. The payoff isn&amp;#39;t just cleaner code. It&amp;#39;s a development experience that feels less like correcting a stranger and more like working alongside someone who already knows the framework you&amp;#39;re using.&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;Further Reading&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/DevExpress/agent-skills"&gt;DevExpress AI Skills on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/Blazor/405919"&gt;DevExpress AI Skills for Coding Agents (Getting Started)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/GeneralInformation/405551/help-resources/dev-express-documentation-mcp-server-configure-an-ai-powered-assistant"&gt;Configure the DevExpress Documentation MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://community.devexpress.com/Blogs/news/archive/2025/10/16/transform-your-development-experience-with-the-devexpress-mcp-server.aspx"&gt;Introducing the DevExpress MCP Server (DevExpress Blog)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/OfficeFileAPI/14911/office-file-api"&gt;Office &amp;amp; PDF File API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.devexpress.com/XtraReports/2162/reporting"&gt;DevExpress Reporting Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Thu, 09 Jul 2026 03:23:00 Z</pubDate>
      <dc:creator>Paul Usher (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388288</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/06/02/devexpress-developer-survey-ai-impact-security-accessibility-compliance-upgrade-other-product-experience.aspx</link>
      <category domain="https://community.devexpress.com/Tags/Accessibility">Accessibility</category>
      <category domain="https://community.devexpress.com/Tags/ai">ai</category>
      <category domain="https://community.devexpress.com/Tags/Compliance">Compliance</category>
      <category domain="https://community.devexpress.com/Tags/Featured">Featured</category>
      <category domain="https://community.devexpress.com/Tags/installation">installation</category>
      <category domain="https://community.devexpress.com/Tags/licensing">licensing</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/Survey">Survey</category>
      <category domain="https://community.devexpress.com/Tags/upgrade">upgrade</category>
      <category domain="https://community.devexpress.com/Tags/ux">ux</category>
      <title>DevExpress Developer Survey — AI Impact, Regulatory Compliance, Upgrade &amp; General Product Experience</title>
      <description>&lt;p&gt;As always, we thank you for your continued support and for choosing DevExpress for your software development needs.&lt;/p&gt;&lt;p&gt;Below is&amp;nbsp;an important usage survey and we ask that you take a few minutes to submit your feedback to us. Your thoughts/comments will help us shape our future R&amp;amp;D efforts so they better align with your development objectives.&amp;nbsp;&lt;span&gt;The survey should take&amp;nbsp;&lt;/span&gt;&lt;strong&gt;about 10 minutes&lt;/strong&gt;&lt;span&gt;&amp;nbsp;to complete.&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The focus of this survey is as follows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;AI-assisted development and its impact on your enterprise&lt;/li&gt;&lt;li&gt;Regulatory compliance requirements in an ever-changing regulatory landscape&lt;/li&gt;&lt;li&gt;Satisfaction with DevExpress product delivery model and licensing&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Your Feedback Matters!&lt;/h2&gt;
&lt;div data-survey-id="67e5b107-c501-4b6b-9d32-727b9d7a3577" data-survey-auth-required="true"&gt;&lt;/div&gt;
&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;br&gt;&lt;span&gt;Dennis Garavsky&lt;/span&gt;&lt;br&gt;&lt;span&gt;Principal Product Manager&lt;/span&gt;&lt;br&gt;&lt;a href="mailto:dennis@devexpress.com" title="Email me if you have questions or suggestions"&gt;dennis@devexpress.com&lt;/a&gt;&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 02 Jun 2026 07:08:00 Z</pubDate>
      <dc:creator>Dennis Garavsky (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388290</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/05/29/application-security-documents-are-untrusted-input.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/Architecture">Architecture</category>
      <category domain="https://community.devexpress.com/Tags/ASP.NET">ASP.NET</category>
      <category domain="https://community.devexpress.com/Tags/Blazor">Blazor</category>
      <category domain="https://community.devexpress.com/Tags/Office+File+API">Office File API</category>
      <category domain="https://community.devexpress.com/Tags/Reporting">Reporting</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/WPF">WPF</category>
      <category domain="https://community.devexpress.com/Tags/XAF">XAF</category>
      <title>Application Security — Documents Are Untrusted Input</title>
      <description>&lt;h2 id="a-docx-is-a-zip-file"&gt;A .docx is a ZIP file&lt;/h2&gt;
&lt;p&gt;Open a &lt;code&gt;.docx&lt;/code&gt; file in a hex editor and the first two bytes are &lt;code&gt;PK&lt;/code&gt;. Every
modern Office format - &lt;code&gt;.docx&lt;/code&gt;, &lt;code&gt;.xlsx&lt;/code&gt;, &lt;code&gt;.pptx&lt;/code&gt; - is a ZIP archive of XML parts
and embedded resources. PDF is not a ZIP file, but just like Office formats it
is a container. When your code loads any of these file types, some complex work
is done with the content of that container: compressed streams are inflated,
references are resolved, an object graph is materialized.&lt;/p&gt;
&lt;p&gt;Most of us understand a “load document” feature to be a passive read operation:
bytes in, document model out, nothing happens that we didn’t ask for. But
loading is not passive, and the document itself dictates the shape and size of
the process. A document can instruct the loader to allocate gigabytes from a few
kilobytes on disk, to follow a path that climbs out of the extraction directory,
or to decrypt with primitives pulled in by the format specification
implicitly. The document is input, but it must be treated as untrusted input.&lt;/p&gt;
&lt;p&gt;Loading a document implies a security boundary.&lt;/p&gt;
&lt;p&gt;Here are a few examples of known attack vectors used “in the wild” against document loaders:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Decompression bombs” are small archives that inflate to a size which exhausts memory.&lt;/li&gt;
&lt;li&gt;Path traversal (“Zip Slip”) can write outside the intended directory when
extracted carelessly, by using an entry named &lt;code&gt;../../etc/something&lt;/code&gt; or &lt;code&gt;..\..\Windows\System32\something&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Symlink and device-name tricks use entries resolving to absolute paths, or to
reserved Windows names like &lt;code&gt;CON&lt;/code&gt;, &lt;code&gt;NUL&lt;/code&gt;, &lt;code&gt;PRN&lt;/code&gt;, to cause damage when extracted.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="compatible-is-not-secure"&gt;”Compatible” is not “secure”&lt;/h2&gt;
&lt;p&gt;Most applications which load documents can’t easily decide to only support the
latest formats. Of course we know not to assume that old formats are as secure
as new ones, but since support for legacy formats is required, we may believe
that if our loader algorithms are compliant with the latest standards, then we
are secure. Unfortunately, that is not always the case.&lt;/p&gt;
&lt;p&gt;For example, a PDF may be encrypted with AES-128. By name that is a modern
choice, nothing obviously legacy about it. But the PDF standard (ISO 32000-1)
requires AES-128-encrypted PDFs to derive the encryption key with MD5 and to
validate permissions with RC4. Both are long recognized as cryptographically
weak, and neither is permitted under FIPS 140-2, the US government’s
cryptographic standard. PDF readers that support AES-128 encryption need to
support MD5 and RC4, and this means that the code path that loads such documents
is not FIPS-compliant.&lt;/p&gt;
&lt;p&gt;This is what “compatible isn’t secure” actually means: you didn’t knowingly pick
something old, but your choice to support a seemingly current format carries a
hidden legacy dependency. The same is true of Office document protection: the
latest OpenXML formats support SHA-512 hashing, but they also support SHA-1 and
MD5 for legacy reasons. If you support the format, you support the legacy
algorithms too.&lt;/p&gt;
&lt;p&gt;A document format is a specification, and it can mandate approaches that your
application code can’t avoid. Your exposure is inherited from the standards you
choose to support, not introduced by any mistakes you made.&lt;/p&gt;
&lt;p&gt;In the .NET space in particular, the Windows FIPS policy used to be the main
line of defence against this problem. If you tried to load a document that
triggered a non-compliant code path, the runtime would throw an
exception. However, this safety mechanism was never perfect:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On .NET Framework with the Windows FIPS policy enabled, instantiating a
non-validated algorithm threw an exception. However, that exception was a
&lt;code&gt;TargetInvocationException&lt;/code&gt; with a message pointing at a generic non-validated
implementation, and lacking details like the document type or the offending
algorithm.&lt;/li&gt;
&lt;li&gt;On .NET 5 and later, managed FIPS enforcement was largely removed. An MD5/RC4
code path now runs with no error at all. The trap is the transition: code that
threw reliably on .NET Framework can fall silent after a routine upgrade to
.NET 5 or later, with no source change. It is easy to read that silence as the
problem having been fixed, when in fact only the diagnostic has gone, while
the code remains exactly as non -compliant, just quieter about it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that any loader code is responsible for auditing the document types
it supports. We can’t rely on the runtime to enforce compliance.&lt;/p&gt;
&lt;h2 id="office-file-api-compliance-and-safety-by-design"&gt;Office &amp;amp; PDF File API: compliance and safety by design&lt;/h2&gt;
&lt;p&gt;The latest &lt;a href="https://www.devexpress.com/products/net/office-file-api/" target="_blank" style="background-color:#ffffff;"&gt;Office &amp;amp; PDF File API&lt;/a&gt; answers both halves of the problem with a single
idea: &lt;strong&gt;compliance and structural safety should be enforced automatically and
early in the pipeline&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;At the cryptographic layer, FIPS enforcement is now explicit. On a FIPS-enforced
Windows system, opening or saving a document that depends on cryptography
prohibited by FIPS (this includes encrypted XLS or DOC files, AES-128 or ARC4
PDFs, OpenXML protection using SHA-1 or MD5 hashes) throws a
&lt;code&gt;DevExpress.Utils.OperatingSystemLevelFipsMode.ComplianceViolationException&lt;/code&gt;
&lt;em&gt;before&lt;/em&gt; processing. We made two design choices to improve upon the .NET
Framework-style handling. First,
the exception derives from &lt;code&gt;System.Security.SecurityException&lt;/code&gt;, so existing
&lt;code&gt;catch (SecurityException)&lt;/code&gt; blocks keep working unchanged. Second, the message
includes actionable details: instead of the runtime’s generic string, our
message tells you which detail of the document you attempted to load was
non-compliant, and we include suggestions for compliance.&lt;/p&gt;
&lt;p&gt;Note that on machines which are not configured with the Windows FIPS policy, or
in non-Windows environments, no cryptography validation is performed. It is
possible to force the same behavior by setting
&lt;code&gt;DevExpress.Utils.OperatingSystemLevelFipsMode.ForcedFipsMode&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, and
you can use &lt;code&gt;IsEnabled&lt;/code&gt; on the same type to detect whether the policy is
active. Setting &lt;code&gt;ForcedFipsMode&lt;/code&gt; does not change the operating system level
policy.&lt;/p&gt;
&lt;p&gt;At the structural layer, the new &lt;code&gt;SecureZipPolicy&lt;/code&gt; applies to both the low-level
data engine (&lt;code&gt;DevExpress.Utils.Zip&lt;/code&gt;) and the high-level API
(&lt;code&gt;DevExpress.Compression.ZipArchive&lt;/code&gt;). It enforces resource limits with sensible
defaults, such as maximum entry count, per-entry and total uncompressed size,
per-entry and total compression ratio to guard against “decompression bombs”, as
well as path-nesting depth. It blocks the structural attacks mentioned earlier:
path traversal, absolute paths, control characters, reserved device names,
symlinks. The write-time encryption default also changes from the old
&lt;code&gt;EncryptionType.PkZip&lt;/code&gt; to AES-256.&lt;/p&gt;
&lt;p&gt;The structural enforcement through &lt;code&gt;SecureZipPolicy&lt;/code&gt; applies to all ZIP
processing and is not tied to the FIPS policy. But on systems that do not have
FIPS enabled, a call to &lt;code&gt;SecureZipPolicy.SetEncryptionPolicy(...)&lt;/code&gt; with either
&lt;code&gt;AesRequired&lt;/code&gt; or &lt;code&gt;FipsStrict&lt;/code&gt; (the latter disallows any unknown encryption types
on read) enables the encryption policies regardless of any OS-level
configuration.&lt;/p&gt;
&lt;h2 id="some-of-these-changes-may-be-breaking"&gt;Some of these changes may be “breaking”&lt;/h2&gt;
&lt;p&gt;If you process documents on FIPS-enforced systems, code that previously ran on
.NET 5 or later may now throw an exception. We have published detailed guidance
for existing code, &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1327031/office-pdf-file-api-fips-enforcement-for-encrypted-doc-xls-and-pdf-documents" rel="nofollow noreferrer" target="_blank"&gt;Breaking Change T1327031 for the Office and PDF File
API&lt;/a&gt;
and &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1325920/new-zip-security-policy-has-been-applied-to-both-our-low-level-data-engine-devexpress" rel="nofollow noreferrer" target="_blank"&gt;Breaking Change T1325920 for the new Zip Security
Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is important to point out that these changes are only “breaking” in the sense
that they change behavior for existing implementations. They make your code
safer (very directly so in the case of the new Zip security policy), and offer
improved discoverability and auditability of violations for FIPS compliance.&lt;/p&gt;
&lt;p&gt;Without repeating the details of the guides, it is possible to adjust some of
the defaults to restore old behavior, but also to accommodate your
requirements. For example, the Zip policy has tunable parameters for resource
protection.&lt;/p&gt;
&lt;p&gt;We recommend that you take the opportunity to review your document processing
code and consider whether you can migrate to more secure formats. You can use
the new observable violations to identify documents that are currently being
processed but would not be compliant with the new policies, and then make
informed decisions.&lt;/p&gt;&lt;p&gt;&lt;span&gt;See also:&amp;nbsp;&lt;/span&gt;&lt;a href="https://community.devexpress.com/Blogs/news/archive/2026/04/17/application-security-stronger-hashes-and-safer-passwords.aspx"&gt;Application Security — Stronger Hashes and Safer Passwords&lt;/a&gt;&lt;span&gt;.&lt;/span&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id="compatibility-and-security"&gt;Compatibility and security&lt;/h2&gt;
&lt;p&gt;A common perception is that security and compatibility are always in tension. We
should state up front that this is not generally true. The new &lt;a href="https://www.devexpress.com/products/net/office-file-api/" target="_blank"&gt;Office &amp;amp; PDF File API&lt;/a&gt;
is an example of a case where the compliant choice and the convenient choice are
the same, and the new enforcement simply makes that alignment visible. For many
applications, there is no meaningful trade-off between security and
compatibility.&lt;/p&gt;
&lt;p&gt;The real conflict between security and compatibility is mostly at the legacy
surface area. Sticking to documents as the main topic of this article, that
legacy surface area can be large if you need to support old formats and old
storage standards, but it can be small if you can migrate to current formats.&lt;/p&gt;
&lt;p&gt;There are two recommendations for navigation of this tension.&lt;/p&gt;
&lt;p&gt;First, if you can use current formats, do. Migrating encrypted XLS to XLSX, DOC
to DOCX and AES-128/ARC4 PDFs to AES-256 (Revision 6) is an easy and cheap
path - speaking from the purely technical perspective of course, while
organizational and regulatory constraints may be more complex, and only you can
judge the practical complexity of migration in your environment.&lt;/p&gt;
&lt;p&gt;If legacy formats are genuinely unavoidable, then treat those documents
explicitly as untrusted input and wrap them accordingly: you now get resource
limits by default, and you can consider separating your loading or conversion
logic out to a standalone process that makes it possible to apply OS limits on
memory use or prevent network access - bearing in mind that any loading method
still parses the document, so the point of a separate process is to contain that
parse, not to avoid it.&lt;/p&gt;
&lt;p&gt;Depending on the exposure your project has to unverified input, you will find
your own balance of “defense in depth” measures, but it is important to make
active decisions about these assessments. Monitoring for violations is easy with
the new policies, and the &lt;code&gt;ResourceLimitViolation&lt;/code&gt; and &lt;code&gt;TrustBoundaryViolation&lt;/code&gt;
events exist precisely so that you gain auditability that matters particularly
in regulated, enterprise, and government environments.&lt;/p&gt;

&lt;h2&gt;Your Feedback Matters!&lt;/h2&gt;
&lt;div data-survey-id="b31c0c9e-b420-4b2b-9501-2a16d14dd7af" data-survey-auth-required="false"&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 29 May 2026 07:04:00 Z</pubDate>
      <dc:creator>Oliver Sturm (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388287</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/05/07/sboms-for-cra-compliance-in-devexpress-based-apps-preview-now-open.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/CRA">CRA</category>
      <category domain="https://community.devexpress.com/Tags/Featured">Featured</category>
      <category domain="https://community.devexpress.com/Tags/JS">JS</category>
      <category domain="https://community.devexpress.com/Tags/npm">npm</category>
      <category domain="https://community.devexpress.com/Tags/NuGet">NuGet</category>
      <category domain="https://community.devexpress.com/Tags/SBOM">SBOM</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/VCL">VCL</category>
      <title>SBOMs for CRA Compliance in DevExpress-Based Apps — Preview Now Open</title>
      <description>&lt;p&gt;If you ship apps to customers in the EU, the Cyber Resilience Act (CRA) will require a Software Bill of Materials&amp;nbsp;(SBOM) as part of your conformity documentation. SBOM generation and CRA compliance are top priorities for DevExpress, and CycloneDX SBOM files for our .NET NuGet packages are now available as a preview. We are looking for feedback to help us refine our solution before a broader release.&lt;/p&gt;
&lt;h2 id="why-this-matters"&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;Regulatory expectations around software supply chain transparency have moved from emerging practice to a baseline requirement over the past four years:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2021&lt;/strong&gt; — SBOM became a key requirement of the &lt;a href="https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/"&gt;US Executive Order 14028 on Improving the Nation&amp;#39;s Cybersecurity&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2022&lt;/strong&gt; — Microsoft open-sourced its &lt;a href="https://devblogs.microsoft.com/engineering-at-microsoft/microsoft-open-sources-software-bill-of-materials-sbom-generation-tool/"&gt;SBOM generation tool&lt;/a&gt;, signaling SBOM as a standard part of the build pipeline.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2024&lt;/strong&gt; — Germany&amp;#39;s &lt;a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03183/BSI-TR-03183-2_v2_1_0.pdf"&gt;BSI TR-03183 Part 2&lt;/a&gt; made SBOM delivery mandatory for products in scope. The &lt;a href="https://en.wikipedia.org/wiki/Cyber_Resilience_Act"&gt;EU Cyber Resilience Act (CRA)&lt;/a&gt; adopted the same requirement and entered into force on December 10, 2024, with a three-year transition period. Manufacturers selling digital products in the EU must produce and maintain SBOMs for conformity assessment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2026&lt;/strong&gt; — CRA vulnerability reporting obligations apply from September 11, 2026, ahead of full applicability on December 11, 2027.&lt;/li&gt;
&lt;/ul&gt;
&lt;img src="https://community.devexpress.com/blogs/news/2026/sbom-announcement/sbom-timeline.png" alt="sbom-timeline"&gt;
&lt;p&gt;Under the CRA, SBOM obligation falls on the manufacturer of the finished product. You can run an SBOM generation tool against your project and assemble most of what you need. But tools that read package manifests cannot reliably see bundled NPM assets, statically-linked code, or license attribution for third-party components embedded at build time. A vendor-signed SBOM can fill these gaps and serve as stronger evidence when compared to tool-derived data. Our goal is to provide SBOMs that fit cleanly into workflows you already use.&lt;/p&gt;
&lt;h2 id="what-s-available-today-preview-"&gt;What&amp;#39;s Available Today (Preview)&lt;/h2&gt;
&lt;p&gt;DevExpress publishes digitally-signed CycloneDX 1.6 SBOM files for our .NET NuGet packages. Each SBOM is updated with every build. These files use our production format and signing pipeline — &amp;quot;preview&amp;quot; status reflects ongoing metadata alignment with &lt;a href="https://www.cisa.gov/sites/default/files/2025-08/2025_CISA_SBOM_Minimum_Elements.pdf"&gt;NTIA Minimum Elements&lt;/a&gt; and &lt;a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03183/BSI-TR-03183-2_v2_1_0.pdf"&gt;BSI TR-03183&lt;/a&gt;, not file quality.&lt;/p&gt;
&lt;p&gt;Each SBOM:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lists first-party and third-party dependencies, including transitive dependencies.&lt;/li&gt;
&lt;li&gt;Includes a dependency graph for the package it describes.&lt;/li&gt;
&lt;li&gt;Lists corresponding NPM packages and their transitive dependencies when DevExpress .NET packages bundle client-side NPM assets.&lt;/li&gt;
&lt;li&gt;Marks NPM devDependencies (used during development but not shipped) with &lt;code&gt;&amp;quot;scope&amp;quot;: &amp;quot;excluded&amp;quot;&lt;/code&gt; for transparency.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These files can be consumed by standard SBOM analysis tools — including Dependency-Track, Trivy, and Grype.&lt;/p&gt;
&lt;h3 id="current-scope"&gt;Current Scope&lt;/h3&gt;
&lt;p&gt;This first release covers DevExpress .NET product packages (Blazor, WinForms, WPF, ASP.NET Core, Web Forms, MVC, and shared component libraries) published on NuGet.org for our current shipping version (v25.2.6). It does not yet cover VCL or DevExtreme product libraries, installers, demos, packages from our private NuGet feed, standalone assembly-level SBOMs, or earlier package versions. We are starting with this narrow scope so we can refine output based on customer requirements before broadening coverage.&lt;/p&gt;
&lt;div class="Note"&gt;For complete technical details — including known limitations, format specifics, and step-by-step guidance for Dependency-Track, Trivy, and Grype — see our &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1312026/software-bill-of-materials-sbom-for-devexpress-net-assemblies-nuget-packages-javascript"&gt;SBOM discussion thread&lt;/a&gt;.&lt;/div&gt;
&lt;h2 id="your-feedback-matters"&gt;Your Feedback Matters&lt;/h2&gt;
&lt;p&gt;Our SBOM preview is now open to additional participants — particularly developers working on compliance, supply chain security, or vulnerability management for applications built with DevExpress components.&lt;/p&gt;
&lt;p&gt;If you are willing to test our SBOM files in your existing tooling and share what works (and what does not), please complete the survey below. After you submit, our team contacts you with download access and next steps. Survey participants also get a direct line to the product team. If you would prefer to discuss specifics outside the survey, you can also &lt;a href="https://www.devexpress.com/ask"&gt;open a private support ticket&lt;/a&gt;.&lt;/p&gt;
&lt;div data-survey-id="8bfc2c72-365b-4638-b3c5-c89875a66d49" data-survey-auth-required="true"&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 07 May 2026 10:10:00 Z</pubDate>
      <dc:creator>Alex Chuev (DevExpress)</dc:creator>
      <dx:excerpt>If you ship apps to customers in the EU, the Cyber Resilience Act (CRA) will require an SBOM as part of your conformity documentation. SBOM generation and CRA compliance are top priorities for DevExpress, and CycloneDX SBOM files for our .NET NuGet packages are now available as a preview</dx:excerpt>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388286</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/04/27/microsoft-build-2026-is-coming.aspx</link>
      <category domain="https://community.devexpress.com/Tags/build">build</category>
      <title>Microsoft Build 2026 is coming!</title>
      <description>&lt;p&gt;...And we shall be there! Not in Seattle this year, but, for a change, in San Francisco. To be more accurate, Microsoft Build will be&amp;nbsp;at&amp;nbsp;&lt;span style="color:#000000;"&gt;Fort Mason Center in San Francisco, CA. for two full days, June 2-3. As is usual,&amp;nbsp;sessions will also be broadcast&amp;nbsp;online.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The main emphasis of Microsoft Build 2026 is going to be&amp;nbsp;AI. Not only how to use AI workflows and agents to write code and applications, but also how to provide AI capabilities to end-users to help them&amp;nbsp;use&amp;nbsp;those apps.&amp;nbsp;Naturally sessions will also cover how developers &amp;quot;supervise&amp;quot; output from AI agents&amp;nbsp;through testing, checking outputs for security, applicability, and so on. For more details on the sessions that will occur at Build, please follow &lt;a href="https://build.microsoft.com/en-US/home" title="Microsoft Build 2026 website"&gt;this link&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Like every year, DevExpress will have a booth in the Partner Hub, and we will be there to chat to attendees about what&amp;#39;s happening&amp;nbsp;with our next major releases coming up in late June, as well as how we&amp;#39;re supporting&amp;nbsp;the topics highlighted&amp;nbsp;in the Build sessions. We&amp;#39;ll talk about how we&amp;#39;re providing support for AI agents&amp;nbsp;when writing apps with our controls, as well as how we&amp;#39;re providing AI capabilities for end-users of the apps that use those&amp;nbsp;controls.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;We look forward to seeing you at our booth if you&amp;#39;re going to Microsoft Build 2026. Do&amp;nbsp;please stop by and say hello!&lt;/span&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 27 Apr 2026 15:10:00 Z</pubDate>
      <dc:creator>Julian Bucknall (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388285</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/04/24/application-security-project-dependency-version-bumps-demystified-modern-security-realities-in-net-nuget-ecosystem.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/JS">JS</category>
      <category domain="https://community.devexpress.com/Tags/npm">npm</category>
      <category domain="https://community.devexpress.com/Tags/NuGet">NuGet</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <title>Application Security — Project Dependency "Version Bumps" Demystified or Modern Security Realities in .NET / NuGet Ecosystem</title>
      <description>&lt;p&gt;In this post, I want to show you how to effectively upgrade vulnerable third-party dependencies in your projects, highlight .NET industry best practices, and also clarify how DevExpress helps you mitigate security-related risks in general. For illustration purposes, I will use a System.Security.Cryptography.Xml-related security advisory, which Microsoft published in the GitHub Advisory database &lt;a href="https://github.com/advisories/GHSA-w3x6-4m5h-cxqf" target="_blank"&gt;last week&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;You probably already know about this report from NuGet, Visual Studio, or &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1326802/vulnerable-system-security-cryptography-xml-nuget-package-versions-10-0-0-10-0-5-9-0-0-9" target="_blank"&gt;DevExpress Support Center&lt;/a&gt;. And if not, it&amp;#39;s important to note that &lt;b&gt;such reports impact every NuGet package, which has direct or transitive dependencies on the highlighted package version&lt;/b&gt; (it&amp;#39;s not specific to DevExpress directly). Ultimately, even if such external advisories do not originate from DevExpress, they may impact DevExpress packages and DevExpress customers via a chain of system or third-party sub-dependencies. Hence, it&amp;#39;s still our responsibility as a component vendor to inform our customers, improve transparency and awareness of the best practices, update problematic dependencies of affected DevExpress packages in our new releases.&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/ghsa-fixed-versions.png" alt="" style="width:2009px;height:711px;border-width:1px;border-color:#c0c0c0;border-style:solid;"&gt;&lt;p&gt;As a result of this System.Security.Cryptography.Xml advisory, you might see warnings in your Solution Explorer, NuGet Package Manager or just build output (example for .NET 8 projects). Since we also build .NET projects and use the same development tools daily, we knew about this new report right after its publication in the GitHub Advisory database on April 13-14th 2026 &lt;strong&gt;(much like you, other vendors or anyone else)&lt;/strong&gt;. Fortunately for all, a general fix (upgrade to the latest package version) is also available for all affected DevExpress and other vendor packages that were &lt;strong&gt;released prior to publishing such advisories&lt;/strong&gt; (for example, DevExpress v25.2.6 released on 07 Apr 2026 - a week before this particular report).&lt;/p&gt;&lt;div class="Note"&gt;warning NU1901: Package &amp;#39;System.Security.Cryptography.Xml&amp;#39; 8.0.2 has a known low severity vulnerability, &lt;a href="https://github.com/advisories/GHSA-w3x6-4m5h-cxqf" rel="nofollow"&gt;https://github.com/advisories/GHSA-w3x6-4m5h-cxqf&lt;/a&gt;&lt;br&gt;DevExpress.Blazor imports the transitive package of System.Security.Cryptography.Xml&lt;/div&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_9.png" alt=""&gt;&lt;h2&gt;General Fix Idea (Applicable to All Solutions)&lt;/h2&gt;&lt;p&gt;The beauty of such simple &amp;quot;version bump&amp;quot; vulnerabilities is that you can easily fix it yourself immediately - without awaiting anyone (vendors, new package versions, etc).&lt;/p&gt;&lt;p&gt;You can bump the version right in your project for affected third-party dependencies (such as Microsoft .NET System.XXX or others), as described in the &amp;quot;&lt;em&gt;How do I fix the issue?&lt;/em&gt;&amp;quot; section of the official advisory. Anyone can apply this fix at their convenience (even &amp;quot;within hours&amp;quot; of publication of the original security advisory in the CVE / GHSA database), because in this instance it&amp;#39;s literally one line of code in one or a few places only.&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/ghsa-how-to-fix.png" alt="" style="width:2258px;height:1646px;border-width:1px;border-color:#c0c0c0;border-style:solid;"&gt;&lt;p&gt;I also want to emphasize that when a vulnerability occur in a system or core .NET library, many other dependent system, .NET BCL, and vendor libraries are impacted. For example, System.Security.Cryptography.Xml is used by System.ServiceModel.Http, System.ServiceModel.Primitives, System.ServiceModel and others. They are also used directly or indirectly in a dozen more packages - all are often used in many apps of even medium complexity (I am not even talking about complex apps). You will have to update those dependencies anyway, regardless DevExpress or any other impacted package vendor/third-party.&lt;/p&gt;&lt;p&gt;Notwithstanding the negative effects of dealing with a vulnerability, NuGet and its best practices such as &lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management"&gt;&lt;strong&gt;Central Package Management (CPM)&lt;/strong&gt;&lt;/a&gt; exist in the development world - all to deal with such incidents quickly and to address modern realities effectively.

&lt;/p&gt;&lt;h2&gt;Solution #1: You Have a Few Projects Only or Are NOT Using CPM&lt;/h2&gt;&lt;div class="Note"&gt;&lt;strong&gt;Applicability&lt;/strong&gt;: Simple applications (~1-3-5 projects in your solution) targeting any .NET version, no CPM.&lt;br&gt;&lt;strong&gt;Urgency&lt;/strong&gt;: High (apply immediately).&lt;br&gt;&lt;strong&gt;Complexity&lt;/strong&gt;: Medium - Copy and maintain one code line in &lt;strong&gt;X&lt;/strong&gt; files (the number of your projects).&lt;br&gt;&lt;strong&gt;Risks&lt;/strong&gt;: Low.&lt;/div&gt;&lt;p&gt;&lt;strong&gt;If you have no &lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management"&gt;CPM&lt;/a&gt;&lt;/strong&gt;, the standard Microsoft solution is to:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1. &lt;/strong&gt;Add a direct NuGet package reference&amp;nbsp;(&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference" target="_blank"&gt;PackageReference&lt;/a&gt;&lt;/strong&gt;)&amp;nbsp;to your required projects (CSPROJ/VBPROJ);&lt;br&gt;&lt;strong&gt;2.&lt;/strong&gt; Set the patched version (&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-version" target="_blank"&gt;Version&lt;/a&gt;&lt;/strong&gt;) from the advisory (for example, 8.0.3&amp;nbsp;for&amp;nbsp;&lt;span&gt;System.Security.Cryptography.Xml and &lt;span&gt;.NET 8&amp;nbsp;&lt;/span&gt;in this case, but it can be another third-party package/version&lt;/span&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;8.0.3&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;9.0.15&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;10.0.6&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As you can see, this is a one-line solution, which you can copy into required projects where problematic direct or transitive dependencies were detected. In my example, I copied it into 1 project&amp;nbsp;only (so, 1 code line&amp;nbsp;in total to maintain).&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_10.png" alt=""&gt;&lt;h2&gt;Solution&amp;nbsp;#2: You Have Multiple Projects or Are Using CPM&lt;/h2&gt;&lt;div class="Note"&gt;&lt;strong&gt;Applicability&lt;/strong&gt;: Medium to complex applications (more than 5&amp;nbsp;projects in your solution) targeting any .NET version, CPM configured.&lt;br&gt;&lt;strong&gt;Urgency&lt;/strong&gt;: High (apply immediately).&lt;br&gt;&lt;strong&gt;Complexity&lt;/strong&gt;: Low - Copy and maintain one code line in one file.&lt;br&gt;&lt;strong&gt;Risks&lt;/strong&gt;: Low.&lt;br&gt;&lt;/div&gt;&lt;p&gt;If you have too many projects so that even the one-line solution is not practical to copy/maintain, then you must seriously consider using &lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management"&gt;CPM&lt;/a&gt;&lt;/strong&gt;&amp;nbsp;with the Directory.Packages.props file&amp;nbsp;&lt;span&gt;(&lt;/span&gt;&lt;code&gt;&amp;lt;ManagePackageVersionsCentrally&amp;gt;true&amp;lt;/ManagePackageVersionsCentrally&amp;gt;&lt;/code&gt;&lt;span&gt;)&lt;/span&gt;. CPM is the best or recommended development practice regardless this vulnerability discussion anyway.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span&gt;Regardless how many projects you have in your .NET solution (5, 100, 200, etc.), this is always a one-line solution to maintain - that is the beauty of CPM in action.&lt;/span&gt;&lt;span&gt;CPM is nowadays also super-fast to add to your non-CPM solution with AI assistants.&lt;/span&gt;&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_8.png" alt="" style="width:3524px;height:1594px;border-width:1px;border-color:#c0c0c0;border-style:solid;"&gt;&lt;h3&gt;&lt;span style="font-weight:normal;"&gt;Solution #2.1 (&lt;span&gt;PackageVersion)&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;If CPM&amp;nbsp;is enabled and&amp;nbsp;you need &lt;strong&gt;common dependencies for many different projects (not all) &lt;/strong&gt;in a repository&lt;span&gt;, the&amp;nbsp;&lt;/span&gt;&lt;span&gt;standard Microsoft solution is to:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;strong&gt;1. &lt;/strong&gt;Define a&amp;nbsp;&lt;/span&gt;&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference" target="_blank"&gt;PackageReference&lt;/a&gt;&lt;/strong&gt;element&amp;nbsp;&lt;span&gt;&lt;span style="color:#161616;"&gt;&lt;strong&gt;without the&amp;nbsp;&lt;/strong&gt;&lt;strong style="color:#404040;"&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-version" target="_blank"&gt;Version&lt;/a&gt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#161616;"&gt;attribute in&amp;nbsp;&lt;/span&gt;your required projects (CSPROJ/VBPROJ):&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span&gt;&lt;code class="language-xml"&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot;/&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; In your&amp;nbsp;&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#enabling-central-package-management" target="_blank"&gt;Directory.Packages.props&lt;/a&gt;&lt;/strong&gt; file,&amp;nbsp;add a&amp;nbsp;package version entry (&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#enabling-central-package-management" target="_blank"&gt;PackageVersion&lt;/a&gt;&lt;/strong&gt;)&amp;nbsp;and&amp;nbsp;set the patched version (&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-version" target="_blank"&gt;Version&lt;/a&gt;&lt;/strong&gt;) from the advisory (for example, 8.0.3&amp;nbsp;for&amp;nbsp;System.Security.Cryptography.Xml and&amp;nbsp;.NET 8&amp;nbsp;in this case, but it can be another third-party package/version):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageVersion Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;8.0.3&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageVersion Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;9.0.15&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;PackageVersion Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;10.0.6&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_11.png" alt=""&gt;&lt;h3&gt;Solution #2.2 (GlobalPackageReference)&lt;/h3&gt;&lt;p&gt;&lt;span&gt;If CPM&amp;nbsp;is enabled and&amp;nbsp;&lt;/span&gt;you need to&amp;nbsp;&lt;span style="color:#161616;"&gt;specify a &lt;strong&gt;package&amp;nbsp;&lt;/strong&gt;&lt;span&gt;&lt;strong&gt;to be used by every project&lt;/strong&gt; in a repository, the&amp;nbsp;&lt;/span&gt;&lt;/span&gt;standard Microsoft solution is to:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; Add a global package reference (&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#global-package-references" target="_blank"&gt;GlobalPackageReference&lt;/a&gt;&lt;/strong&gt;) to your Directory.Packages.props file.&lt;br&gt;&lt;strong&gt;2.&lt;/strong&gt;&lt;span&gt;Set the patched version (&lt;/span&gt;&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-version" target="_blank"&gt;Version&lt;/a&gt;&lt;/strong&gt;&lt;span&gt;) from the advisory (for example, 8.0.3&amp;nbsp;for&amp;nbsp;&lt;/span&gt;&lt;span&gt;System.Security.Cryptography.Xml and&amp;nbsp;.NET 8&amp;nbsp;in this case, but it can be another third-party package/version&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;GlobalPackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;8.0.3&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;GlobalPackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;9.0.15&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;GlobalPackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; Version=&amp;quot;10.0.6&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_6.png" alt="" style="width:558px;height:507px;"&gt;&lt;p&gt;If you already maintain a Directory.Packages.props file, replacing &amp;quot;PackageVersion&amp;quot; with &amp;quot;GlobalPackageReference&amp;quot; is fast too with or without AI.&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_5.png" alt=""&gt;&lt;h3 id="additional-information"&gt;Solution #2.3 (VersionOverride)&lt;/h3&gt;&lt;p&gt;&lt;span&gt;If CPM&amp;nbsp;is enabled and&amp;nbsp;&lt;/span&gt;&lt;span&gt;you need to&amp;nbsp;&lt;strong&gt;ignore the centrally defined package version&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;in a&amp;nbsp;specific project &lt;/strong&gt;of your repository,&amp;nbsp;&lt;/span&gt;&lt;span style="color:#161616;"&gt;the&amp;nbsp;&lt;/span&gt;standard Microsoft solution is to:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;1.&amp;nbsp;&lt;/strong&gt;Add a direct NuGet package reference&amp;nbsp;(&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference" target="_blank"&gt;PackageReference&lt;/a&gt;&lt;/strong&gt;)&amp;nbsp;to your required projects (CSPROJ/VBPROJ);&lt;br&gt;&lt;strong&gt;2.&lt;/strong&gt;&amp;nbsp;Set the patched version (&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#overriding-package-versions" target="_blank"&gt;VersionOverride&lt;/a&gt;&lt;/strong&gt;) from the advisory (for example, 8.0.3&amp;nbsp;for&amp;nbsp;System.Security.Cryptography.Xml and&amp;nbsp;.NET 8&amp;nbsp;in this case, but it can be another third-party package/version):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;:&amp;nbsp;&lt;code&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; VersionOverride=&amp;quot;8.0.3&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;:&amp;nbsp;&lt;code&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; VersionOverride=&amp;quot;9.0.15&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;:&amp;nbsp;&lt;code&gt;&amp;lt;PackageReference Include=&amp;quot;System.Security.Cryptography.Xml&amp;quot; VersionOverride=&amp;quot;10.0.6&amp;quot; /&amp;gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span&gt;&lt;span&gt;You can disable this feature in your&amp;nbsp;project or&amp;nbsp;Directory.Packages.props /&amp;nbsp;Directory.Build.props&amp;nbsp;files:&amp;nbsp;&lt;code class="language-xml"&gt;&amp;lt;CentralPackageVersionOverrideEnabled&amp;gt;false&amp;lt;/CentralPackageVersionOverrideEnabled&amp;gt;&lt;/code&gt;&lt;/span&gt;&lt;/span&gt;(in that case VersionOverride causes error NU1009).&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_12.png" alt=""&gt;&lt;br&gt;&lt;/p&gt;&lt;h2 id="additional-information"&gt;Solution #3: Await &amp;amp; Install a New/Fixed DevExpress Build&amp;nbsp;&lt;/h2&gt;&lt;div class="Note"&gt;&lt;strong&gt;Applicability&lt;/strong&gt;: Applications of any complexity targeting the&amp;nbsp;minimally&amp;nbsp;supported .NET version (like .NET 8), with or without CPM.&lt;br&gt;&lt;strong&gt;Urgency&lt;/strong&gt;: Low (await a few weeks).&lt;br&gt;&lt;strong&gt;Complexity&lt;/strong&gt;: Medium - Download a new version and re-test your application completely.&lt;br&gt;&lt;strong&gt;Risks&lt;/strong&gt;: Low - for the official maintenance update; High - for a hot-fix/intermediate build.&lt;/div&gt;&lt;p&gt;Affected DevExpress packages are typically updated in the next minor release according to our &lt;a href="https://docs.devexpress.com/GeneralInformation/403365/security/security?utm_source=SupportCenter&amp;amp;utm_medium=website&amp;amp;utm_campaign=docs-feedback&amp;amp;utm_content=T1326802#security-advisories-and-product-update-process"&gt;Security Advisories and Product Update Process&lt;/a&gt;. This usually takes a few weeks or so.&amp;nbsp;&lt;span&gt;If you wish, you can request a hot-fix/intermediate build as well. For example, for this particular System.Security.Cryptography.Xml vulnerability we updated our packages and published a fixed night build at&amp;nbsp;&lt;/span&gt;&lt;a href="https://downloads.devexpress.com/HotFixes/DXP/v25.2" style="color:#337ab7;"&gt;https://downloads.devexpress.com/HotFixes/DXP/v25.2&lt;/a&gt;&lt;span&gt;(review our&amp;nbsp;&lt;/span&gt;&lt;a href="https://www.devexpress.com/support/eulas/hotfix-policy.xml" style="color:#337ab7;"&gt;hot-fix policy&lt;/a&gt;&lt;span&gt;&amp;nbsp;first&amp;nbsp;before applying).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#333333;"&gt;.NET 8 is the minimally supported modern .NET / .NET Core version for DevExpress v25.2 and v26.1 NuGet libs.&amp;nbsp;Due to various reasons, we currently publish only a single .NET 8&amp;nbsp;package set, which is compatible with multiple .NET frameworks (.NET 9 and .NET 10).&lt;/span&gt;&lt;/p&gt;&lt;h3&gt;&lt;span style="color:#333333;"&gt;.NET 8-based Projects&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style="color:#333333;"&gt;&lt;strong&gt;If your project targets&amp;nbsp;&lt;/strong&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;: our&amp;nbsp;&lt;/span&gt;&lt;span style="color:#333333;"&gt;DevExpress.Printing.Core (v25.2.7+) and other affected DevExpress packages will use a non-vulnerable&amp;nbsp;&lt;/span&gt;&lt;a href="https://www.nuget.org/packages/System.Security.Cryptography.Xml/" style="color:#337ab7;"&gt;System.Security.Cryptography.Xml&lt;/a&gt;&lt;span style="color:#333333;"&gt;&amp;nbsp;dependency (&amp;gt;= 8.0.3 for .NET 8) after the official fix &lt;strong&gt;automatically&lt;/strong&gt;. &lt;a href="https://docs.devexpress.com/GeneralInformation/2529/updates/project-converter" target="_blank"&gt;Once you upgrade&lt;/a&gt; your DevExpress dependencies, &lt;span&gt;the previous Solutions #1 or #2 (manual version pinning) are no longer required - remove them from your projects.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color:#333333;"&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_13.png" alt="" style="width:927px;height:873px;border-width:1px;border-color:#c0c0c0;border-style:solid;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;h3&gt;.NET 9/10-based Projects&lt;/h3&gt;&lt;p&gt;&lt;span style="color:#333333;"&gt;&lt;strong&gt;If your project targets .NET 9/10,&lt;/strong&gt; your solutions depend on the target project SDK and target framework:&lt;/span&gt;&lt;strong style="color:#333333;"&gt;&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong style="color:#333333;"&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#available-sdks" target="_blank"&gt;Microsoft.NET.Sdk&lt;/a&gt;&amp;nbsp;&lt;/strong&gt;&lt;span style="color:#333333;"&gt;(the base SDK for .NET without additional targets like&amp;nbsp;net10.0-windows):&amp;nbsp;&lt;strong&gt;Implement&amp;nbsp;&lt;/strong&gt;&lt;span&gt;&lt;strong&gt;the  Solutions #1 or #2&lt;/strong&gt; (manual version pinning), because they&amp;nbsp;are still&amp;nbsp;required and recommended &lt;span&gt;due to how NuGet resolution operates.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;How NuGet/IDE restores third-party dependencies or which versions are used eventually in your project on your target machine are out of DevExpress&amp;nbsp;control. NuGet has its own rules where in a dependency tree with multiple parents, the &amp;quot;lowest wins&amp;quot; for the target framework of your end app. For example, DevExpress path → System.Security.Cryptography.Xml (&amp;gt;= 8.0.0) and ServiceModel path → System.Security.Cryptography.Xml (&amp;gt;= 10.0.0), then the&amp;nbsp;&lt;span&gt;result for net10 is &amp;gt;= 10.0.0 → choose 10.0.0 - lowest.&amp;nbsp;&lt;/span&gt;&lt;p style="color:#333333;"&gt;When it comes to built-in .NET dependencies (a part of the distributed .NET runtime on your machine), another &amp;quot;framework&amp;quot; layer is also considered (see this&amp;nbsp;&lt;a href="https://community.devexpress.com/blogs/news/archive/2024/07/18/dot-net-nuget-package-audit-and-false-positive-security-warnings.aspx" style="color:#337ab7;"&gt;example situation&lt;/a&gt;). It&amp;#39;s even more interesting when it comes to your third-party dependencies, which are unique for each customer app - there will be numerous dependency trees with System.ServiceModel.Http, Microsoft.Identity.Web, and other libs, for which it will be necessary to find a common denominator or override package versions.&amp;nbsp;&lt;span&gt;Ultimately, third-party dependencies and .NET runtimes are unique for each customer app and environment - this falls under the responsibility of the app developer eventually.&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#available-sdks" target="_blank"&gt;Microsoft.NET.Sdk.Web,&amp;nbsp;Microsoft.NET.Sdk.Razor&lt;/a&gt;, or&amp;nbsp;Microsoft.NET.Sdk +&amp;nbsp;net10.0-windows&lt;/strong&gt;: No manual action needed, because&amp;nbsp;&lt;span style="color:#333333;"&gt;the System.Security.Cryptography.Xml is correctly resolved to a non-vulnerable version from the SDK bundle&amp;nbsp;&lt;strong&gt;automatically&lt;/strong&gt;. This version&amp;nbsp;(for example, v10.0.9, not 9.0.15) is bundled in&amp;nbsp;your installed .NET 9/10 runtime for&amp;nbsp;your build environment/machine (of course,&amp;nbsp;&lt;/span&gt;&lt;span style="color:#333333;"&gt;if your .NET 9/10 is updated properly&lt;/span&gt;&lt;span style="color:#333333;"&gt;).&amp;nbsp;&lt;img src="https://community.devexpress.com/blogs/news/image_14.png" alt=""&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Frequently Asked Questions (FAQ)&lt;/h2&gt;&lt;h3&gt;Does DevExpress release builds when it already &amp;quot;knows&amp;quot; about a vulnerability such as System.Security.Cryptography.Xml 8.0.2?&lt;/h3&gt;&lt;p&gt;No. In this instance, DevExpress v25.2.6 was released on 07 Apr 2026, many days before the aforementioned vulnerability was even published/known to the world. &lt;/p&gt;&lt;p&gt;DevExpress uses a multi-layered scanning strategy for every PR (code repositories and container images are continuously and automatically scanned for vulnerabilities during the CI/CD process) &lt;strong&gt;prior to release&lt;/strong&gt;. This includes Static Application Security Testing (SAST) for product source code, Software Composition Analysis (SCA) for vulnerable third-party libraries/license compliance, antiviral software installation and artifact scanning. High-risk vulnerabilities trigger an automatic &amp;#39;Build Fail&amp;#39;. DevExpress employs a combination of commercial and internally managed security tools (including, but not limited to Veracode, Dependabot, CodeQL, NuGet Audit, VirusTotal, etc).&lt;/p&gt;&lt;p&gt;For more information, please review &lt;a href="https://www.devexpress.com/support/information-security.xml" style="color:#337ab7;"&gt;Information Security&lt;/a&gt; and &lt;a href="https://docs.devexpress.com/GeneralInformation/403365/security/security" style="color:#337ab7;"&gt;Security - What You Need to Know&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;How often similar security advisories for system/core or popular 3rd-party packages are reported?&lt;/h3&gt;&lt;p&gt;Quite many every day - it&amp;#39;s best to estimate it for yourself at &lt;a href="https://github.com/advisories" target="_blank"&gt;https://github.com/advisories&lt;/a&gt; (filter by NuGet, NPM, or other keywords). This is also not the first and not the last vulnerability in a system/core library. For example, 3 security advisories were published for System.Security.Cryptography.Xml alone in less than 2 years. And I am not even referring to others in popular SQL Client, JSON, OData, and other libraries with even more dependencies.&lt;/p&gt;&lt;p&gt;To better understand the situation, let&amp;#39;s make a thought experiment: imagine that a vendor started publishing new official builds in response to each and every security advisory immediately. For this (in theory), one would need the previous official build, bump the affected NuGet package version (such as System.Security.Cryptography.Xml), re-build, re-run automatic tests and security checks, and publish a new official build. As a result of this experiment, customers would need to deal with 3-5 new minors a week. That rough number is only considering the current CVE/GHSA update rate for .NET - for JS/NPM it would be even more frequent. As you may understand, not many customers or businesses would want such an update carousel.&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_4.png" alt="" style="border-width:1px;border-color:#c0c0c0;border-style:solid;"&gt;&lt;h3&gt;How often DevExpress &amp;quot;bumps versions&amp;quot; of their .NET packages internally in response to security advisories for external NuGet packages?&lt;/h3&gt;&lt;p&gt;Multiple times every month or so. To give you a full picture, DevExpress v25.2 .NET packages depend on over 150+ system/core .NET packages (based on our &amp;quot;c:\Program Files\DevExpress 25.2\Components\Sources\Directory.Packages.props&amp;quot; file or our public &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1312026/software-bill-of-materials-sbom-for-devexpress-net-assemblies-nuget-packages-javascript" target="_blank"&gt;SBOM artifacts&lt;/a&gt;, which you can check for yourself). Our .NET packages often include our JS packages as assets, these JS packages depend on external JS/NPM packages, and so on - you got the idea or the high chances of a &amp;quot;version bump&amp;quot; at such a scale.&lt;/p&gt;&lt;p&gt;Good news is that we heavily rely on CPM, so this &amp;quot;version bumping&amp;quot; itself is now a mechanical routine - it just takes time and discipline from our product teams. This is basically what every developer of any serious or complex application/solution is doing nowadays, because security matters.&lt;/p&gt;&lt;h3&gt;Why does not DevExpress release a new/fixed build within hours after a security advisory is published?&lt;/h3&gt;&lt;p&gt;As noted in Method #3, we follow our &lt;a href="https://docs.devexpress.com/GeneralInformation/403365/security/security#security-advisories-and-product-update-process" style="color:#337ab7;"&gt;Security Advisories and Product Update Process&lt;/a&gt; and update affected DevExpress packages  in the next minor release (in a few weeks or so &lt;strong&gt;on purpose&lt;/strong&gt;). All our builds must pass standard testing procedures. We do our best to test our software and it takes time (for example, we intentionally did not release v25.2.7 &amp;quot;within hours&amp;quot;). We simply do not want our customers rely on poorly tested software (and potentially experience bigger issues with the upgrade). &lt;/p&gt;&lt;p&gt;Fortunately, the current release cadence suits the majority of our customers and proved itself over the years well. In urgent cases, customers can either apply a one-line solution in their projects or request a hot-fix/intermediate build. That is also why Microsoft has Patch Tuesday &lt;strong style="color:#333333;"&gt;monthly &lt;/strong&gt;and NOT &amp;quot;hourly&amp;quot;, and many other vendors follow similar security and testing protocols. Otherwise, it would be a mess for all vendors and customers in the .NET ecosystem, for JS ecosystem it would be even worse due to a different NPM package update strategies and the number of updated packages. &lt;strong&gt;In other words, the solution should never be worse than the original problem.&lt;/strong&gt;&lt;/p&gt;&lt;h2 id="additional-information" style="color:#505050;font-weight:600;"&gt;See Also&lt;/h2&gt;&lt;p&gt;Microsoft clarified this general pattern in their blogs and docs, because this version upgrade is needed regularly:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/nugetaudit-2-0-elevating-security-and-trust-in-package-management/#how-to-upgrade-transitive-packages" rel="nofollow"&gt;NuGetAudit 2.0: Elevating Security and Trust in Package Management&lt;/a&gt; (see the &amp;quot;How to upgrade transitive packages&amp;quot; section)&lt;/li&gt;&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management#overriding-package-versions" rel="nofollow"&gt;Overriding Package Versions&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We also described how to fix this and similar customer issues at &lt;a href="https://community.devexpress.com/blogs/news/archive/2024/07/18/dot-net-nuget-package-audit-and-false-positive-security-warnings.aspx"&gt;.NET — About NuGet Package Audit and &amp;quot;False-Positive&amp;quot; Security Warnings&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Please let me know if you have any DevExpress-related questions or suggestions.&lt;/p&gt;&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;br&gt;&lt;span&gt;Dennis Garavsky&lt;/span&gt;&lt;br&gt;&lt;span&gt;Principal Product Manager&lt;/span&gt;&lt;br&gt;&lt;a href="mailto:dennis@devexpress.com" title="Email me if you have questions or suggestions"&gt;dennis@devexpress.com&lt;/a&gt;&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 24 Apr 2026 09:44:00 Z</pubDate>
      <dc:creator>Dennis Garavsky (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388284</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/04/17/application-security-stronger-hashes-and-safer-passwords.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/Architecture">Architecture</category>
      <category domain="https://community.devexpress.com/Tags/ASP.NET">ASP.NET</category>
      <category domain="https://community.devexpress.com/Tags/Blazor">Blazor</category>
      <category domain="https://community.devexpress.com/Tags/Dashboard">Dashboard</category>
      <category domain="https://community.devexpress.com/Tags/Data+Access">Data Access</category>
      <category domain="https://community.devexpress.com/Tags/Office+File+API">Office File API</category>
      <category domain="https://community.devexpress.com/Tags/Reporting">Reporting</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/WPF">WPF</category>
      <category domain="https://community.devexpress.com/Tags/XAF">XAF</category>
      <title>Application Security — Stronger Hashes and Safer Passwords</title>
      <description>&lt;p&gt;Every application that stores passwords makes an implicit bet: that the hashing
algorithm it chose will remain strong enough to resist attacks for as long as
those hashes exist. It’s worth revisiting that bet regularly. This post walks
through the reasoning behind some recent changes we’ve made to password hashing
across DevExpress components, and covers broader principles that apply whether
you use our tools or not.&lt;/p&gt;
&lt;h2 id="a-quick-primer-on-password-hashing"&gt;A Quick Primer on Password Hashing&lt;/h2&gt;
&lt;p&gt;A hash function takes an input - say, a password - and produces a fixed-length
string that looks nothing like the original. The critical property is that this
transformation is one-way: given the hash, it should be computationally
impossible to recover the original password.&lt;/p&gt;
&lt;p&gt;Here’s a concise example using the .NET class &lt;code&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes?view=net-10.0" target="_blank"&gt;Rfc2898DeriveBytes&lt;/a&gt;&lt;/code&gt;, which
implements the PBKDF2 algorithm:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp" data-line-numbers="true"&gt;using System.Security.Cryptography;

byte[] salt = RandomNumberGenerator.GetBytes(16);
int iterations = 600_000;

byte[] hash = Rfc2898DeriveBytes.Pbkdf2(
    password: &amp;quot;correct-horse-battery-staple&amp;quot;,
    salt: salt,
    iterations: iterations,
    hashAlgorithm: HashAlgorithmName.SHA512,
    outputLength: 64);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The salt ensures that identical passwords produce different hashes. The
iteration count controls how much computational work is required to produce each
hash, making brute-force attacks proportionally more expensive. And the choice
of hash algorithm matters more than you might think, as I’ll discuss below.&lt;/p&gt;&lt;div class="Note"&gt;&lt;span style="color:#333333;"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: The low-level code above is intended primarily for demonstration purposes. For production-ready password hashing and storage, you may&amp;nbsp;end up with a more sophisticated implementation based on Rfc2898DeriveBytes and other built-in .NET helpers. For instance, in modern ASP.NET Core&amp;nbsp;applications with Identity (Blazor, Web API, Minimal APIs, ASP.NET Core MVC, Razor Pages, gRPC), you can use&amp;nbsp;&lt;/span&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.passwordhasher-1?view=aspnetcore-10.0" style="color:#337ab7;"&gt;PasswordHasher&amp;lt;TUser&amp;gt;&lt;/a&gt;&amp;nbsp;&lt;span style="color:#333333;"&gt;(Microsoft&amp;#39;s recommendation -&amp;nbsp;&lt;/span&gt;&lt;a href="https://learn.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing?view=aspnetcore-10.0" target="_blank"&gt;see below&lt;/a&gt;&lt;span style="color:#333333;"&gt;)&lt;/span&gt;&lt;span style="color:#333333;"&gt;. Similar APIs can be used for other platforms: our XAF framework (for Blazor/WinForms UI and Web API)&amp;nbsp;includes a&amp;nbsp;&lt;/span&gt;&lt;a href="https://docs.devexpress.com/eXpressAppFramework/112649/data-security-and-safety/security-system/authentication/passwords-in-the-security-system#access-passwords-in-code" style="color:#337ab7;"&gt;PasswordCryptographer&lt;/a&gt;&lt;span style="color:#333333;"&gt;&amp;nbsp;helper powered by Rfc2898DeriveBytes&amp;nbsp;with additional configuration options.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="color:#333333;"&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_3.png" alt=""&gt;&lt;br&gt;&lt;/span&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id="document-protection-sha-512-for-office-documents"&gt;Document Protection: SHA-512 for Office Documents&lt;/h2&gt;
&lt;p&gt;If you’ve used document protection in Word-compatible file formats, you know
that it’s an “advisory” protection mechanism. It signals that a document
shouldn’t be edited, but it’s ultimately up to the consuming application to
check and enforce that flag. Document protection is not an encryption mechanism
designed to provide strong security.&lt;/p&gt;
&lt;p&gt;Even so, the protection password hash is stored inside the document. While these
passwords are often shared with collaborators and hopefully aren’t reused for
online banking, there’s still no good reason to make it easy for someone to
brute-force the original password. In v26.1, our
&lt;a href="https://docs.devexpress.com/OfficeFileAPI/DevExpress.XtraRichEdit.API.Native.Document.Protect.overloads" rel="nofollow noreferrer" target="_blank"&gt;&lt;code&gt;Document.Protect&lt;/code&gt;&lt;/a&gt;
method&amp;nbsp;uses the strongest hash function supported by the Office format, as
&lt;a href="https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/fb220a2f-88d4-488c-a9b7-e094756b6699" rel="nofollow noreferrer" target="_blank"&gt;documented by
Microsoft&lt;/a&gt;. You
can find the &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1322324/document-protection-password-protected-documents-now-use-sha-512" rel="nofollow noreferrer" target="_blank"&gt;full details in our breaking change notice&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;See Also:&amp;nbsp;&lt;/strong&gt;&lt;a href="https://community.devexpress.com/Blogs/news/archive/2026/05/29/application-security-documents-are-untrusted-input.aspx"&gt;Application Security — Documents Are Untrusted Input&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="digital-signatures-ocspclient-defaults-to-sha-512"&gt;Digital Signatures: OcspClient Defaults to SHA-512&lt;/h2&gt;
&lt;p&gt;Password hashes aren’t the only place where hash strength matters. Digital
signatures rely on hash functions too, and a weak hash can undermine the
integrity guarantees that a signature is supposed to provide. With v26.1, the
&lt;code&gt;OcspClient&lt;/code&gt; class used for OCSP (Online Certificate Status Protocol) responses
in our digital signature workflow &lt;a href="https://supportcenter.devexpress.com/ticket/details/t1322321/digital-signatures-ocspclient-now-uses-sha-512-by-default" rel="nofollow noreferrer" target="_blank"&gt;now uses SHA-512 by
default&lt;/a&gt;. This
is a straightforward upgrade that brings the default in line with current best
practices.&lt;/p&gt;
&lt;h2 id="xaf-security-system-sha-512-with-600000-iterations"&gt;XAF Security System: SHA-512 with 600000 Iterations&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://docs.devexpress.com/eXpressAppFramework/113366/data-security-and-safety/security-system" target="_blank"&gt;XAF’s built-in Security System&lt;/a&gt; handles full user account management, including
password storage. This is the scenario where hashing strength matters most,
since these are real user passwords protecting real application access.&lt;/p&gt;
&lt;p&gt;With v26.1, we’re configuring the default hash mechanism to use SHA-512 with
600000 iterations of PBKDF2. This is a significant step up from previous
defaults. Because this change affects how stored passwords are verified, it can be considered a&amp;nbsp;&lt;a href="https://supportcenter.devexpress.com/ticket/details/t1325657/xaf-security-a-stronger-password-hashing-algorithm-has-been-configured" rel="nofollow noreferrer" target="_blank"&gt;breaking change (full documentation and migration guidance is
available
here&lt;/a&gt;). We’ll
provide detailed steps to help you update your application and migrate existing
password hashes to the new configuration.&lt;/p&gt;
&lt;h2 id="why-these-specific-choices"&gt;Why These Specific Choices?&lt;/h2&gt;
&lt;p&gt;You might wonder: why SHA-512? Why 600000 iterations? Why not something else entirely?&lt;/p&gt;
&lt;p&gt;The short answer is that we’re following the &lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html" rel="nofollow noreferrer" target="_blank"&gt;OWASP Password Storage Cheat
Sheet&lt;/a&gt;,
specifically its guidance on PBKDF2 for environments that require FIPS-140
compliance. OWASP is widely regarded as the authoritative source for application
security best practices, and their recommendations are well-researched,
regularly updated, and practical.&lt;/p&gt;
&lt;p&gt;If you handle passwords in your own applications - whether for storage,
verification, or any other processing - reading the OWASP guidance in detail is
highly recommended. It’s clearly written and covers important related concepts like
the salts mentioned above (random values mixed into each hash to prevent precomputed attacks)
and peppers (application-level secrets added as an extra layer of defense).&lt;/p&gt;
&lt;p&gt;That said, there are two important points worth expanding on in the context of
the choices we made.&lt;/p&gt;&lt;div class="Note"&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: As of this writing, SHA-256 remains a fully valid, supported, and widely recommended choice (including the current OWASP and NIST guidance). Despite a larger output size, SHA-512 can be as fast as SHA-256 on modern 64-bit hardware. In practice, the overall security is driven by many more factors (like iteration count, rate limiting, and algorithm design, etc.) than the output length of a specific SHA-XXX algorithm.&lt;br&gt;&lt;/div&gt;
&lt;h2 id="point-1-iteration-count-is-a-trade-off-and-rate-limiting-is-non-negotiable"&gt;Point 1: Iteration Count Is a Trade-Off, and Rate Limiting Is Non-Negotiable&lt;/h2&gt;
&lt;p&gt;The OWASP guidance for PBKDF2 with SHA-512 suggests an iteration count that is
actually somewhat lower than the 600000 we adopted for XAF. That’s because
iteration count is a trade-off between security and performance: more iterations
mean more work for an attacker, but also more work for your server on every
legitimate login.&lt;/p&gt;
&lt;p&gt;To make an informed choice, think about where and when your application computes
password hashes. How frequently does it happen? What does the load look like
during peak usage? Measure how long a single hash computation takes on your
hardware. These data points, combined with the OWASP guidance, will help you
find the right balance for your specific situation.&lt;/p&gt;
&lt;p&gt;This line of thinking leads to a critical complementary measure: rate
limiting. No matter how strong your hash function is, if an attacker can make
unlimited login attempts, they have unlimited opportunities to guess
passwords. Rate limiting caps the number of attempts in a given time window,
making brute-force attacks impractical even against weaker hashes.&lt;/p&gt;
&lt;p&gt;You want this at two levels. At the application level, lock out individual
accounts after repeated failures. ASP.NET Core Identity supports this through
the
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.lockoutoptions.maxfailedaccessattempts" rel="nofollow noreferrer" target="_blank"&gt;&lt;code&gt;LockoutOptions.MaxFailedAccessAttempts&lt;/code&gt;&lt;/a&gt;
property in the &lt;code&gt;IdentityOptions.Lockout&lt;/code&gt; configuration, and the XAF Security
System offers equivalent functionality with the
&lt;a href="https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.Security.ISecurityUserLockout" rel="nofollow noreferrer" target="_blank"&gt;&lt;code&gt;ISecurityUserLockout&lt;/code&gt;&lt;/a&gt;
interface. At the edge, protect your infrastructure from being overwhelmed, by
using a WAF (Web Application Firewall), Cloudflare, or a reverse proxy like
Nginx or Caddy with built-in rate limiting. Use both techniques: account lockout
and infrastructure protection solve different problems.&lt;/p&gt;
&lt;h2 id="point-2-pbkdf2-vs-memory-hard-algorithms---the-state-of-the-art"&gt;Point 2: PBKDF2 vs. Memory-Hard Algorithms - the State of the Art&lt;/h2&gt;
&lt;p&gt;If you read the OWASP cheat sheet closely, you’ll notice that PBKDF2 is
positioned as the last choice in their ranked list of recommended
algorithms. OWASP explicitly notes that PBKDF2 is the best option only when
FIPS-140 compliance is required.&lt;/p&gt;
&lt;p&gt;The reason is architectural. PBKDF2 is a CPU-bound algorithm, its security
relies on requiring many sequential computations. The problem is that modern
GPUs and purpose-built ASIC chips can perform these computations orders of magnitude
faster than general-purpose CPUs. An attacker with access to specialized
hardware can brute-force PBKDF2 hashes far more efficiently than a defender’s
server can compute them. Some hardware of this nature can be rented conveniently
in the cloud, making it accessible to a wide range of attackers.&lt;/p&gt;
&lt;p&gt;OWASP’s preferred alternatives are memory-hard algorithms like Argon2id and
scrypt. These algorithms are designed to require large amounts of memory during
computation, which makes them resistant to GPU and ASIC attacks. Specialized
hardware is fast at computation but has limited memory bandwidth, which levels
the playing field.&lt;/p&gt;
&lt;p&gt;However, memory-hard algorithms come with trade-offs of their own. Consider the
OWASP-recommended minimum for Argon2id: 19 MiB of memory and 2 iterations per
hash computation. If you need to support just 100 concurrent login attempts,
that’s already 1.9 GiB of memory dedicated solely to password hashing. The
calculation for your maximum concurrent user count becomes a fundamentally
different exercise than with CPU-bound algorithms.&lt;/p&gt;
&lt;p&gt;There’s also a practical consideration in the .NET ecosystem: Argon2id and
scrypt are not natively supported by the .NET runtime. Using them requires
third-party libraries, which introduces dependencies on external maintainers for
security-critical code. Many developers and organizations reasonably conclude
that a well-configured, natively supported algorithm - PBKDF2 with SHA-512 and a
high iteration count - is preferable to taking on that dependency risk. This is
the reasoning behind our choice for DevExpress products.&lt;/p&gt;
&lt;h2 id="the-bottom-line"&gt;The Bottom Line&lt;/h2&gt;
&lt;p&gt;Password hashing is one of those areas where “good enough” has a shelf
life. Algorithms that were considered strong a few years ago may no longer
provide adequate protection against modern hardware. The updates we’re shipping
in v26.1 reflect current best practices, and we encourage you to review your own
applications with the same critical eye, if you handle passwords in any capacity.&lt;/p&gt;

&lt;h2&gt;Your Feedback Matters!&lt;/h2&gt;
&lt;div data-survey-id="b31c0c9e-b420-4b2b-9501-2a16d14dd7af" data-survey-auth-required="false"&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 17 Apr 2026 11:00:00 Z</pubDate>
      <dc:creator>Oliver Sturm (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388282</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/04/02/application-security-why-you-cant-protect-your-connection-string.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/Architecture">Architecture</category>
      <category domain="https://community.devexpress.com/Tags/Backend">Backend</category>
      <category domain="https://community.devexpress.com/Tags/Data+Access">Data Access</category>
      <category domain="https://community.devexpress.com/Tags/database">database</category>
      <category domain="https://community.devexpress.com/Tags/Desktop">Desktop</category>
      <category domain="https://community.devexpress.com/Tags/Frontend">Frontend</category>
      <category domain="https://community.devexpress.com/Tags/Middle+Tier">Middle Tier</category>
      <category domain="https://community.devexpress.com/Tags/ORM">ORM</category>
      <category domain="https://community.devexpress.com/Tags/RDBMS">RDBMS</category>
      <category domain="https://community.devexpress.com/Tags/REST">REST</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/webapi">webapi</category>
      <category domain="https://community.devexpress.com/Tags/windows">windows</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/WPF">WPF</category>
      <title>Application Security — Why One Does Not Simply Protect a Data Store Connection String and Other Login Credentials?</title>
      <description>&lt;p&gt;A developer asks: “How do I protect my connection string in a desktop
application?”&lt;/p&gt;
&lt;p&gt;This is one of the most common security questions in .NET development, and it
sounds like it should have a straightforward answer. But there is a fundamental
problem we need to analyze.&lt;/p&gt;
&lt;p&gt;When an application connects to a service, SQL Server, a REST API, any service
at all, it needs credentials. That’s unavoidable.&lt;/p&gt;
&lt;p&gt;Sometimes those are long-lived “root” credentials: usernames and passwords, API
keys, client secrets. Sometimes they’re derived tokens with limited scope and
lifetime. Sometimes they come from the environment, like Windows
Authentication. The exact form doesn’t matter.&lt;/p&gt;
&lt;p&gt;What matters is this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;At the moment your application uses those credentials, it has everything it
needs to act on them.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And that leads directly to a part which is easily underestimated.&lt;/p&gt;
&lt;h2 id="the-reality-of-using-credentials"&gt;The reality of using credentials&lt;/h2&gt;
&lt;p&gt;If your application can use credentials, then anything that can control your
application can use them too.&lt;/p&gt;
&lt;p&gt;On a typical desktop system, the user fully controls the machine. That means
they can inspect memory, attach a debugger, intercept calls, or simply drive the
application in ways you didn’t intend.&lt;/p&gt;
&lt;p&gt;To illustrate: a connection string used by an application through Entity
Framework or ADO.NET can typically be found in plain text in a process memory
dump, using standard tools like WinDbg or dotnet-dump. No reverse engineering
required.&lt;/p&gt;
&lt;p&gt;Managed enterprise environments can raise the cost of such attacks
significantly, through tools like AppLocker, WDAC, or restricted user
accounts. But the fundamental dynamic does not change: the complexity of
exploitation increases, while the possibility remains. This applies to WPF or
Windows Forms applications, other types of native applications, and also to
server applications like those served by a web server.&lt;/p&gt;
&lt;p&gt;If your application uses a secret to access a remote resource, you can try to
hide the secret. You can encrypt it at rest. You can obfuscate it.&lt;/p&gt;
&lt;p&gt;But none of that changes the core fact: &lt;strong&gt;the application itself is already
authenticated, at the point where it works with the remote resource&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;An attacker doesn’t need to extract the password if they can just make your
application run the query, call the API, or perform the operation on their
behalf.&lt;/p&gt;
&lt;p&gt;This is a key point that many discussions miss. The problem is not just that
secrets can be stolen. It’s that the application already embodies the permission
those secrets grant.&lt;/p&gt;
&lt;h2 id="so-can-we-protect-connection-strings"&gt;So can we protect connection strings?&lt;/h2&gt;
&lt;p&gt;Not in the way people often expect. If someone can run code on the same machine,
under the same user account as your application, they can make your application
do anything it is allowed to do. That’s not a framework limitation or a missing
feature. It’s simply how software works.&lt;/p&gt;
&lt;p&gt;Microsoft’s own guidance reflects this reality indirectly. For example, Entity
Framework explicitly recommends &lt;strong&gt;not&lt;/strong&gt; relying on storing connection strings
with sensitive information directly in application configuration, and instead
using more secure patterns where possible (see: &lt;a href="https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/ef/security-considerations#secure-the-connection-string" rel="nofollow noreferrer" target="_blank"&gt;Entity Framework Core
connection string
guidance&lt;/a&gt;). Guidelines
for ASP.NET Core go in the same direction, &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-10.0#security-and-user-secrets" rel="nofollow noreferrer" target="_blank"&gt;you can read them
here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For development, Microsoft recommends the use of &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-10.0" rel="nofollow noreferrer" target="_blank"&gt;the Secret Manager
tool&lt;/a&gt;. Note
that it is meant to be used for development purposes only! Local storage
mechanisms are for convenience and isolation - not for real security
boundaries. The fundamental issue isn’t changed by the use of these tools:
locally stored secrets are not safe from the user of the machine.&lt;/p&gt;
&lt;p&gt;The .NET platform itself does not provide a single, clear, production-ready
solution for secure storage on client machines. Its built-in configuration
system can read values from many sources, but it does not make those sources
secure.&lt;/p&gt;
&lt;p&gt;In Microsoft’s more current guidance, the picture does not fundamentally
change. For example, documentation for
&lt;a href="https://learn.microsoft.com/en-us/entra/msal/dotnet/how-to/token-cache-serialization?tabs=desktop" rel="nofollow noreferrer" target="_blank"&gt;MSAL.NET&lt;/a&gt;,
specifically for desktop apps, recommends persisting token caches locally and,
on Windows, protecting them using DPAPI or similar mechanisms. In other words,
the responsibility for secure storage remains with the application and the
underlying operating system rather than the .NET framework itself.&lt;/p&gt;
&lt;p&gt;Integrating facilities such as DPAPI or the Windows Credential Manager with
application configuration often requires additional code or libraries, as there
is no standard built-in bridge between secure OS storage and the .NET
configuration system. The documentation for MSAL.NET, linked just above,
includes mention of the &lt;code&gt;Microsoft.Identity.Client.Extensions.Msal&lt;/code&gt; NuGet
package, which has persistence support for token caches. The best recommendation
for general purpose secret persistence however is &lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.protecteddata?view=windowsdesktop-10.0" rel="nofollow noreferrer" target="_blank"&gt;the ProtectedData
class&lt;/a&gt;. There
are third party NuGet packages in this space as well, but trustworthiness is a
concern for such an important feature.&lt;/p&gt;
&lt;h2 id="what-actually-helps"&gt;What actually helps&lt;/h2&gt;
&lt;p&gt;Once you accept that secrets inside a client application cannot be fully
protected, the question changes. It’s no longer &lt;em&gt;how do I hide this credential?&lt;/em&gt;
but &lt;em&gt;how do I limit the damage when it’s used by the wrong person?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are two strategies, and they work best together.&lt;/p&gt;
&lt;h3 id="make-credentials-less-worth-stealing"&gt;Make credentials less worth stealing&lt;/h3&gt;
&lt;p&gt;If a credential is compromised, how much damage can it do? The answer should be:
as little as possible.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Restrict permissions to the minimum required&lt;/li&gt;
&lt;li&gt;Scope credentials to specific operations&lt;/li&gt;
&lt;li&gt;Prefer short-lived tokens over long-lived root secrets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where modern identity systems earn their keep, whether
cloud-based or self-hosted. OpenID Connect providers, managed identities, token
services, they don’t hide secrets better. They issue weaker, narrower ones, secrets of
much lower value to a potential hacker.&lt;/p&gt;
&lt;h3 id="reduce-the-blast-radius"&gt;Reduce the blast radius&lt;/h3&gt;
&lt;p&gt;If a credential or an application is compromised, how far can the damage spread?
There are two ways to constrain it: change the architecture, or change the
environment.&lt;/p&gt;
&lt;p&gt;Changing the architecture is the most powerful option: instead of giving a
client direct access to a database, you introduce a service layer. The client
talks to an API, the API talks to the database.&lt;/p&gt;
&lt;p&gt;Now the high-value credentials live in a controlled environment: on a server you
manage, not on every user’s machine. The API of that server, the services it
publishes, define what is possible. A connection string allows arbitrary SQL. An
API should not.&lt;/p&gt;
&lt;p&gt;A service layer also solves another problem: it decouples client authentication
from backend authentication. If your database or backend service only supports
long-lived credentials, the API can still offer token-based, short-lived access
to clients. The powerful credential stays on the server, the client never sees
it.&lt;/p&gt;
&lt;p&gt;The narrower and more specific your API is, the less damage can be done. Of
course the client will still need credentials to access the API, but with a
careful structure potential damage is very limited even if a client is fully
compromised.&lt;/p&gt;
&lt;p&gt;This idea can also be extended to the client environment itself. In managed
Windows environments, administrators can reduce the blast radius further by
restricting what users are allowed to do on the machine: limiting which
applications can be executed (e.g. via AppLocker or Windows Defender Application
Control), enforcing restricted user accounts, or even locking systems into
kiosk-style operation. These measures do not eliminate the underlying issue, but
they can make it significantly harder to exploit in practice by removing the
ability to run arbitrary code alongside the application.&lt;/p&gt;
&lt;p&gt;A service layer also opens up an entire category of server-side protections that
are simply impossible to enforce on a client machine: rate limiting, anomaly
detection, device or IP binding, audit logging. These don’t prevent credential
misuse on their own, but they make abuse observable and containable - and they
only become options once privileged access has moved off the client.&lt;/p&gt;
&lt;h2 id="the-path-most-people-take"&gt;The path most people take&lt;/h2&gt;
&lt;p&gt;In practice, developers rarely jump straight to architectural changes. They tend
to go through a series of steps.&lt;/p&gt;
&lt;p&gt;First, they look for ways to avoid handling credentials at all, using Windows
Authentication or similar mechanisms. If that works, it’s ideal.&lt;/p&gt;
&lt;p&gt;If this is not an option, the second-best approach is to avoid embedding
powerful credentials directly, introducing identity providers or token-based
access instead.&lt;/p&gt;
&lt;p&gt;As long as any credentials need to be stored on the client machine, secure
storage becomes a concern - options have been discussed above.&lt;/p&gt;
&lt;p&gt;At this point, many developers feel they’ve “secured” their application. But if
you follow the logic from earlier, you arrive at an uncomfortable conclusion:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;None of these steps prevent a determined attacker with control over the
machine from using the application’s access.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And that’s where the final step becomes unavoidable.&lt;/p&gt;
&lt;h2 id="when-architecture-is-the-only-real-fix"&gt;When architecture is the only real fix&lt;/h2&gt;
&lt;p&gt;If the risk still matters - and in many systems it does! - the only meaningful
improvement comes from changing the shape of the system.&lt;/p&gt;
&lt;p&gt;Move privileged access away from the client. Introduce services. Narrow what
those services do.&lt;/p&gt;
&lt;p&gt;This doesn’t make your system invulnerable. But it changes the game from &lt;em&gt;anyone
with access can do anything&lt;/em&gt; to &lt;em&gt;even with access, only specific actions are
possible&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That’s a huge difference.&lt;/p&gt;
&lt;p&gt;I strongly recommend reading our &lt;a href="https://community.devexpress.com/Tags/rbac" target="_blank"&gt;related blog series&lt;/a&gt;&amp;nbsp;(starting with &lt;a href="https://community.devexpress.com/blogs/news/archive/2024/02/09/modern-desktop-apps-and-their-complex-architectures.aspx" target="_blank" rel="nofollow noreferrer"&gt;Modern Desktop Apps And Their Complex Architectures&lt;/a&gt;) and&amp;nbsp;documentation pages about the &lt;a href="https://docs.devexpress.com/eXpressAppFramework/403394/backend-web-api-service" rel="nofollow noreferrer" target="_blank"&gt;Backend Web API Service&lt;/a&gt;, &lt;a href="https://docs.devexpress.com/WindowsForms/405145/data-access-security" rel="nofollow noreferrer" target="_blank"&gt;Data Access
Security&lt;/a&gt;,
and &lt;a href="https://docs.devexpress.com/eXpressAppFramework/404691/security-considerations/general-security-considerations#security-tiers" rel="nofollow noreferrer" target="_blank"&gt;XAF Security
Tiers&lt;/a&gt;. They go into more detail about how to design systems with these principles in
mind. Of course this approach is complex and specific to your application, its
architecture and requirements. Please don’t hesitate to reach out if we can
help!&lt;/p&gt;
&lt;h2 id="a-common-misconception-securestring"&gt;A common misconception: .NET &amp;quot;Secure&amp;quot; String&lt;/h2&gt;
&lt;p&gt;This comes up often enough to be worth addressing directly, in a few words.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/system.security.securestring" target="_blank"&gt;SecureString&lt;/a&gt; was designed to minimize the time secrets exist in memory in
plain text. In theory, that sounds helpful.&lt;/p&gt;
&lt;p&gt;In practice, especially in the managed .NET environment, it does little to solve
the problem. There are two reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Most APIs which connect you to services require “normal” strings, so the
secure in-memory representation &lt;code&gt;SecureString&lt;/code&gt; offers needs to be converted
into .NET strings. These conversions leave data in managed memory, just as if
you’d stored it there all along.&lt;/li&gt;
&lt;li&gt;Even if this could be prevented, the application still performs authenticated
operations. This leaves it open to control by a local user just like before.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So while it may reduce exposure in very narrow scenarios, it does nothing to
address the fundamental issue: the application already has the capability to
act. Finally, it&amp;#39;s difficult to ignore the&amp;nbsp;official Microsoft recommendations (&lt;a href="https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md" target="_blank"&gt;one&lt;/a&gt;,&amp;nbsp;&lt;a href="https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-security-securestring" target="_blank"&gt;two&lt;/a&gt;, &lt;a href="https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-security-securestring#how-secure-is-securestring" target="_blank"&gt;three&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/news/image_2.png" alt=""&gt;&lt;/p&gt;&lt;h2&gt;Your Feedback Matters!&lt;/h2&gt;
&lt;div data-survey-id="b31c0c9e-b420-4b2b-9501-2a16d14dd7af" data-survey-auth-required="false"&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 02 Apr 2026 11:00:00 Z</pubDate>
      <dc:creator>Oliver Sturm (DevExpress)</dc:creator>
    </item>
    <item>
      <guid isPermaLink="false">bd716303-653c-428d-8b8a-a7d998cde032:388283</guid>
      <link>https://community.devexpress.com/Blogs/news/archive/2026/04/01/microsoft-multilingual-app-toolkit-mat-has-been-deprecated-what-s-next-for-devexpress-powered-app-localization.aspx</link>
      <category domain="https://community.devexpress.com/Tags/.NET">.NET</category>
      <category domain="https://community.devexpress.com/Tags/.net+core">.net core</category>
      <category domain="https://community.devexpress.com/Tags/ASP.NET">ASP.NET</category>
      <category domain="https://community.devexpress.com/Tags/Blazor">Blazor</category>
      <category domain="https://community.devexpress.com/Tags/charting">charting</category>
      <category domain="https://community.devexpress.com/Tags/Dashboard">Dashboard</category>
      <category domain="https://community.devexpress.com/Tags/DevExtreme">DevExtreme</category>
      <category domain="https://community.devexpress.com/Tags/Featured">Featured</category>
      <category domain="https://community.devexpress.com/Tags/feedback">feedback</category>
      <category domain="https://community.devexpress.com/Tags/future">future</category>
      <category domain="https://community.devexpress.com/Tags/globalization">globalization</category>
      <category domain="https://community.devexpress.com/Tags/JS">JS</category>
      <category domain="https://community.devexpress.com/Tags/localization">localization</category>
      <category domain="https://community.devexpress.com/Tags/office">office</category>
      <category domain="https://community.devexpress.com/Tags/Reporting">Reporting</category>
      <category domain="https://community.devexpress.com/Tags/Roadmap">Roadmap</category>
      <category domain="https://community.devexpress.com/Tags/Survey">Survey</category>
      <category domain="https://community.devexpress.com/Tags/usability">usability</category>
      <category domain="https://community.devexpress.com/Tags/ux">ux</category>
      <category domain="https://community.devexpress.com/Tags/VCL">VCL</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/WPF">WPF</category>
      <category domain="https://community.devexpress.com/Tags/XAF">XAF</category>
      <title>Microsoft Multilingual App Toolkit (MAT) Has Been Deprecated: What’s Next for DevExpress-Powered App Localization?</title>
      <description>&lt;p&gt;&lt;span style="color:#000000;"&gt;As you probably know,&amp;nbsp;Microsoft Multilingual App Toolkit (MAT)&amp;nbsp;support ended&amp;nbsp;on October 15, 2025. Since MAT&amp;nbsp;is no longer supported, this post documents&amp;nbsp;localization-related alternatives available to the Microsoft developer community.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;h2 style="color:#242424;"&gt;&lt;span&gt;What MAT Deprecation Means in Practice&lt;/span&gt;&lt;/h2&gt;&lt;ul style="color:#242424;"&gt;&lt;li&gt;No future compatibility guarantees with new tooling or runtimes.&lt;/li&gt;&lt;li&gt;Localization assets are not lost&amp;nbsp;— MAT uses standard XLIFF / RESX formats,&amp;nbsp;so translations remain reusable.&lt;/li&gt;&lt;li&gt;Microsoft recommends moving to alternative localization tools.&lt;/li&gt;&lt;/ul&gt;&lt;h2 style="color:#242424;"&gt;&lt;span&gt;What to Look for in a MAT Alternative&lt;/span&gt;&lt;br&gt;&lt;/h2&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;Key requirements for .NET apps:&lt;/span&gt;&lt;/p&gt;&lt;ul style="color:#242424;"&gt;&lt;li&gt;Centralized localization string management&lt;/li&gt;&lt;li&gt;Validation and consistency checks&lt;/li&gt;&lt;li&gt;Reuse of translations across versions&lt;/li&gt;&lt;li&gt;Support for RESX/XLIFF-based workflows&lt;/li&gt;&lt;/ul&gt;&lt;h2 style="color:#242424;"&gt;&lt;span&gt;New DevExpress Localization Tool at a Glance&lt;/span&gt;&lt;br&gt;&lt;/h2&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;All the aforementioned localization requirements are supported in the new &lt;a href="https://docs.devexpress.com/GeneralInformation/405620/localization/localization-tool" target="_blank" style="background-color:#ffff99;"&gt;DevExpress Localization Tool&lt;/a&gt; (available as Community Technology Preview or CTP&amp;nbsp;in v25.2): &lt;span style="background-color:#ffff99;"&gt;&lt;a href="https://github.com/DevExpress/Localization" target="_blank"&gt;Downloads&lt;/a&gt; | &lt;a href="https://docs.devexpress.com/GeneralInformation/404608/localization/localization-tool" target="_blank"&gt;Get Started&lt;/a&gt;&lt;/span&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style="color:#242424;"&gt;&lt;span style="color:#404040;"&gt;This new tool introduces enhanced collaboration capabilities, easier resource navigation/management, AI-powered translation services, support for multiple DevExpress products/platforms, and much more.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Key features include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Simpler localization string management&lt;/strong&gt;&lt;br&gt;Use advanced data shaping capabilities available in our Data Grid control to locate resources, filter or group data, and more.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Enhanced translation consistency and coverage&lt;/strong&gt;&lt;br&gt;Locate duplicate strings, find inconsistent translations using a built-in localization validator, review context information, and run batch operations.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Multiple export types&lt;/strong&gt;&lt;br&gt;You can export translations as satellite assemblies, NuGet packages, a single merged RESX file for multiple products (replaces hundreds of assemblies), or JSON files for JS/TS-based products.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;New collaboration capabilities&lt;/strong&gt;&lt;br&gt;You can now use change tracking, reviews, import/export capabilities, and built-in backups. All DevExpress product localization resources are available on GitHub. You can either use our Windows-based tool, modify your translations directly in RESX/XML, or build your own tool.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Support for multiple products/platforms&lt;/strong&gt;&lt;br&gt;The current version already supports numerous DevExpress UI libraries (WinForms, WPF, Blazor, ASP.NET Core, Reports, Dashboard, XAF). We plan to add support for .NET MAUI, DevExtreme, and VCL UI Controls in future release cycles.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;AI-powered resource translation&lt;/strong&gt;&lt;br&gt;Integrate your favorite AI service into our new Localization client.&lt;/li&gt;&lt;/ul&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;&lt;img src="https://www.devexpress.com/subscriptions/i/25.2/25-2-localization-tool@2x.png" alt=""&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;&lt;strong&gt;My favorite feature&lt;/strong&gt;&lt;span&gt;: a way to export all your multi-product translations to a &lt;a href="https://docs.devexpress.com/GeneralInformation/405620/localization/localization-tool#export-to-mergedsingle-resx" target="_blank" style="background-color:#ffff99;"&gt;single or merged RESX file&lt;/a&gt;. This is a huge time-saver or much simpler alternative to dozens of NuGet packages or satellite resources/assemblies (this&amp;nbsp;standard .NET approach is still supported). A single RESX file under your control means fewer dependencies in projects: no accidentally forgotten references and no heavy maintenance later when you add a new component to the project.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;&lt;img src="https://community.devexpress.com/blogs/news/single_localization_resource.png" alt="" style="width:1514px;height:896px;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;&lt;span&gt;The fact that the&amp;nbsp;source translations&amp;nbsp;reside&amp;nbsp;on GitHub and the internal translation database (RESX/XML)&amp;nbsp;is accessible for custom tools (yes, our customers did that too)&amp;nbsp;or AI-based translations are&amp;nbsp;nice additions as well. I also think that our powerful WinForms Data Grid speaks for itself.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;&lt;img src="https://community.devexpress.com/blogs/news/machine_readable_sources_collage.png" alt="" style="width:2146px;height:1089px;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;h2 style="color:#242424;"&gt;&lt;span&gt;Future Plans&lt;/span&gt;&lt;/h2&gt;&lt;p style="color:#242424;"&gt;&lt;span&gt;Long-term goal: one unified localization platform (even for VCL and JS) instead of multiple overlapping tools.&amp;nbsp;&lt;/span&gt;In 2026, we will improve ease of use/usability as follows:&lt;/p&gt;&lt;ul style="color:#242424;"&gt;&lt;li&gt;Automatic localization resource downloads vs manual copy/paste from GitHub;&lt;/li&gt;&lt;li&gt;Automatic product selection for localization (based on application DLL)&lt;/li&gt;&lt;li&gt;Better integration with DevExtreme JS / TS (&lt;a href="https://docs.devexpress.com/AspNetCore/400577/devextreme-based-controls/concepts/localization" target="_blank"&gt;Intl and custom dictionaries&lt;/a&gt;), XAF (&lt;a href="https://docs.devexpress.com/eXpressAppFramework/113297/localization/localization-tool" target="_blank"&gt;XAFML files&lt;/a&gt;), VCL (&lt;a href="https://docs.devexpress.com/VCL/154039/ExpressCrossPlatformLibrary/how-to/localize-an-application" target="_blank"&gt;INI files&lt;/a&gt;).​&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="color:#000000;"&gt;Ultimately, the new&amp;nbsp;&lt;a href="https://docs.devexpress.com/GeneralInformation/405620/localization/localization-tool" target="_blank"&gt;DevExpress Localization Tool&lt;/a&gt;&amp;nbsp;offers a modern path forward for DevExpress-powered apps. Older DevExpress localization utilities are now in maintenance mode (see also&amp;nbsp;&lt;a href="https://docs.devexpress.com/GeneralInformation/404608/localization/localization#tools" target="_blank" style="background-color:#ffff99;"&gt;this comparison&lt;/a&gt;). For example, we will continue to maintain the&amp;nbsp;&lt;a href="https://localization.devexpress.com/" target="_blank"&gt;localization.devexpress.com&lt;/a&gt;&amp;nbsp;service as we have no alternatives for older DevExpress product versions, but this service will only receive&amp;nbsp;bug fixes. While you can use&amp;nbsp;the service for new DevExpress versions, we recommend that you give the new tool a&amp;nbsp;try for translation-related tasks (on Windows at least).&lt;/span&gt;&lt;/p&gt;&lt;h2&gt;Your Feedback Matters!&lt;/h2&gt;
&lt;div data-survey-id="16f43533-a02a-43b0-9a22-bbab1c5aa730" data-survey-auth-required="false"&gt;&lt;/div&gt;
&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;br&gt;&lt;span&gt;Dennis Garavsky&lt;/span&gt;&lt;br&gt;&lt;span&gt;Principal Product Manager&lt;/span&gt;&lt;br&gt;&lt;a href="mailto:dennis@devexpress.com" title="Email me if you have questions or suggestions"&gt;dennis@devexpress.com&lt;/a&gt;&lt;br&gt;&lt;/p&gt;</description>
      <pubDate>Wed, 01 Apr 2026 05:15:00 Z</pubDate>
      <dc:creator>Dennis Garavsky (DevExpress)</dc:creator>
    </item>
  </channel>
</rss>