﻿<?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>Developer Express Inc.</title>
    <link>https://community.devexpress.com/Blogs</link>
    <description>Microsoft ASP.NET, WinForms Controls, Delphi &amp; C++ VCL Controls, Visual Studio IDE Productivity Tools &amp; Application Frameworks. WPF &amp; Reporting
Got questions? Email us: info@DevExpress.com</description>
    <language>en-US</language>
    <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/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 DevExpress Office File API and Reporting 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 DevExpress AI Skills. 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 File API and Reporting 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 Excel Export 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 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: Reporting Setup and Viewer Customisation&lt;/h2&gt;

&lt;p&gt;Reporting 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 Reporting 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 Reporting 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 Reporting 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 API and Reporting 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 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:388292</guid>
      <link>https://community.devexpress.com/Blogs/markmiller/archive/2026/06/22/what-39-s-new-in-coderush-26-1-mermaid-diagrams-latex-formulas-and-smarter-ai.aspx</link>
      <category domain="https://community.devexpress.com/Tags/AI">AI</category>
      <category domain="https://community.devexpress.com/Tags/AI+Agents">AI Agents</category>
      <category domain="https://community.devexpress.com/Tags/AiGen">AiGen</category>
      <category domain="https://community.devexpress.com/Tags/CodeRush">CodeRush</category>
      <category domain="https://community.devexpress.com/Tags/Formulas+in+Source+Code">Formulas in Source Code</category>
      <category domain="https://community.devexpress.com/Tags/IDE">IDE</category>
      <category domain="https://community.devexpress.com/Tags/LaTeX">LaTeX</category>
      <category domain="https://community.devexpress.com/Tags/Math+expressions">Math expressions</category>
      <category domain="https://community.devexpress.com/Tags/Mermaid+Diagrams">Mermaid Diagrams</category>
      <category domain="https://community.devexpress.com/Tags/productivity">productivity</category>
      <category domain="https://community.devexpress.com/Tags/Visual+Studio">Visual Studio</category>
      <category domain="https://community.devexpress.com/Tags/visual+studio+2022">visual studio 2022</category>
      <category domain="https://community.devexpress.com/Tags/Voice+Commands">Voice Commands</category>
      <title>What's New in CodeRush 26.1: Mermaid Diagrams, LaTeX Formulas, and Smarter AI</title>
      <description>&lt;p&gt;This release adds support for embedding &lt;a href="https://mermaid.ai/" target="_blank"&gt;Mermaid diagrams&lt;/a&gt; and&amp;nbsp;beautifully rendered formulas (math, chemistry, physics) into source code comments. This release also adds support for the latest AI models, improves AiGen&amp;#39;s ability to work with diagrams and formulas, and introduces a new Test Runner feature that makes it easier to troubleshoot failing tests with AI assistance.&lt;/p&gt;&lt;p&gt;Let&amp;#39;s take a look.&lt;/p&gt;&lt;h2&gt;Mermaid Diagrams in Rich Comments&lt;/h2&gt;&lt;p&gt;Rich Comments can now render Mermaid diagrams directly inside source code comments.&lt;/p&gt;&lt;p&gt;Instead of maintaining architectural&amp;nbsp;diagrams in separate documentation systems that inevitably drift from the implementation, you can keep them alongside the code they describe. Mermaid source is stored in external &lt;code&gt;.mmd&lt;/code&gt; files and referenced in the source code comment where it renders, allowing diagrams to participate naturally in source control and code reviews.&lt;/p&gt;&lt;p&gt;CodeRush renders Mermaid diagrams directly inside the editor, supporting a broad range of diagram types including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Flowcharts&lt;/li&gt;&lt;li&gt;Sequence diagrams&lt;/li&gt;&lt;li&gt;Class diagrams&lt;/li&gt;&lt;li&gt;State diagrams&lt;/li&gt;&lt;li&gt;Entity Relationship diagrams&lt;/li&gt;&lt;li&gt;Git graphs&lt;/li&gt;&lt;li&gt;Mind maps&lt;/li&gt;&lt;li&gt;Timelines&lt;/li&gt;&lt;li&gt;ZenUML&lt;/li&gt;&lt;li&gt;And many more&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;&lt;span&gt;]&lt;img src="https://community.devexpress.com/blogs/markmiller/SequenceDiagram.png" alt="" style="width:1341px;height:951px;"&gt;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Diagrams can be edited in place by right-clicking the rendered image and selecting &lt;strong&gt;Edit Diagram&lt;/strong&gt;. The integrated editor provides a live preview while you modify the Mermaid source inside Visual Studio, eliminating the need to switch to external tools.&amp;nbsp;You can even have AiGen&amp;nbsp;generate and modify Mermaid source automatically -- more on that in a bit.&amp;nbsp;&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/SequenceDiagram2.png" alt=""&gt;&lt;p&gt;We added two display options make diagrams easier to manage in larger files.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Thumbnail Mode&lt;/strong&gt; collapses a diagram into a compact preview that expands on demand, making it ideal for large architectural diagrams. Just click the thumbnail to see it in the full size image viewer.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/Thumbnail.png" alt="" style="width:817px;height:269px;"&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;When a thumbnail expands, it appears in a special image viewer that makes it easy to explore large images.&amp;nbsp;You can zoom in and out with the mouse wheel and you can click and drag to shift your view into the large image.&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Fit in TextView&lt;/strong&gt; automatically scales diagrams to fit the current editor window, helping them remain readable at a glance without introducing unnecessary scrolling.&lt;/p&gt;&lt;div&gt;&lt;hr&gt;&lt;/div&gt;&lt;h2&gt;Enhanced LaTeX Support&lt;/h2&gt;&lt;p&gt;LaTeX support has graduated from beta and now provides sharper output, improved performance, and expanded support for complex mathematical notation, including matrices, piecewise functions, chemistry notation, physics symbols, and multi-line expressions.&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/ApproximateErrorFunction.png" alt=""&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;Formulas automatically scale with the editor font, allowing them to integrate naturally with surrounding code.&amp;nbsp;&lt;/p&gt;&lt;p&gt;The following templates create formula placeholders&amp;nbsp;inside code comments:&lt;/p&gt;
&lt;table&gt;

&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Template&lt;/th&gt;
&lt;th&gt;Expansion&lt;/th&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;/f&lt;/td&gt;
&lt;td&gt;// &amp;lt;formula &amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VB&lt;/td&gt;
&lt;td&gt;‘f&lt;/td&gt;
&lt;td&gt;‘ &amp;lt;formula &amp;gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XAML&lt;/td&gt;
&lt;td&gt;!f&lt;/td&gt;
&lt;td&gt;&amp;lt;!– &amp;lt;formula &amp;gt; –&amp;gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;
&lt;p&gt;After expanding one of the templates above in the appropriate source file, you can paste in the LaTeX equation (you can also use &lt;a href="https://latexeditor.lagrida.com/" target="_blank"&gt;online LaTeX equation editors&lt;/a&gt; to create formulas)&lt;/p&gt;&lt;p&gt;Templates for LaTeX formula components:
&lt;/p&gt;
&lt;table&gt;

&lt;tr&gt;
&lt;th&gt;Template&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Expansion&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;


&lt;tr&gt;
&lt;td&gt;\.&lt;/td&gt;
&lt;td&gt;Centered dot&lt;/td&gt;
&lt;td&gt;\cdot&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/cdot.png" alt="centered-dot"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\..&lt;/td&gt;
&lt;td&gt;Three centered dots&lt;/td&gt;
&lt;td&gt;\cdots&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/cdots.png" alt="three-centered-dots"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\8&lt;/td&gt;
&lt;td&gt;Infinity&lt;/td&gt;
&lt;td&gt;\infty&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/infinity.png" alt="infinity"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\b&lt;/td&gt;
&lt;td&gt;Braces&lt;/td&gt;
&lt;td&gt;{}&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\bca&lt;/td&gt;
&lt;td&gt;Big Cap&lt;/td&gt;
&lt;td&gt;\bigcap_{lower}^{upper}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/bigCap.png" alt="big-cap"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\bcu&lt;/td&gt;
&lt;td&gt;Big Cup&lt;/td&gt;
&lt;td&gt;\bigcup_{lower}^{upper}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/bigCup.png" alt="big-cup"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\cp&lt;/td&gt;
&lt;td&gt;Co-product&lt;/td&gt;
&lt;td&gt;\coprod_{lower}^{upper}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/coprod.png" alt="co-prodict"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\f&lt;/td&gt;
&lt;td&gt;Fraction&lt;/td&gt;
&lt;td&gt;\frac{numerator}{denominator}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/frac.png" alt="fraction"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\l&lt;/td&gt;
&lt;td&gt;Limit&lt;/td&gt;
&lt;td&gt;\lim_{x\to\infty}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/lim.png" alt="limit"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\lr&lt;/td&gt;
&lt;td&gt;Left &amp;amp; Right Parens&lt;/td&gt;
&lt;td&gt;\left( \right)&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/parens.png" alt="left-right-parens"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\nr&lt;/td&gt;
&lt;td&gt;nth Root&lt;/td&gt;
&lt;td&gt;\sqrt[root]{value}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/nthRoot.png" alt="nth-root"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\o&lt;/td&gt;
&lt;td&gt;Circle symbol&lt;/td&gt;
&lt;td&gt;\circ&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/circ.png" alt="circle-symbol"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\oi&lt;/td&gt;
&lt;td&gt;Contour integral&lt;/td&gt;
&lt;td&gt;\oint&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/oint.png" alt="contour-integral"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\p&lt;/td&gt;
&lt;td&gt;Product&lt;/td&gt;
&lt;td&gt;\prod_{lower}^{upper}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/prod.png" alt="product"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\s&lt;/td&gt;
&lt;td&gt;Sum&lt;/td&gt;
&lt;td&gt;\sum_{lower}^{upper}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/sum.png" alt="sum"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\sq&lt;/td&gt;
&lt;td&gt;Square Root&lt;/td&gt;
&lt;td&gt;\sqrt{value}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/sqrt.png" alt="square-root"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;\v&lt;/td&gt;
&lt;td&gt;Vector&lt;/td&gt;
&lt;td&gt;\vec{numerator}&lt;/td&gt;
&lt;td&gt;&lt;img src="https://docs.devexpress.com/CodeRushForRoslyn/images/vec.png" alt="vector"&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;/table&gt;&lt;p&gt;Together with Mermaid support, Rich Comments become an effective place to capture visuals of algorithms, mathematical derivations, engineering and architectural diagrams directly within the source code.&lt;/p&gt;&lt;div&gt;&lt;hr&gt;&lt;/div&gt;&lt;h2&gt;AiGen Works with Code, Diagrams, and Formulas&lt;/h2&gt;&lt;p&gt;AiGen now understands not only your source code, but also the Mermaid diagrams and LaTeX formulas contained within Rich Comments.&lt;/p&gt;&lt;p&gt;This enables new workflows. You can ask AiGen to generate diagrams from existing code, generate code from diagrams, create LaTeX representations of algorithms, or analyze whether documentation and implementation remain consistent.&lt;/p&gt;&lt;p&gt;Here&amp;#39;s an example of a Mermaid diagram in Visual Studio generated from the source code below it.&lt;br&gt;&lt;/p&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/FlowChartForSimpleMethod.png" alt="" style="width:361px;height:649px;"&gt;&lt;p&gt;&lt;span&gt;Keeping documentation synchronized with evolving code has traditionally been a manual process. Because AI can now reason across both implementation and in-source documentation (including diagrams and formulas), you can use CodeRush and AiGen to realign architectural drift over time.&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;You can also ask AiGen to &lt;strong&gt;generate LaTeX formulas for expressions inside a&amp;nbsp;method and have those placed inside a comment&amp;nbsp;&lt;/strong&gt;in the code. In the screenshot below notice that AI found the local variable &lt;code class="language-csharp"&gt;u = 1 - t&lt;/code&gt;&amp;nbsp;and substituted its expression everywhere the &lt;code class="language-csharp"&gt;u&lt;/code&gt;&amp;nbsp;variable appeared in the code. It also found coefficients and power equivalents and incorporated them into the formula.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/CubicBezierFormula2.png" alt="" style="width:681px;height:305px;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;hr&gt;&lt;/div&gt;&lt;h2&gt;Expanded AI Model Support&lt;/h2&gt;&lt;p&gt;AiGen now supports the latest generation of AI models from multiple providers, including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Anthropic Claude 4.5 models&lt;/li&gt;&lt;li&gt;Google Gemini 2.x and 3.x models&lt;/li&gt;&lt;li&gt;OpenAI GPT-5.5 models&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Support has also been added for advanced reasoning capabilities available on supported models.&lt;/p&gt;&lt;p&gt;Configuring providers, selecting models, and understanding model-specific capabilities is covered in a separate blog post dedicated to AI configuration.&lt;/p&gt;&lt;div&gt;&lt;hr&gt;&lt;/div&gt;&lt;h2&gt;Copy Failed Test Report&lt;/h2&gt;&lt;p&gt;The Test Runner includes a new &lt;strong&gt;Copy Failed Test Report&lt;/strong&gt; command.&lt;/p&gt;&lt;p&gt;Available from the context menu, this command copies detailed information for every failing test within the selected node (and child nodes)&amp;nbsp;including fully-qualified test names, execution times, exception information, and complete stack traces.&lt;/p&gt;&lt;p&gt;The generated report is ideal for direct use with AI assistants, making it easy to send the clipboard results to AiGen or another LLM for analysis of failing tests and identification of common root causes.&lt;/p&gt;&lt;p&gt;&lt;img src="https://community.devexpress.com/blogs/markmiller/CopyFailedTestReport.png" alt="" style="width:439px;height:570px;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:&amp;#39;Open Sans Condensed&amp;#39;, HelveticaNeue-CondensedBold, Helvetica, &amp;#39;Arial Narrow&amp;#39;, Calibri, Arial, &amp;#39;Lucida Grande&amp;#39;, sans-serif;font-size:30px;"&gt;Wrapping Up&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The features in this release share a common goal: keeping more of your project&amp;#39;s knowledge inside the source code itself.&lt;/p&gt;&lt;p&gt;Mermaid diagrams, LaTeX formulas, and AI-generated documentation all become first-class citizens, and AiGen gets the ability to reason across code and diagram documentation together. Along with expanded AI model support and improved developer tooling like &lt;strong&gt;Copy Failed Test Report&lt;/strong&gt;, these new features&amp;nbsp;streamline everyday development while helping in-source documentation stay in sync with implementation.&lt;/p&gt;&lt;p&gt;As always, we look forward to hearing your feedback.&lt;/p&gt;</description>
      <pubDate>Mon, 22 Jun 2026 09:00:00 Z</pubDate>
      <dc:creator>Mark Miller (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:388291</guid>
      <link>https://community.devexpress.com/Blogs/xaf/archive/2026/06/01/xaf-blazor-winforms-ui-case-study-by-datawerkes-field-services-management-platform-timewerkes.aspx</link>
      <category domain="https://community.devexpress.com/Tags/Audit">Audit</category>
      <category domain="https://community.devexpress.com/Tags/bi">bi</category>
      <category domain="https://community.devexpress.com/Tags/blazor">blazor</category>
      <category domain="https://community.devexpress.com/Tags/case+study">case study</category>
      <category domain="https://community.devexpress.com/Tags/charts">charts</category>
      <category domain="https://community.devexpress.com/Tags/Dashboards">Dashboards</category>
      <category domain="https://community.devexpress.com/Tags/LOB">LOB</category>
      <category domain="https://community.devexpress.com/Tags/lowcode">lowcode</category>
      <category domain="https://community.devexpress.com/Tags/PivotGrid">PivotGrid</category>
      <category domain="https://community.devexpress.com/Tags/rad">rad</category>
      <category domain="https://community.devexpress.com/Tags/reporting">reporting</category>
      <category domain="https://community.devexpress.com/Tags/Reports">Reports</category>
      <category domain="https://community.devexpress.com/Tags/scheduler">scheduler</category>
      <category domain="https://community.devexpress.com/Tags/security">security</category>
      <category domain="https://community.devexpress.com/Tags/TreeList">TreeList</category>
      <category domain="https://community.devexpress.com/Tags/Validation">Validation</category>
      <category domain="https://community.devexpress.com/Tags/WinForms">WinForms</category>
      <category domain="https://community.devexpress.com/Tags/workflow">workflow</category>
      <category domain="https://community.devexpress.com/Tags/XAF">XAF</category>
      <category domain="https://community.devexpress.com/Tags/XPO">XPO</category>
      <title>XAF Blazor/WinForms UI — Case Study by DataWerkes: Field Services Management Platform (TimeWerkes)</title>
      <description>&lt;p&gt;Meet &lt;a href="https://www.datawerkes.ca/" target="_blank"&gt;DataWerkes&lt;/a&gt;&amp;nbsp;(&lt;span&gt;an independent software vendor&amp;nbsp;&lt;/span&gt;in Alberta, Canada) and &lt;span&gt;Keith Courneyea (a founder),&amp;nbsp;&lt;/span&gt;who has been using our&amp;nbsp;&lt;a href="https://www.devexpress.com/products/net/application_framework/" target="_blank" style="background-color:#ffff99;"&gt;Cross-Platform .NET App UI (XAF)&lt;/a&gt;&amp;nbsp;since 2019.&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="https://www.devexpress.com/aboutus/testimonials/assets/casestudies/datawerkes-logo.png" alt="DataWerkes"&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;We recently &lt;strong&gt;&lt;a href="https://www.devexpress.com/AboutUs/Testimonials/timewerkes/" target="_blank" style="background-color:#ffff99;"&gt;published a case study&lt;/a&gt;&lt;/strong&gt; about their &lt;span&gt;flagship commercial product&lt;/span&gt; (TimeWerkes)&amp;nbsp;powered by &lt;a href="https://www.devexpress.com/products/net/application_framework/" target="_blank"&gt;XAF&lt;/a&gt; WinForms/Blazor UI as well as DevExpress&amp;nbsp;&lt;a href="https://www.devexpress.com/products/net/controls/blazor/" target="_blank"&gt;Blazor&lt;/a&gt;&amp;nbsp;/&amp;nbsp;&lt;a href="https://www.devexpress.com/products/net/controls/winforms/" target="_blank"&gt;WinForms&lt;/a&gt;&amp;nbsp;(Grid &amp;amp; Data&amp;nbsp;Editors, Charts, Pivot Grid, TreeList, Scheduler, Rich Text Editor),&amp;nbsp;&lt;a href="https://www.devexpress.com/subscriptions/reporting/" target="_blank"&gt;Reporting&lt;/a&gt;&amp;nbsp;and &lt;a href="https://www.devexpress.com/products/net/dashboard/" target="_blank"&gt;BI Dashboard&lt;/a&gt; components. &lt;/p&gt;&lt;p&gt;Here is how Keith Courneyea described their product TimeWerkes (has been in active client use since late 2024):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;TimeWerkes is a commercial, end-to-end field services management platform for industrial contractors. It manages the full business lifecycle of a contracting operation — from initial quoting through job execution, field ticketing (aka time reporting), inspection reporting, and final invoicing — within a single integrated application available as both a Windows desktop client and a Blazor Server web application. Currently the Blazor app in the primary client.&lt;br&gt;&lt;br&gt;The platform is architected as a core business foundation with industry-specific modules that can be added as client requirements evolve. The core handles workflows common to all contractors: quotes, jobs, field tickets (aka timesheets) with labour and billable items, rate sheets, approval workflows, staff and certification management, equipment tracking, document management, and full invoicing. Specialized modules adapt this base for specific industries.&lt;br&gt;&lt;br&gt; TimeWerkes is offered commercially. It is built on Microsoft SQL Server with Azure SQL in production and uses Azure Blob Storage for all document/image attachments, Azure Functions for background workflow processing, and Azure Communication Services for automated email notifications.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;img src="https://www.devexpress.com/AboutUs/Testimonials/timewerkes/i/03-job-detail-view@2x.png" alt=""&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="https://www.devexpress.com/AboutUs/Testimonials/timewerkes/i/05-corrosion-survey-report@2x.png" alt=""&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;DataWerkes has been in operation for seven years.&amp;nbsp;&lt;/span&gt;Keith&amp;#39;s decision to build on DevExpress in 2019 was not the result of a product evaluation or a recommendation — it was a return. He had worked with DevExpress components in the early 2000s and had a positive experience that stayed with him. When he decided to pursue serious application development, DevExpress was the first place he went back to.&lt;/p&gt;&lt;p&gt;&lt;span&gt;The specific choice of &lt;a href="https://www.devexpress.com/products/net/application_framework/" target="_blank"&gt;XAF&lt;/a&gt; as the framework was driven by what Keith needed as a first-time C# developer with a clear vision of what he wanted to build. XAF&amp;#39;s model-driven approach — where defining a domain class in XPO produces a working UI, security system, and data layer without writing boilerplate infrastructure code — meant that Keith could focus on the business logic he understood deeply and let the framework handle the rest.&lt;/span&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;And here’s what&amp;nbsp;Keith Courneyea&amp;nbsp;said about XAF&amp;#39;s primary benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;TimeWerkes uses the full breadth of the XAF module ecosystem. The &lt;a href="https://docs.devexpress.com/eXpressAppFramework/113366/data-security-and-safety/security-system" target="_blank"&gt;Security System&lt;/a&gt; provides role-based access control across the entire application without custom authentication code. The &lt;a href="https://docs.devexpress.com/eXpressAppFramework/112782/data-security-and-safety/audit-trail-module-overview" target="_blank"&gt;Audit Trail&lt;/a&gt; module — extended through Llamachant&amp;#39;s enhanced implementation — tracks every change across all 120 domain entities. The &lt;a href="https://docs.devexpress.com/eXpressAppFramework/113008/validation/validation-rules" target="_blank"&gt;Validation&lt;/a&gt; module enforces business rules declaratively. &lt;a href="https://docs.devexpress.com/eXpressAppFramework/113286/conditional-appearance" target="_blank"&gt;Conditional Appearance&lt;/a&gt; drives dynamic UI behaviour. The &lt;a href="https://docs.devexpress.com/eXpressAppFramework/112811/event-planning-and-notifications/scheduler-module" target="_blank"&gt;Scheduler&lt;/a&gt; handles staff and job scheduling. &lt;a href="https://docs.devexpress.com/eXpressAppFramework/113591/shape-export-print-data/reports/reports-v2-module-overview" target="_blank"&gt;Reports Module&lt;/a&gt; V2 powers 34 reports covering every business document in the system, from client-facing inspection reports to internal job cost summaries and invoices.&lt;br&gt;&lt;br&gt;Critically, XAF&amp;#39;s cross-platform architecture meant that the same core module and XPO domain model powers three deployment targets simultaneously: a WinForms desktop client, a Blazor Server web application, and an Azure Functions background processing host. A team of any size would find that a significant time saving. For a product owned by one person and built in partnership with a small development firm, it is what made the product possible at all.&lt;br&gt;&lt;br&gt;Dave Hesketh of Llamachant Technology Ltd., whose team serves as the primary development partner on TimeWerkes, describes the XAF ecosystem as central to how Llamachant approaches every engagement. &lt;a href="https://www.llamachant.com/docs/Modules" target="_blank"&gt;Llamachant&amp;#39;s own framework extensions&lt;/a&gt; — including the workflow engine, Azure Blob file attachment integration, AutoIncrementingID, and LlamaLogger — are themselves built on top of XAF, which is a measure of how extensible and production-ready the platform is.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.devexpress.com/AboutUs/Testimonials/timewerkes/" target="_blank" style="background-color:#ffff99;"&gt;Read the full article&lt;/a&gt;&amp;nbsp;to learn why DataWerkes chose XAF&amp;nbsp;for&amp;nbsp;cross-platform RAD project development and&amp;nbsp;what they liked about our tools.&amp;nbsp;&lt;/p&gt;&lt;div class="Note"&gt;&lt;a href="https://docs.devexpress.com/eXpressAppFramework/113577/getting-started" style="background-color:#ffff99;"&gt;Get&amp;nbsp;Started with XAF today&lt;/a&gt;&amp;nbsp;if you want to build Office-like line-of-business (LOB) apps powered by Blazor and WinForms much faster than using traditional approaches. Check out XAF&amp;#39;s demos in your DevExpress installation or online at&amp;nbsp;&lt;a href="https://demos.devexpress.com/xaf/blazordemo/" target="_blank"&gt;https://demos.devexpress.com/xaf/blazordemo/&lt;/a&gt;. You can learn more about&amp;nbsp;&lt;a href="https://www.devexpress.com/products/net/application_framework/" target="_blank"&gt;XAF benefits here&lt;/a&gt;,&amp;nbsp;and our &lt;a href="https://www.devexpress.com/products/net/application_framework/xaf-considerations-for-newcomers.xml" target="_blank"&gt;Considerations for Newcomers&lt;/a&gt;&amp;nbsp;will help you understand whether this application framework is right for your business.&lt;br&gt;&lt;/div&gt;&lt;h2&gt;Do You Have a Story to Share?&lt;/h2&gt;&lt;p&gt;We&amp;#39;d love to publish your story on our website. It doesn’t matter if the project is big or small, or which DevExpress tools you used. Fill out this simple&amp;nbsp;&lt;a href="https://community.devexpress.com/blogs/xaf/social/Developer_Express_General_Case_Study_Template.docx" target="_blank"&gt;case&amp;nbsp;study form&lt;/a&gt;&amp;nbsp;and email us at&amp;nbsp;&lt;a href="mailto:clientservices@devexpress.com"&gt;clientservices@devexpress.com&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Thanks,&lt;br&gt;Dennis Garavsky&lt;br&gt;Principal Product Manager&lt;br&gt;&lt;a title="Email me if you have questions or suggestions" href="mailto:dennis@devexpress.com?subject=Feedback%20on%20Installation-NuGet%20Experience"&gt;dennis@devexpress.com&lt;/a&gt;&amp;nbsp;&lt;/p&gt;</description>
      <pubDate>Mon, 01 Jun 2026 12:49: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:388289</guid>
      <link>https://community.devexpress.com/Blogs/aspnet/archive/2026/05/22/devexpress-blazor-ai-chat-multi-model-support-mcp-server-integration-and-a-look-at-what-39-s-coming-next.aspx</link>
      <category domain="https://community.devexpress.com/Tags/AI">AI</category>
      <category domain="https://community.devexpress.com/Tags/Blazor">Blazor</category>
      <category domain="https://community.devexpress.com/Tags/Chat+UI">Chat UI</category>
      <category domain="https://community.devexpress.com/Tags/LLM">LLM</category>
      <category domain="https://community.devexpress.com/Tags/MCP">MCP</category>
      <category domain="https://community.devexpress.com/Tags/v26.1">v26.1</category>
      <title>DevExpress Blazor AI Chat — Multi-Model Support, MCP Server Integration, and a Look at What's Coming Next</title>
      <description>&lt;p&gt;We continue to extend the capabilities of the&amp;nbsp;&lt;a href="https://docs.devexpress.com/Blazor/DevExpress.AIIntegration.Blazor.Chat.DxAIChat" target="_blank" title="DevExpress Blazor AI Chat"&gt;DevExpress Blazor AI Chat&lt;/a&gt; component and publish GitHub examples designed to address real-world usage scenarios. This post highlights two new examples: a multi-model chat with persistent conversation history, and MCP server integration that extends AI context with external data sources. I&amp;#39;ll also share planned features for v26.1 (scheduled for mid-June 2026).&lt;/p&gt;

&lt;h2 id="multi-model-chat-with-conversation-history"&gt;Multi-Model Chat with Conversation History&lt;/h2&gt;

&lt;p&gt;Our &lt;a href="https://community.devexpress.com/Blogs/aspnet/archive/2025/05/06/devexpress-blazor-ai-chat-build-a-multi-llm-chat-application.aspx" target="_blank" title="DevExpress Blazor AI Chat — Build a Multi-LLM Chat Application"&gt;earlier multi-LLM chat application example&lt;/a&gt; demonstrated how to switch between AI providers within a single chat session. The new &lt;a href="https://github.com/DevExpress-Examples/blazor-ai-chat-with-multiple-llm-services" target="_blank" title="DevExpress Blazor AI Chat — Multi-Model Chat with Conversation History"&gt;DevExpress Blazor AI Chat — Multi-Model Chat with Conversation History&lt;/a&gt; example adds persistent conversation threads and automated chat session title generation.&lt;/p&gt;

&lt;img class="small" src="https://community.devexpress.com/blogs/aspnet/26.1/mcp-multi-llm/devexpress-ai-blazor-chat-multi-llm-with-title-generation.png" alt="The multi-model chat UI showing the left sidebar with a list of conversation threads (each with an auto-generated title), a model selector dropdown at the top, and the active chat pane on the right." style="width:730px;height:606px;"&gt;

&lt;p&gt;The application uses a two-pane layout with &lt;code&gt;DxSplitter&lt;/code&gt;. The left pane is a sidebar that hosts a &lt;code&gt;DxComboBox&lt;/code&gt; for model selection and a &lt;code&gt;DxListBox&lt;/code&gt; for conversation threads. &lt;code&gt;InMemoryChatThreadStore&lt;/code&gt; manages thread data. This thread-safe dictionary-backed store tracks message history and timestamps. The right pane hosts the &lt;code&gt;DxAIChat&lt;/code&gt; component. The following Razor markup defines the layout:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;DxSplitter CssClass=&amp;quot;chat-splitter&amp;quot; Height=&amp;quot;100%&amp;quot;&amp;gt;
    &amp;lt;Panes&amp;gt;
        &amp;lt;DxSplitterPane Size=&amp;quot;320px&amp;quot; MinSize=&amp;quot;220px&amp;quot; MaxSize=&amp;quot;500px&amp;quot;&amp;gt;
            &amp;lt;DxButton RenderStyle=&amp;quot;ButtonRenderStyle.Primary&amp;quot;
                      RenderStyleMode=&amp;quot;ButtonRenderStyleMode.Contained&amp;quot;
                      Text=&amp;quot;New Chat&amp;quot;
                      Click=&amp;quot;CreateNewThreadAsync&amp;quot; /&amp;gt;
            &amp;lt;DxComboBox Data=&amp;quot;@ModelsList&amp;quot;
                        Value=&amp;quot;@SelectedModel&amp;quot;
                        TextFieldName=&amp;quot;@nameof(ChatClientSession.Name)&amp;quot;
                        ValueChanged=&amp;quot;@((ChatClientSession session) =&amp;gt; OnSelectedThreadModelChangedAsync(session))&amp;quot; /&amp;gt;
            &amp;lt;DxListBox Data=&amp;quot;@Threads&amp;quot;
                       Value=&amp;quot;@SelectedThread&amp;quot;
                       ValueChanged=&amp;quot;@((ChatThread thread) =&amp;gt; OnThreadSelectedAsync(thread))&amp;quot;
                       TextFieldName=&amp;quot;@nameof(ChatThread.Title)&amp;quot;&amp;gt;
                &amp;lt;ItemDisplayTemplate&amp;gt;
                    &amp;lt;div class=&amp;quot;thread-list-item&amp;quot;&amp;gt;
                        &amp;lt;div class=&amp;quot;thread-title&amp;quot;&amp;gt;@context.DataItem.Title&amp;lt;/div&amp;gt;
                        &amp;lt;div class=&amp;quot;thread-model&amp;quot;&amp;gt;@GetModelName(context.DataItem.ModelSessionId)&amp;lt;/div&amp;gt;
                    &amp;lt;/div&amp;gt;
                &amp;lt;/ItemDisplayTemplate&amp;gt;
            &amp;lt;/DxListBox&amp;gt;
        &amp;lt;/DxSplitterPane&amp;gt;
        &amp;lt;DxSplitterPane&amp;gt;
            &amp;lt;DxAIChat @ref=&amp;quot;DxAiChat&amp;quot;
                      Initialized=&amp;quot;OnChatInitialized&amp;quot; /&amp;gt;
        &amp;lt;/DxSplitterPane&amp;gt;
    &amp;lt;/Panes&amp;gt;
&amp;lt;/DxSplitter&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Automatic thread title generation is a key implementation detail. The &lt;code&gt;CompositeChatClient&lt;/code&gt; class implements &lt;code&gt;IChatClient&lt;/code&gt; and intercepts outgoing user messages via &lt;code&gt;GetResponseAsync&lt;/code&gt; and &lt;code&gt;GetStreamingResponseAsync&lt;/code&gt; methods. On the first message in a new thread, the class sends a background request to the selected AI model using a dedicated system prompt and requests a concise 3–6 word title. &lt;code&gt;IChatThreadStore&lt;/code&gt; stores the result. The &lt;code&gt;ThreadTitleUpdated&lt;/code&gt; event updates the UI and refreshes the sidebar without blocking the main chat response:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;// CompositeChatClient.cs
public IAsyncEnumerable&amp;lt;ChatResponseUpdate&amp;gt; GetStreamingResponseAsync(IEnumerable&amp;lt;ChatMessagegt; messages, 
ChatOptions? options = null, CancellationToken cancellationToken = new CancellationToken())
    {
        var selectedSession = GetRequiredSelectedSession();
        var messageList = messages.ToList();
        TryQueueTitleGeneration(messageList, selectedSession);
		...
        await foreach (var update in selectedSession.Client.GetStreamingResponseAsync(
        	messageList, options, cancellationToken))
            yield return update;
        ...
    }

private void TryQueueTitleGeneration(IEnumerable&amp;lt;ChatMessage&amp;gt; messages, ChatClientSession selectedSession) {
    var threadId = _activeThreadId.Value;
    var firstUserMessage = GetFirstUserMessage(messages);
    ...
    _ = GenerateTitleForThreadAsync(threadId, selectedSession, firstUserMessage);
}

private async Task GenerateTitleForThreadAsync(Guid threadId,
    ChatClientSession selectedSession, string firstUserMessage) {
    try {
        var thread = await _threadStore.GetThreadAsync(threadId, CancellationToken.None);
        if (thread is null || thread.HasGeneratedTitle)
            return;

        var modelSession = AvailableChatClients
            .FirstOrDefault(x =&amp;gt; x.Id == thread.ModelSessionId) ?? selectedSession;

        string generatedTitle;
            try {
                generatedTitle = await _titleGenerator.GenerateTitleAsync(modelSession, firstUserMessage, CancellationToken.None);
            }
            catch {
                generatedTitle = _titleGenerator.BuildFallbackTitle(firstUserMessage);
            }

            if (string.IsNullOrWhiteSpace(generatedTitle)) {
                generatedTitle = _titleGenerator.BuildFallbackTitle(firstUserMessage);
            }

            await _threadStore.UpdateTitleAsync(threadId, generatedTitle, true, CancellationToken.None);
            lock (_syncRoot) {
                _titledThreadIds.Add(threadId);
            }
            ThreadTitleUpdated?.Invoke(threadId, generatedTitle);
        }
        catch (OperationCanceledException) { }
        finally {
            lock (_syncRoot)
                _titleGenerationInProgress.Remove(threadId);
        }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The example includes an in-memory store. The &lt;code&gt;IChatThreadStore&lt;/code&gt; interface allows for replacement with an EF Core-backed implementation for applications that require persistent history.&lt;/p&gt;

&lt;p&gt;To download and explore our implementation, navigate to the following&amp;nbsp;DevExpress GitHub repository: &lt;a href="https://github.com/DevExpress-Examples/blazor-ai-chat-with-multiple-llm-services" target="_blank" title="Blazor AI Chat — Multi-Model Chat with Conversation History"&gt;Blazor AI Chat — Multi-Model Chat with Conversation History&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="mcp-server-integration"&gt;MCP Server Integration&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://github.com/DevExpress-Examples/blazor-ai-chat-mcp-resources" target="_blank" title="DevExpress Blazor AI Chat — Integration with Model Context Protocol"&gt;DevExpress Blazor AI Chat — Integration with Model Context Protocol&lt;/a&gt; example connects our Blazor AI Chat component to external data through the &lt;a href="https://modelcontextprotocol.io/docs/getting-started/intro" target="_blank" title="Model Context Protocol — Introduction"&gt;Model Context Protocol (MCP)&lt;/a&gt;.&lt;/p&gt;

&lt;img class="small" src="https://community.devexpress.com/blogs/aspnet/26.1/mcp-multi-llm/devexpress-ai-blazor-chat-mcp-resources-window.png" alt="The Blazor AI Chat UI with an MCP-powered chat session open, showing the chat querying a server access log and receiving an AI-generated analysis in response." style="width:626px;height:602px;"&gt;

&lt;p&gt;The solution includes two projects.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;AIChatMcpServer&lt;/code&gt; is a custom MCP server that exposes sample tools, resources, and prompt templates to the client application.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;AIChatMcpClient&lt;/code&gt; is a Blazor Server application that hosts &lt;code&gt;DxAIChat&lt;/code&gt; and loads MCP capabilities at startup through a hosted &lt;code&gt;McpRepository&lt;/code&gt; service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sample MCP server exposes three primitives: &lt;strong&gt;tools&lt;/strong&gt; (executable functions the AI model can call automatically), &lt;strong&gt;resources&lt;/strong&gt; (static content such as logs, text files, and binary images), and &lt;strong&gt;prompts&lt;/strong&gt; (reusable parameterized templates). &lt;code&gt;McpRepository&lt;/code&gt; loads these primitives at startup and passes them to &lt;code&gt;DxAIChat&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each primitive maps directly to a &lt;code&gt;DxAIChat&lt;/code&gt; feature. Resources map to &lt;code&gt;AIChatResource&lt;/code&gt; objects and populate the &lt;code&gt;Resources&lt;/code&gt; collection. Prompts map to &lt;code&gt;DxAIChatPromptSuggestion&lt;/code&gt; entries displayed when the chat opens. Tools attach to &lt;code&gt;IChatClient&lt;/code&gt; through &lt;code&gt;UseFunctionInvocation&lt;/code&gt; at startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Index.razor&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;DxAIChat FileUploadEnabled=&amp;quot;true&amp;quot;
          Resources=&amp;quot;Resources&amp;quot;
          IncludeFunctionCallInfo=&amp;quot;true&amp;quot;&amp;gt;
        &amp;lt;PromptSuggestions&amp;gt;
            @foreach (var suggestion in PromptSuggestions){
                &amp;lt;DxAIChatPromptSuggestion PromptMessage=&amp;quot;@suggestion.PromptMessage&amp;quot; Title=&amp;quot;@suggestion.Title&amp;quot; Text=&amp;quot;@suggestion.PromptMessage&amp;quot;/&amp;gt;
            }
        &amp;lt;/PromptSuggestions&amp;gt;
        &amp;lt;AIChatSettings&amp;gt;
            &amp;lt;DxAIChatFileUploadSettings MaxFileSize=&amp;quot;10000000&amp;quot; MaxFileCount=&amp;quot;3&amp;quot;/&amp;gt;
        &amp;lt;/AIChatSettings&amp;gt;
    &amp;lt;/DxAIChat&amp;gt;

@code {
    IEnumerable&amp;lt;AIChatResource&amp;gt; Resources { get; set; } = [];
    IEnumerable&amp;lt;PromptSuggestion&amp;gt; PromptSuggestions { get; set; } = [];

    protected override async Task OnInitializedAsync() {
        // Map MCP resources to AIChatResource — DxAIChat fetches content on demand via LoadResourceData
        Resources = McpRepository.Resources.Select(x =&amp;gt;
            new AIChatResource(x.Uri, x.Name, LoadResourceData, x.MimeType, x.Description));
        // Map MCP prompt templates to prompt suggestions shown in the chat UI
        PromptSuggestions = McpRepository.PromptSuggestions;
    }

    async Task&amp;lt;IList&amp;lt;AIContent&amp;gt;&amp;gt; LoadResourceData(AIChatResource resource, CancellationToken ct) {
        var result = await McpRepository.Client.ReadResourceAsync(resource.Uri, cancellationToken: ct);
        return result.Contents.ToAIContents();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Program.cs&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using Azure;
using Azure.AI.OpenAI;
using AIChatMcpClient;
using AIChatMcpClient.Components;
using AIChatMcpClient.Services;
using Microsoft.Extensions.AI;
...

builder.Services.AddSingleton&amp;lt;McpRepository&amp;gt;();
builder.Services.AddHostedService(sp =&amp;gt; sp.GetRequiredService&amp;lt;McpRepository&amp;gt;());

builder.Services.AddSingleton&amp;lt;IChatClient&amp;gt;(sp =&amp;gt; {
    var mcpRepository = sp.GetService&amp;lt;McpRepository&amp;gt;();
    var azureOpenAIClient = new AzureOpenAIClient(
        new Uri(azureOpenAISettings.Endpoint),
        new AzureKeyCredential(azureOpenAISettings.ApiKey));
    var chatClient = azureOpenAIClient.GetChatClient(azureOpenAISettings.DeploymentName).AsIChatClient();
    return new ChatClientBuilder(chatClient)
        .ConfigureOptions(co =&amp;gt; {
            co.Tools = mcpRepository.Tools.ToArray&amp;lt;AITool&amp;gt;();
        })
        .UseFunctionInvocation()
        .Build();
});
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation follows MCP standards. Client code requires no changes when you switch to another MCP-compliant backend. To connect the Blazor application to a different MCP server, modify the &lt;code&gt;McpRepository&lt;/code&gt; endpoint:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;using AIChatMcpClient.Models;
using ModelContextProtocol.Client;
using ModelContextProtocol.Protocol;
...
public class McpRepository : IHostedService, IAsyncDisposable {
    private readonly string _mcpEndpoint;

    public McpClient Client { get; private set; } = null!;
    public List&amp;lt;McpClientTool&amp;gt; Tools { get; } = [];
    public List&amp;lt;McpClientResource&amp;gt; Resources { get; } = [];
    public List&amp;lt;McpClientPrompt&amp;gt; Prompts { get; } = [];
    public List&amp;lt;PromptSuggestion&amp;gt; PromptSuggestions { get; } = [];

    public McpRepository(IConfiguration configuration) {
        _mcpEndpoint = configuration.GetSection(&amp;quot;McpServer:Endpoint&amp;quot;).Value 
                       ?? throw new InvalidOperationException(&amp;quot;McpServer:Endpoint is not configured in appsettings.json&amp;quot;);
    }

    public async Task StartAsync(CancellationToken cancellationToken) {
        var transport = new HttpClientTransport(new() { Endpoint = new(_mcpEndpoint) });
        Client = await McpClient.CreateAsync(transport);
        
        var tools = await Client.ListToolsAsync(cancellationToken: cancellationToken);
        var resources = await Client.ListResourcesAsync(cancellationToken: cancellationToken);
        var prompts = await Client.ListPromptsAsync(cancellationToken: cancellationToken);
        
        Tools.AddRange(tools);
        Resources.AddRange(resources);
        Prompts.AddRange(prompts);

        // Preload prompt suggestions at startup
        foreach (var prompt in Prompts) {
            var result = await prompt.GetAsync();
            var content = result.Messages[0].Content;
            PromptSuggestions.Add(new PromptSuggestion {
                PromptMessage = ((TextContentBlock)content).Text,
                Title = prompt.Title ?? &amp;quot;Untitled&amp;quot;
            });
        }
    }

    public Task StopAsync(CancellationToken cancellationToken) =&amp;gt; Task.CompletedTask;

    public async ValueTask DisposeAsync() {
        await Client.DisposeAsync();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span&gt;To download and explore our implementation, navigate to the following&amp;nbsp;DevExpress GitHub repository&lt;/span&gt;: &lt;a href="https://github.com/DevExpress-Examples/blazor-ai-chat-mcp-resources" target="_blank" title="DevExpress Blazor AI Chat — Integration with Model Context Protocol"&gt;DevExpress Blazor AI Chat — Integration with Model Context Protocol&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="whats-coming-in-v26-1"&gt;What&amp;#39;s Coming in v26.1&lt;/h2&gt;

&lt;p&gt;Our v26.1 release is scheduled for mid-June 2026 and includes the following enhancements to DevExpress AI Chat components for Blazor, WinForms, and WPF.&lt;/p&gt;

&lt;h3 id="microsoft-agent-framework-and-openai-responses-api-support"&gt;Microsoft Agent Framework and OpenAI Responses API Support&lt;/h3&gt;

&lt;p&gt;The most substantial addition is a new &lt;code&gt;IChatResponseProvider&lt;/code&gt; abstraction layer that decouples the chat UI from the underlying AI service. This layer allows you to bind &lt;code&gt;DxAIChat&lt;/code&gt; to a wider set of AI backends beyond the standard &lt;code&gt;IChatClient&lt;/code&gt; interface, including the Microsoft Agent Framework (with support for agents, executors, and multi-step workflows), the OpenAI Responses API, and Azure AI Projects. The API also supports custom &lt;code&gt;IChatResponseProvider&lt;/code&gt; implementations for usage scenarios that don&amp;#39;t fit standard providers.&lt;/p&gt;

&lt;p&gt;Planned demos will illustrate how to connect our&amp;nbsp;AI Chat Control to individual agents, composite workflows, AG-UI backends, and tool approval workflows in agentic pipelines.&lt;/p&gt;

&lt;h3 id="api-enhancements"&gt;API Enhancements&lt;/h3&gt;

&lt;p&gt;v26.1 replaces the &lt;code&gt;MessageSent&lt;/code&gt; event with &lt;code&gt;MessageSending&lt;/code&gt;. This event fires before the message is added to chat history and sent to the AI service. Additionally, this event exposes an &lt;code&gt;e.Cancel&lt;/code&gt; parameter that allows you to block send operations entirely. Use it to preprocess and validate input, filter content, call external services and handle the messaging pipeline manually. Alternatively, if &lt;code&gt;e.Cancel&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt;, the AI Chat Control will continue sending and displaying messages and allow you to log and audit user messages without disruption to the normal message pipeline.&lt;/p&gt;

&lt;p&gt;The new event also supports augmentation before delivery — for example, appending a system message or supplemental context to the chat history via the new &lt;code&gt;AppendMessageAsync&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-csharp"&gt;async void AiChatControl1_MessageSending(object sender, AIChatControlMessageSendingEventArgs e) {
    // Append a system message before sending the user&amp;#39;s prompt to the AI service.
    await e.Chat.AppendMessageAsync(&amp;quot;Translate text to Spanish&amp;quot;, ChatRole.System);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id="empty-chat-customization"&gt;Empty Chat Customization&lt;/h3&gt;

&lt;p&gt;v26.1 introduces two new properties designed to customize initial chat state. &lt;code&gt;EmptyMessageAreaText&lt;/code&gt; specifies text dispalyed in the empty chat area, and &lt;code&gt;InputBoxNullText&lt;/code&gt; specifies placeholder text in the input box. These properties allow you to align the initial chat experience with application context and tone:&lt;/p&gt;

&lt;pre&gt;&lt;code class="language-html"&gt;&amp;lt;DxAIChat EmptyMessageAreaText=&amp;quot;How can I help you today?&amp;quot;
          InputBoxNullText=&amp;quot;Ask a question or describe a task...&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="https://community.devexpress.com/blogs/aspnet/26.1/mcp-multi-llm/26-1-blazor-aichat-empty-chat-ui@2x.png" alt="Blazor AI Chat — Customized Empty Text Area and Input Null Text" style="width:780px;height:300px;"&gt;

&lt;h2 id="share-your-feedback"&gt;Share Your Feedback&lt;/h2&gt;

&lt;p&gt;Looking for a particular code example? &lt;a href="https://supportcenter.devexpress.com/" target="_blank" title="DevExpress Support Center"&gt;Contact us via the DevExpress Support Center&lt;/a&gt; to share your usage scenario and we&amp;#39;ll be happy to recommend an implementation.&lt;/p&gt;</description>
      <pubDate>Fri, 22 May 2026 00:01:00 Z</pubDate>
      <dc:creator>Dmitry Tokmachev (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>
  </channel>
</rss>