<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: assaadfrs</title>
    <description>The latest articles on DEV Community by assaadfrs (@assaadfrs).</description>
    <link>https://dev.to/assaadfrs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F759916%2Fc1bbf17c-251d-4837-add3-279b07c2ce30.png</url>
      <title>DEV Community: assaadfrs</title>
      <link>https://dev.to/assaadfrs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/assaadfrs"/>
    <language>en</language>
    <item>
      <title>Fixing MSBuild NU5019 Errors in Multi-Targeting .NET Projects: A Complete Guide</title>
      <dc:creator>assaadfrs</dc:creator>
      <pubDate>Tue, 09 Sep 2025 08:43:18 +0000</pubDate>
      <link>https://dev.to/assaadfrs/fixing-msbuild-nu5019-errors-in-multi-targeting-net-projects-a-complete-guide-1ip6</link>
      <guid>https://dev.to/assaadfrs/fixing-msbuild-nu5019-errors-in-multi-targeting-net-projects-a-complete-guide-1ip6</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Getting &lt;code&gt;NU5019: File not found&lt;/code&gt; when packaging multi-targeting .NET projects? The issue is that &lt;code&gt;$(TargetFramework)&lt;/code&gt; doesn't resolve properly during &lt;code&gt;dotnet pack&lt;/code&gt;. &lt;strong&gt;Solution&lt;/strong&gt;: Use a custom MSBuild target with hardcoded framework paths instead of static ItemGroups with variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"IncludeAdditionalFiles"&lt;/span&gt; &lt;span class="na"&gt;BeforeTargets=&lt;/span&gt;&lt;span class="s"&gt;"_GetPackageFiles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\OtherProject\bin\$(Configuration)\net47\OtherProject.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\net47\OtherProject.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\OtherProject\bin\$(Configuration)\net9.0\OtherProject.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\net9.0\OtherProject.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Have you ever encountered the dreaded &lt;code&gt;NU5019: File not found&lt;/code&gt; error when trying to create NuGet packages from multi-targeting .NET projects? If you're building projects that target multiple frameworks and want to bundle multiple DLLs into a single package, you've probably run into this frustrating issue.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk you through the exact problem I encountered and the solution that finally worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I was working with a solution containing two projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MyProject.Core&lt;/code&gt; (VB.NET project, multi-targeting &lt;code&gt;net47&lt;/code&gt; and &lt;code&gt;net9.0&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MyProject.Utils&lt;/code&gt; (C# project, also multi-targeting &lt;code&gt;net47&lt;/code&gt; and &lt;code&gt;net9.0&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My goal was to create a single NuGet package from the VB.NET project that would include &lt;strong&gt;both&lt;/strong&gt; the VB.NET and C# DLLs for each target framework.&lt;/p&gt;

&lt;p&gt;Initially, I tried the "obvious" approach in my &lt;code&gt;.vbproj&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\MyProject.Utils\bin\$(Configuration)\$(TargetFramework)\MyProject.Utils.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\$(TargetFramework)\MyProject.Utils.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"bin\$(Configuration)\$(TargetFramework)\MyProject.Core.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\$(TargetFramework)\MyProject.Core.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But when I ran &lt;code&gt;dotnet pack&lt;/code&gt;, I got:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;error NU5019: File not found: 'C:\...\MyProject.Utils\bin\Release\MyProject.Utils.dll'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Root Cause
&lt;/h2&gt;

&lt;p&gt;The issue was that &lt;code&gt;$(TargetFramework)&lt;/code&gt; doesn't resolve correctly during the packaging phase in multi-targeting scenarios. Instead of resolving to &lt;code&gt;net47&lt;/code&gt; or &lt;code&gt;net9.0&lt;/code&gt;, it was resolving to an empty string, creating invalid paths like:&lt;/p&gt;

&lt;p&gt;❌ &lt;code&gt;bin\Release\MyProject.Utils.dll&lt;/code&gt; (missing framework folder)&lt;/p&gt;

&lt;p&gt;Instead of the correct paths:&lt;/p&gt;

&lt;p&gt;✅ &lt;code&gt;bin\Release\net47\MyProject.Utils.dll&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ &lt;code&gt;bin\Release\net9.0\MyProject.Utils.dll&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: MSBuild Target Approach
&lt;/h2&gt;

&lt;p&gt;After trying several approaches, the solution that worked was to use a custom MSBuild target instead of static ItemGroups. Here's what I implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"IncludeAdditionalFiles"&lt;/span&gt; &lt;span class="na"&gt;BeforeTargets=&lt;/span&gt;&lt;span class="s"&gt;"_GetPackageFiles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Include C# project DLLs only (VB.NET DLLs are included automatically) --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\MyProject.Utils\bin\$(Configuration)\net47\MyProject.Utils.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\net47\MyProject.Utils.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;None&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\MyProject.Utils\bin\$(Configuration)\net9.0\MyProject.Utils.dll"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Pack&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/Pack&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;PackagePath&amp;gt;&lt;/span&gt;lib\net9.0\MyProject.Utils.dll&lt;span class="nt"&gt;&amp;lt;/PackagePath&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/None&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Target Timing&lt;/strong&gt;: &lt;code&gt;BeforeTargets="_GetPackageFiles"&lt;/code&gt; ensures our target runs at the right time during the packaging process, after the build is complete but before NuGet collects the files to pack.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Explicit Framework Paths&lt;/strong&gt;: Instead of relying on the problematic &lt;code&gt;$(TargetFramework)&lt;/code&gt; variable, we use hardcoded framework identifiers (&lt;code&gt;net47&lt;/code&gt;, &lt;code&gt;net9.0&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Duplicates&lt;/strong&gt;: Since MSBuild automatically includes the primary project's output DLLs, we only need to explicitly include the additional C# project DLLs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Bonus: Fixing MSB4057 GetTargetPath Errors
&lt;/h2&gt;

&lt;p&gt;While working on this, I also encountered &lt;code&gt;MSB4057: The target "GetTargetPath" does not exist in the project&lt;/code&gt; errors. This happens when using SDK-style projects that are referenced by other projects (especially ASP.NET websites).&lt;/p&gt;

&lt;p&gt;The fix is to add this target to any project experiencing the error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Target&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"GetTargetPath"&lt;/span&gt; &lt;span class="na"&gt;Returns=&lt;/span&gt;&lt;span class="s"&gt;"@(_FakeOutputPath)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;_FakeOutputPath&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"$(MSBuildProjectDirectory)\$(OutputPath)\$(_InstallerTargetFramework)\$(AssemblyName).dll"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;

&lt;p&gt;After implementing these changes:&lt;/p&gt;

&lt;p&gt;✅ &lt;code&gt;dotnet pack&lt;/code&gt; succeeds without NU5019 errors&lt;br&gt;&lt;br&gt;
✅ Package contains all DLLs for both target frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lib/net47/MyProject.Core.dll&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/net47/MyProject.Utils.dll&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lib/net9.0/MyProject.Core.dll&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/net9.0/MyProject.Utils.dll&lt;/code&gt;
✅ No duplicate file warnings
✅ Single NuGet package with bundled dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't rely on &lt;code&gt;$(TargetFramework)&lt;/code&gt; during packaging&lt;/strong&gt; in multi-targeting scenarios - it may not resolve as expected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use MSBuild targets for dynamic file inclusion&lt;/strong&gt; instead of static ItemGroups when dealing with complex packaging requirements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The timing of MSBuild targets matters&lt;/strong&gt; - &lt;code&gt;BeforeTargets="_GetPackageFiles"&lt;/code&gt; is the sweet spot for packaging customizations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-targeting projects need special handling&lt;/strong&gt; when you want to bundle outputs from multiple projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Alternative Approaches Considered
&lt;/h2&gt;

&lt;p&gt;Before settling on this solution, I tried:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework-specific ItemGroups with conditions&lt;/li&gt;
&lt;li&gt;Different target timing (&lt;code&gt;BeforeTargets="GenerateNuspec"&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;Exists()&lt;/code&gt; conditions (failed due to timing issues)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these worked reliably. The target-based approach with explicit framework paths proved to be the most robust solution.&lt;/p&gt;




&lt;p&gt;Have you encountered similar MSBuild packaging issues? What solutions worked for you? Let me know in the comments!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this post helped you solve a similar problem, give it a ❤️ and consider sharing it with others who might be struggling with the same issue.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt; #dotnet #msbuild #nuget #packaging #multitargeting #csharp #vbnet&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>msbuild</category>
      <category>nuget</category>
      <category>packaging</category>
    </item>
    <item>
      <title>Fixing Blazor 404 Errors When Using Razor Class Library Pages</title>
      <dc:creator>assaadfrs</dc:creator>
      <pubDate>Sat, 05 Jul 2025 09:13:26 +0000</pubDate>
      <link>https://dev.to/assaadfrs/fixing-blazor-404-errors-when-using-razor-class-library-pages-5f1n</link>
      <guid>https://dev.to/assaadfrs/fixing-blazor-404-errors-when-using-razor-class-library-pages-5f1n</guid>
      <description>&lt;p&gt;Have you ever created a Blazor page in a Razor Class Library (RCL) only to get a frustrating 404 error when trying to navigate to it? You're not alone! This is a common issue that catches many developers off guard. Let me walk you through the problem and the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Blazor pages in Razor Class Libraries return 404 errors even when &lt;code&gt;AdditionalAssemblies&lt;/code&gt; is configured in &lt;code&gt;Routes.razor&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Add &lt;code&gt;.AddAdditionalAssemblies()&lt;/code&gt; to your &lt;code&gt;Program.cs&lt;/code&gt; routing configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapRazorComponents&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInteractiveServerRenderMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAdditionalAssemblies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;YourRCL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SomeComponent&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to configure additional assemblies in &lt;strong&gt;both&lt;/strong&gt; &lt;code&gt;Routes.razor&lt;/code&gt; AND &lt;code&gt;Program.cs&lt;/code&gt; for RCL routing to work properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I had a Blazor Server app (&lt;code&gt;BlazorApp1&lt;/code&gt;) that referenced a Razor Class Library (&lt;code&gt;RazorClassLibrary1&lt;/code&gt;). In the RCL, I created a simple page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page "/page1"

&amp;lt;PageTitle&amp;gt;Page 1&amp;lt;/PageTitle&amp;gt;

&amp;lt;h1&amp;gt;Page 1&amp;lt;/h1&amp;gt;

&amp;lt;div class="my-component"&amp;gt;
    This component is defined in the &amp;lt;strong&amp;gt;RazorClassLibrary1&amp;lt;/strong&amp;gt; library.
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I configured the &lt;code&gt;AdditionalAssemblies&lt;/code&gt; in my &lt;code&gt;Routes.razor&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@using System.Reflection
&amp;lt;Router AppAssembly="typeof(Program).Assembly"
        AdditionalAssemblies="new[] { typeof(RazorClassLibrary1.Component1).Assembly }"&amp;gt;
    &amp;lt;Found Context="routeData"&amp;gt;
        &amp;lt;RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/&amp;gt;
        &amp;lt;FocusOnNavigate RouteData="routeData" Selector="h1"/&amp;gt;
    &amp;lt;/Found&amp;gt;
    &amp;lt;NotFound&amp;gt;
        &amp;lt;PageTitle&amp;gt;Not found&amp;lt;/PageTitle&amp;gt;
        &amp;lt;LayoutView Layout="typeof(Layout.MainLayout)"&amp;gt;
            &amp;lt;p role="alert"&amp;gt;Sorry, there's nothing at this address.&amp;lt;/p&amp;gt;
        &amp;lt;/LayoutView&amp;gt;
    &amp;lt;/NotFound&amp;gt;
&amp;lt;/Router&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything looked correct, but navigating to &lt;code&gt;/page1&lt;/code&gt; still returned a 404 error. Frustrating!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Investigation
&lt;/h2&gt;

&lt;p&gt;To debug this issue, I created a diagnostic page that showed me what routes were being discovered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@page "/debug"
@using System.Reflection
@using Microsoft.AspNetCore.Components.Routing

&amp;lt;h3&amp;gt;Debug Routes&amp;lt;/h3&amp;gt;

&amp;lt;h4&amp;gt;Main Assembly Routes:&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
@foreach (var route in GetRoutes(typeof(Program).Assembly))
{
    &amp;lt;li&amp;gt;@route&amp;lt;/li&amp;gt;
}
&amp;lt;/ul&amp;gt;

&amp;lt;h4&amp;gt;RCL Assembly Routes:&amp;lt;/h4&amp;gt;
&amp;lt;ul&amp;gt;
@foreach (var route in GetRoutes(typeof(RazorClassLibrary1.Component1).Assembly))
{
    &amp;lt;li&amp;gt;@route&amp;lt;/li&amp;gt;
}
&amp;lt;/ul&amp;gt;

@code {
    private List&amp;lt;string&amp;gt; GetRoutes(Assembly assembly)
    {
        var routes = new List&amp;lt;string&amp;gt;();

        foreach (var type in assembly.GetTypes())
        {
            var routeAttributes = type.GetCustomAttributes&amp;lt;RouteAttribute&amp;gt;();
            foreach (var attr in routeAttributes)
            {
                routes.Add($"{type.Name}: {attr.Template}");
            }
        }

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

&lt;/div&gt;



&lt;p&gt;The debug page showed that the &lt;code&gt;/page1&lt;/code&gt; route &lt;strong&gt;was&lt;/strong&gt; being discovered from the RCL assembly, but the router still wasn't finding it at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;The issue was that while the &lt;code&gt;Router&lt;/code&gt; component was configured with &lt;code&gt;AdditionalAssemblies&lt;/code&gt;, the routing system in &lt;code&gt;Program.cs&lt;/code&gt; wasn't aware of the RCL assembly. &lt;/p&gt;

&lt;p&gt;The fix is to &lt;strong&gt;also&lt;/strong&gt; register the additional assemblies in &lt;code&gt;Program.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;BlazorApp1.Components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add services to the container.&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddRazorComponents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInteractiveServerComponents&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;span class="c1"&gt;// Configure the HTTP request pipeline.&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsDevelopment&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseExceptionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/Error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;createScopeForErrors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHsts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapStaticAssets&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapRazorComponents&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInteractiveServerRenderMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAdditionalAssemblies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RazorClassLibrary1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Component1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// 👈 This is the key!&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Works
&lt;/h2&gt;

&lt;p&gt;The problem occurs because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;Router&lt;/code&gt; component in &lt;code&gt;Routes.razor&lt;/code&gt; handles client-side routing within the Blazor app&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;MapRazorComponents&lt;/code&gt; in &lt;code&gt;Program.cs&lt;/code&gt; handles server-side route discovery and registration&lt;/li&gt;
&lt;li&gt;Both need to know about the RCL assemblies for the routing to work properly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By adding &lt;code&gt;.AddAdditionalAssemblies()&lt;/code&gt; to the &lt;code&gt;MapRazorComponents&lt;/code&gt; call, we ensure that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The server-side routing system discovers all routes from the RCL&lt;/li&gt;
&lt;li&gt;The routes are properly registered with the ASP.NET Core routing system&lt;/li&gt;
&lt;li&gt;The Blazor router can successfully match and render the pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete Working Configuration
&lt;/h2&gt;

&lt;p&gt;Here's the complete working setup:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapRazorComponents&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddInteractiveServerRenderMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAdditionalAssemblies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RazorClassLibrary1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Component1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Routes.razor:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@using System.Reflection
&amp;lt;Router AppAssembly="typeof(Program).Assembly"
        AdditionalAssemblies="new[] { typeof(RazorClassLibrary1.Component1).Assembly }"&amp;gt;
    &amp;lt;Found Context="routeData"&amp;gt;
        &amp;lt;RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"/&amp;gt;
        &amp;lt;FocusOnNavigate RouteData="routeData" Selector="h1"/&amp;gt;
    &amp;lt;/Found&amp;gt;
    &amp;lt;NotFound&amp;gt;
        &amp;lt;PageTitle&amp;gt;Not found&amp;lt;/PageTitle&amp;gt;
        &amp;lt;LayoutView Layout="typeof(Layout.MainLayout)"&amp;gt;
            &amp;lt;p role="alert"&amp;gt;Sorry, there's nothing at this address.&amp;lt;/p&amp;gt;
        &amp;lt;/LayoutView&amp;gt;
    &amp;lt;/NotFound&amp;gt;
&amp;lt;/Router&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Project Reference in BlazorApp1.csproj:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ProjectReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"..\RazorClassLibrary1\RazorClassLibrary1.csproj"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Both client and server routing need to know about RCL assemblies&lt;/strong&gt; - Configure both &lt;code&gt;Routes.razor&lt;/code&gt; and &lt;code&gt;Program.cs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The diagnostic page technique is invaluable&lt;/strong&gt; - Create a debug page to verify route discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;This applies to any additional assemblies&lt;/strong&gt; - Not just RCLs, but any external assemblies containing Blazor components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This solution has saved me hours of debugging, and I hope it helps you too! Have you encountered this issue before? What other Blazor routing gotchas have you discovered?&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Found this helpful? Give it a ❤️ and share it with your fellow Blazor developers!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blazor</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
