reactjsasp.net-corevitevisual-studio-2022

React and ASP.NET Core - deployment not publishng SPA


I have created an out of the box react app with ASP.NET Core Web API (.NET 9, VS 2022 17.13.5).

In former versions (.NET 6), I'd get a ClientApp nested in the backend solution, and when I publish - this is all included.

Now I have:

When I publish MyApp.Server, the backend application is deployed, but the frontend is not.

Local (folder) or server logs shows the following warning:

warn: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[16]
The WebRootPath was not found: ..
\MyApp.Server\bin\Release\net9.0\publish\wwwroot. Static files may be unavailable.

But that can be expected as the website isn't there.

Has anyone had a similar issue? .NET 6 worked out of the box.

Any help greatly appreciated,
David


Solution

  • We need to add below settings to put the react publish files under wwwroot folder.

    And as we know, app.MapStaticAssets(); is used for .NET9, and app.UseStaticFiles(); still works. There is official documentation about the difference MapStaticAssets and UseStaticFiles, I know it very well, but in this case we need to use app.UseStaticFiles(); to solve the 404 problem.

    Here is my all changes in my brand new project.

    project_name.Server.csproj.

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net9.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <SpaRoot>..\react_spa.client</SpaRoot>
        <SpaProxyLaunchCommand>npm run dev</SpaProxyLaunchCommand>
        <SpaProxyServerUrl>https://localhost:51035</SpaProxyServerUrl>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2" />
        <PackageReference Include="Microsoft.AspNetCore.SpaProxy">
          <Version>9.*-*</Version>
        </PackageReference>
      </ItemGroup>
    
      <ItemGroup>
        <ProjectReference Include="..\react_spa.client\react_spa.client.esproj">
          <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
        </ProjectReference>
      </ItemGroup>
      <!--Please add below settings, it can build the react project and save it under wwwroot folder-->
        
      <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build">
        <Exec Command="node --version" ContinueOnError="true">
          <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
        </Exec>
        <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build this project." />
      </Target>
      
      <Target Name="PublishReact" AfterTargets="ComputeFilesToPublish">
        
        <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
        
        <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build " />
      
        <ItemGroup>
          <DistFiles Include="$(SpaRoot)\dist\**" />
          <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
            <RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
            <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
          <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
          </ResolvedFileToPublish>
        </ItemGroup>
      </Target>
    
    </Project>
    

    Program.cs

    var app = builder.Build();
    
    app.UseDefaultFiles();
    //app.MapStaticAssets();
    app.UseStaticFiles();
    
    // Configure the HTTP request pipeline.
    if (app.Environment.IsDevelopment())
    {
        app.MapOpenApi();
    }
    
    app.UseHttpsRedirection();
    
    app.UseAuthorization();
    
    app.MapControllers();
    
    app.MapFallbackToFile("/index.html");
    
    app.Run();
    

    Test Result

    strong text

    enter image description here