Razor Class 库 (RCL) 中静态内容的 404
404 with static content in Razor Class Library (RCL)
我在 razor class 库 (.net Core 3.1) 中实现静态文件时遇到困难,这些文件被 ASP.NET Core (v3.1) 应用程序使用。
尝试访问静态文件时,我只收到 404 - Not Found。
我在 Whosebug 上遵循了以下答案: 或
我还在以下位置与文档进行了交叉检查:https://docs.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-3.0&tabs=visual-studio#create-an-rcl-with-static-assets。
我在库中的以下位置放置了一个 css 文件:
wwwroot\css\Base.css
并且我测试了以下路径:https://localhost:44300/_content/OurIt.Cockpit/css/Base.css,结果是 404 Not found 响应。
我已经检查过的内容:
- 可以浏览在 RCL 中具有其视图的任何控制器并且它们工作正常(呈现的 HTML 代码提供给浏览器)
- 在 Web 应用程序中有
app.UseStaticFiles();
。
- 在 Web 应用程序中有
webBuilder.UseStaticWebAssets();
。
- 正确的大小写。
wwwroot\css\Base.css
的 Build Action 设置为 Content。
- RCL 项目定义了以下 sdk:
<Project Sdk="Microsoft.NET.Sdk.Razor">
.
在 RCL 项目中设置了以下属性:
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<PropertyGroup>
我也尝试了这个答案中描述的方式: and I tried to access the file from https://localhost:44300/path/css/Base.css
有机会调试或定位问题吗?关于 Microsoft 文档:
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages.
为了验证文件是否在程序集中,我试图找到那个 manifrest,但我找不到它或不知道在哪里寻找它(我检查了输出文件夹)。我还尝试使用 ILSpy 打开 RCL,希望找到解决问题的办法。
有任何想法(或使用带有静态内容的 RCL 的 .NET Core 3.1 工作示例 - 我只找到了控制器/视图的示例,但没有找到静态内容的示例)?
2020-02-05 更新:
我在 Github 上创建了一个样本用于复制:
https://github.com/DominikAmon/RclIssueDemo
如果您从 RclDemo.Library 项目中删除对 Microsoft.AspNet.Core 的引用,那么一切都会按预期进行。这是应该从项目文件中删除的行:
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
如果您创建一个新的 .NET Core 3.x 应用程序,则不会包含此参考,因为它现在已作为 Microsoft.AspNetCore.App 框架参考的一部分包含在内。静态文件在 .NET Core 2.2 Razor Class 库中的工作方式不同,我认为您包含 Microsoft.AspNetCore.Mvc v2.2.0 库是破坏性的。曾经有额外的配置来在 RCL 中包含静态文件。
肖恩
我终于让它为我工作了。我已在 https://github.com/dotnet/AspNetCore.Docs/issues/16837.
上对您创建的问题添加了评论
我现在工作的 .csproj 的相关部分是:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<GenerateMvcApplicationPartsAssemblyAttributes>true</GenerateMvcApplicationPartsAssemblyAttributes>
<RazorCompileOnBuild>true</RazorCompileOnBuild>
<IncludeRazorContentInPack>false</IncludeRazorContentInPack>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<EnableDefaultRazorGenerateItems>true</EnableDefaultRazorGenerateItems>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
</ItemGroup>
<PropertyGroup>
<StaticWebAssetBasePath Condition="$(StaticWebAssetBasePath) == ''">/</StaticWebAssetBasePath>
</PropertyGroup>
</Project>
也许不是上面所有这些设置都是必需的,但由于它正在工作,我不想过多地触摸它 - 如果它有效,请不要触摸: -)
现在,这里有其他问题:
- 因为我想在本地测试我的 NuGet 包,所以我想先将这些包推送到本地存储库文件夹,以便我可以从测试应用程序中使用它们。但是,没有记录 dotnet nuget 也可以推送到本地目录,所以我想我必须使用独立的 nuget.exe 来实现这一点。好吧,显然 it is not a good idea to use nuget.exe with RCL libraries。相反,您可以使用:
dotnet nuget push .\bin\Release\DynamicVML.1.0.32.nupkg -s c:\Projects\nuget
(注意-s选项在documentation中被描述为一个server URL
但实际上可以是一个本地文件夹,这个就不解释了)
周围有太多过时的文章和 Whosebug 答案,可能会让您误入歧途。在我身上发生的事情是,在某个时候我试图遵循 tutorials from different sources,结果发现它对于 .NET Core 3.1 已经过时了。我最终弄乱了我的项目文件,忘记撤消我所做的一些更改。要使其全部正常工作,请确保:
视图/.cshtml 文件必须设置为 "Build Action: Content";
- 静态文件/js文件必须设置为"Build Action: Content";
现在,消费者应用部分:
- 我不必在 Program.cs 中添加
webBuilder.UseStaticWebAssets();
,因为有那么一刻我认为我有。所以我的 CreateHostBuilder 看起来像这样:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
我不必添加过时教程中描述的任何 FileProvider 功能。我的 ConfigureServices 是这样干净的:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("BookAuthors"));
}
我的配置只是基准配置:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
通过以上设置,一切正常。我可以包含来自 RCL 库 的 js 文件,即使它们实际上并未出现在消费者项目 wwwroot 中(我知道这已记录在当前文档中,但在某些时候我正在尝试通过添加 UseDirectoryBrowser to my configure 并检查服务文件夹的内容来调试问题 - 这不起作用,RCL 中的静态文件将不会显示)。
另外,给有类似问题的其他人的注意事项:使用上述设置(由于最后一个配置块,更具体地说)我可以使用来自 /
的静态文件。我没有使用 /_content/LibraryName/...
路径。在我的 RCL 中,我有以下结构
- wwwroot
---- lib
------- myFolder
---------- myScript.js
在消费者应用程序中,我只是使用
使用 .js 文件
@section Scripts {
<script src="~/lib/myFolder/myScript.js"></script>
}
...而且有效!
我查看了您的 github 示例并修复了它。
我删除了 RclDemo.Library.csproj
中的两个包引用。
不知道你的整个项目是否需要这些,但至少你可以找出你是否需要它们,或者你是否需要为它们配置一些东西。
代码:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.1" />-->
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
在 Program.cs 中添加 StaticWebAssetsLoader 以包含静态文件,它能够加载 Razor 库中的 css 和 javascript class
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureAppConfiguration((ctx, cb) =>
{
StaticWebAssetsLoader.UseStaticWebAssets(
ctx.HostingEnvironment,
ctx.Configuration);
});
});
我正在使用一个普通的 Blazor Server 模板,其中包含对我的 RCL 的项目引用。一切正常,无需任何额外代码。
我的问题发生在我添加 Nuget 包属性之后。程序包 ID 与程序集名称不同。
在这种模式中:
_content/{LIBRARY NAME}/
程序集名称 = 库名称。
添加 Nuget 属性后 PackageId = Library Name
希望这对其他人有帮助。
我在 razor class 库 (.net Core 3.1) 中实现静态文件时遇到困难,这些文件被 ASP.NET Core (v3.1) 应用程序使用。
尝试访问静态文件时,我只收到 404 - Not Found。
我在 Whosebug 上遵循了以下答案:
我还在以下位置与文档进行了交叉检查:https://docs.microsoft.com/en-us/aspnet/core/razor-pages/ui-class?view=aspnetcore-3.0&tabs=visual-studio#create-an-rcl-with-static-assets。
我在库中的以下位置放置了一个 css 文件:
wwwroot\css\Base.css
并且我测试了以下路径:https://localhost:44300/_content/OurIt.Cockpit/css/Base.css,结果是 404 Not found 响应。
我已经检查过的内容:
- 可以浏览在 RCL 中具有其视图的任何控制器并且它们工作正常(呈现的 HTML 代码提供给浏览器)
- 在 Web 应用程序中有
app.UseStaticFiles();
。 - 在 Web 应用程序中有
webBuilder.UseStaticWebAssets();
。 - 正确的大小写。
wwwroot\css\Base.css
的 Build Action 设置为 Content。- RCL 项目定义了以下 sdk:
<Project Sdk="Microsoft.NET.Sdk.Razor">
. 在 RCL 项目中设置了以下属性:
<PropertyGroup> <TargetFramework>netcoreapp3.1</TargetFramework> <AddRazorSupportForMvc>true</AddRazorSupportForMvc> <PropertyGroup>
我也尝试了这个答案中描述的方式:
有机会调试或定位问题吗?关于 Microsoft 文档:
When the RCL is built, a manifest is produced that describes the static web asset locations. The consuming app reads the manifest at runtime to consume the assets from referenced projects and packages.
为了验证文件是否在程序集中,我试图找到那个 manifrest,但我找不到它或不知道在哪里寻找它(我检查了输出文件夹)。我还尝试使用 ILSpy 打开 RCL,希望找到解决问题的办法。
有任何想法(或使用带有静态内容的 RCL 的 .NET Core 3.1 工作示例 - 我只找到了控制器/视图的示例,但没有找到静态内容的示例)?
2020-02-05 更新:
我在 Github 上创建了一个样本用于复制: https://github.com/DominikAmon/RclIssueDemo
如果您从 RclDemo.Library 项目中删除对 Microsoft.AspNet.Core 的引用,那么一切都会按预期进行。这是应该从项目文件中删除的行:
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
如果您创建一个新的 .NET Core 3.x 应用程序,则不会包含此参考,因为它现在已作为 Microsoft.AspNetCore.App 框架参考的一部分包含在内。静态文件在 .NET Core 2.2 Razor Class 库中的工作方式不同,我认为您包含 Microsoft.AspNetCore.Mvc v2.2.0 库是破坏性的。曾经有额外的配置来在 RCL 中包含静态文件。
肖恩
我终于让它为我工作了。我已在 https://github.com/dotnet/AspNetCore.Docs/issues/16837.
上对您创建的问题添加了评论我现在工作的 .csproj 的相关部分是:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
<GenerateMvcApplicationPartsAssemblyAttributes>true</GenerateMvcApplicationPartsAssemblyAttributes>
<RazorCompileOnBuild>true</RazorCompileOnBuild>
<IncludeRazorContentInPack>false</IncludeRazorContentInPack>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<EnableDefaultRazorGenerateItems>true</EnableDefaultRazorGenerateItems>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
</ItemGroup>
<PropertyGroup>
<StaticWebAssetBasePath Condition="$(StaticWebAssetBasePath) == ''">/</StaticWebAssetBasePath>
</PropertyGroup>
</Project>
也许不是上面所有这些设置都是必需的,但由于它正在工作,我不想过多地触摸它 - 如果它有效,请不要触摸: -)
现在,这里有其他问题:
- 因为我想在本地测试我的 NuGet 包,所以我想先将这些包推送到本地存储库文件夹,以便我可以从测试应用程序中使用它们。但是,没有记录 dotnet nuget 也可以推送到本地目录,所以我想我必须使用独立的 nuget.exe 来实现这一点。好吧,显然 it is not a good idea to use nuget.exe with RCL libraries。相反,您可以使用:
dotnet nuget push .\bin\Release\DynamicVML.1.0.32.nupkg -s c:\Projects\nuget
(注意-s选项在documentation中被描述为一个server URL
但实际上可以是一个本地文件夹,这个就不解释了)
周围有太多过时的文章和 Whosebug 答案,可能会让您误入歧途。在我身上发生的事情是,在某个时候我试图遵循 tutorials from different sources,结果发现它对于 .NET Core 3.1 已经过时了。我最终弄乱了我的项目文件,忘记撤消我所做的一些更改。要使其全部正常工作,请确保:
视图/.cshtml 文件必须设置为 "Build Action: Content";
- 静态文件/js文件必须设置为"Build Action: Content";
现在,消费者应用部分:
- 我不必在 Program.cs 中添加
webBuilder.UseStaticWebAssets();
,因为有那么一刻我认为我有。所以我的 CreateHostBuilder 看起来像这样:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
我不必添加过时教程中描述的任何 FileProvider 功能。我的 ConfigureServices 是这样干净的:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("BookAuthors"));
}
我的配置只是基准配置:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
通过以上设置,一切正常。我可以包含来自 RCL 库 的 js 文件,即使它们实际上并未出现在消费者项目 wwwroot 中(我知道这已记录在当前文档中,但在某些时候我正在尝试通过添加 UseDirectoryBrowser to my configure 并检查服务文件夹的内容来调试问题 - 这不起作用,RCL 中的静态文件将不会显示)。
另外,给有类似问题的其他人的注意事项:使用上述设置(由于最后一个配置块,更具体地说)我可以使用来自 /
的静态文件。我没有使用 /_content/LibraryName/...
路径。在我的 RCL 中,我有以下结构
- wwwroot
---- lib
------- myFolder
---------- myScript.js
在消费者应用程序中,我只是使用
使用 .js 文件@section Scripts {
<script src="~/lib/myFolder/myScript.js"></script>
}
...而且有效!
我查看了您的 github 示例并修复了它。
我删除了 RclDemo.Library.csproj
中的两个包引用。
不知道你的整个项目是否需要这些,但至少你可以找出你是否需要它们,或者你是否需要为它们配置一些东西。
代码:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
</PropertyGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.1" />-->
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
在 Program.cs 中添加 StaticWebAssetsLoader 以包含静态文件,它能够加载 Razor 库中的 css 和 javascript class
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureAppConfiguration((ctx, cb) =>
{
StaticWebAssetsLoader.UseStaticWebAssets(
ctx.HostingEnvironment,
ctx.Configuration);
});
});
我正在使用一个普通的 Blazor Server 模板,其中包含对我的 RCL 的项目引用。一切正常,无需任何额外代码。
我的问题发生在我添加 Nuget 包属性之后。程序包 ID 与程序集名称不同。
在这种模式中:
_content/{LIBRARY NAME}/
程序集名称 = 库名称。
添加 Nuget 属性后 PackageId = Library Name
希望这对其他人有帮助。