从Asp.Net Core WebAPI引用Blazor Server项目时静态资源404问题求助
我现有一个Asp.Net Core WebAPI项目,想为其添加Server Side Blazor UI。出于可维护性考虑,希望Blazor代码放在同一解决方案的独立.csproj项目中,但UI需通过同一服务的专属路由/ui提供访问。
我先用Visual Studio内置模板创建了带独立Main方法的Blazor项目,现在尝试从原WebAPI项目引用该Blazor项目并合并两者的Main方法。
功能基本可用,但浏览器渲染页面时,<myBlazorApp>.styles.css、blazor.server.js和open-iconic-bootstrap.min.css这几个文件返回404错误:
浏览器控制台显示上述三个静态资源文件均提示“404 Not Found”
操作步骤
- 在WebAPI项目中添加对Blazor项目的项目引用
- 在Blazor项目的csproj文件的
<PropertyGroup>节中添加<OutputType>Library</OutputType>,并删除Program.cs - 在同一csproj文件中添加以下配置:
<ItemGroup> <EmbeddedResource Include="wwwroot/**" /> </ItemGroup>
- 在WebAPI的Main方法中添加:
services.AddRazorPages(); services.AddServerSideBlazor(o => o.DetailedErrors = true);
以及:
app.UseStaticFiles(new StaticFileOptions { FileProvider = new EmbeddedFileProvider(typeof(UserManagerUI.App).Assembly, "myBlazorNamespace.wwwroot"), }); app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
更新:我在仅包含WebAPI和Blazor项目的全新解决方案中测试,得到了完全相同的结果,因此以下说明无关:说明:实际情况更复杂,但不确定是否相关:该WebAPI项目本身是类库,用作其他仓库中多个项目的NuGet包。(上述WebAPI的Main方法实际是被其他项目的Main方法调用的另一个方法)。我提及此点的原因是,这也是我希望将wwwroot文件夹作为嵌入式资源而非常规文件的原因,这样更便于打包成NuGet。
出现404的核心原因是静态资源的嵌入路径、访问路径配置不匹配,以及Blazor路由与静态资源挂载位置未对应,具体修正步骤如下:
修正Blazor项目的嵌入式资源配置
在Blazor项目的csproj中添加静态资源基础路径配置,并规范嵌入式资源的逻辑命名:<PropertyGroup> <OutputType>Library</OutputType> <StaticWebAssetBasePath>ui</StaticWebAssetBasePath> <!-- 对应路由前缀/ui --> </PropertyGroup> <ItemGroup> <EmbeddedResource Include="wwwroot/**" LogicalName="wwwroot\%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup>StaticWebAssetBasePath指定静态资源的基础访问路径,与目标路由/ui对齐;LogicalName确保嵌入的资源路径结构与原wwwroot保持一致。调整WebAPI中静态资源的挂载配置
为Blazor静态资源指定RequestPath为/ui,同时确保嵌入式文件提供者的命名空间正确(Blazor项目根命名空间 +.wwwroot):app.UseStaticFiles(); // 保留WebAPI自身的静态资源(若有) // 挂载Blazor的嵌入式静态资源 app.UseStaticFiles(new StaticFileOptions { RequestPath = "/ui", FileProvider = new EmbeddedFileProvider( typeof(Blazor项目任意类).Assembly, // 例如typeof(UserManagerUI.App).Assembly "Blazor项目根命名空间.wwwroot" ), });修改Blazor的_Host.cshtml页面
确保页面中所有静态资源引用都加上/ui前缀,同时指定页面路由为/ui:@page "/ui" @namespace Blazor项目命名空间.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <link href="/ui/css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="/ui/css/site.css" rel="stylesheet" /> <link href="/ui/<myBlazorApp>.styles.css" rel="stylesheet" /> <script src="/ui/_framework/blazor.server.js"></script>调整端点路由配置
将Blazor Hub和回退页面的路径都与/ui前缀对齐:app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapBlazorHub("/ui/_blazor"); // 指定Blazor Hub的路径前缀 endpoints.MapFallbackToPage("/ui/{*path:nonfile}", "/_Host"); });
完成以上配置后,访问/ui即可正常加载Blazor页面,所有静态资源也能正确加载,不会再出现404错误。
内容的提问来源于stack exchange,提问作者Arnon Axelrod

