【问题标题】:Asp.Net Core 2.0-2.2 Kestrel not serving static contentAsp.Net Core 2.0-2.2 Kestrel 不提供静态内容
【发布时间】:2018-02-20 00:44:16
【问题描述】:

使用 IIS express 运行 Asp.Net Core 2.0(或 2.2)应用程序时,静态文件(css、js)按预期提供。但是,当通过“dotnet publish -o [targetDirectory]”和 dotnet [website.dll] 使用命令行/Kestrel 时,Kestrel 不会提供任何静态内容。使用浏览器 F12,我看到 Kestrel 返回 404 错误。仔细观察,当直接在浏览器中输入文件路径 (localhost:5000/css/cssfile.css) 时,文件未显示,但 浏览器似乎重定向到“localhost:5000/ cssfile.css" 但仍然返回 404 错误(注意缺少的 /css/ 目录)。

我通过 Visual Studio 2017 创建了这个项目,并为新的 MVC Core 2.0 应用程序(已安装 SDK)选择了默认值。

我已按照here 的步骤在 program.cs 和 startup.cs 文件中启用静态文件。这些实现“app.UseStaticFiles();”和“.UseContentRoot(Directory.GetCurrentDirectory())”。通过谷歌找到的文章似乎都没有帮助。我已经验证 dotnet 将静态内容复制到目标目录。

我错过了什么?谢谢

// Program.cs
public static IWebHost BuildWebHost(string[] args) => WebHost
   .CreateDefaultBuilder(args)
   .UseStartup<Startup>()
   .Build();

// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseExceptionHandler("/Error/HandleError");
    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute( name: "default", template: "{controller=User}/{action=Index}/{id?}");
    });
}

【问题讨论】:

  • 文件相对于内容根目录在哪里?在您的情况下,默认值为 wwwroot/css/cssfile.css AFAIK
  • 没错,文件位于wwwroot/css/cssfile.css
  • ConfigurationHelper.Configure(Configuration) 是做什么的?此外,如果应用程序实际上发送了重定向,那么日志会说什么?打开详细日志记录以查看正在发生的一切。
  • ConfigurationHelper 是一个自定义库,我会确认,但我不认为这是基于没有该行的其他测试的问题。
  • 这是通过环境变量 ASPNETCORE_ENVIRONMENT 控制的。要在命令行 (cmd) 中设置它,请使用“set ASPNETCORE_ENVIRONMENT=Development”。

标签: c# css asp.net-core .net-core


【解决方案1】:

请检查这些静态文件是否存在于以下标签中。

<environment include="Development">
</environment>

正如您已发布,如果静态文件存在于 include Development 中,那么它们将不会存在于 Published 文件夹中。另外,检查View Source 并查看这些链接是否存在。

【讨论】:

  • OP 测试了文件的直接 URL,但没有成功。这与 MVC 视图无关。
【解决方案2】:

我无法按照这些步骤使用新的 ASP.NET Core 2.0 项目重现您的错误;

  1. md 静态测试
  2. cd 静态测试
  3. dotnet 新网站
  4. 在 wwwroot 中添加文件夹 css
  5. wwwroot/css中添加文件site.css
  6. Startup.Configure() 方法的开头插入app.UseStaticFiles();
  7. dotnet 发布 -o pubweb
  8. cd pubweb
  9. dotnet .\static-test.dll
  10. 使用浏览器访问http://localhost:5000/css/site.css

dotnet.exe 在我的终端中呈现以下输出:

Hosting environment: Production
Content root path: C:\src\static-test\pubweb
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/css/site.css
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/css/site.css'. Physical path: 'C:\src\static-test\pubweb\wwwroot\css\site.css'

如您所见,它将成功地在子文件夹中正确地提供 css 文件。请尝试上述步骤,并将代码和输出与您失败的项目进行比较。如果仍然失败,请在RequestPhysical 路径上附上调试信息,上面来自Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware

【讨论】:

  • 我按照这些步骤操作,id 确实正确地提供了 css 文件。在我的情况下,我通过 VS 创建了 MVC Core 2.0 项目,尽管我确实向其他 VS 项目添加了一些依赖项。我现在正在检查并比较差异。
  • 仔细观察,当使用浏览器 F12 时,从 Kestrel 而不是 IIS express 运行时,页面似乎并未要求所有静态文件。例如,从 IIS express 提供的页面要求 core.min.js,但从 Kestrel 提供的页面没有。也许配置/视图模型中的某些内容被配置为使页面请求不同的内容?进一步调查...
  • 您的项目中似乎还有很多其他依赖项,您没有在问题中解释..
  • 对于仍在摸不着头脑的人:请注意,他正在与wwwroot 运行 在同一文件夹中 的 dotnet 命令。如果您跳过第 8 步并将 9 更改为 dotnet .\pubweb\static-test.dll,它将无法正常工作。当您进行 Docker 构建时,这很容易出错。更多详情见我的回答
  • 所以我在树莓派上运行了一个小项目,我时断时续地遇到这个问题,但不知道为什么。 @SpencerRuport 引发了一个想法,我将目录更改为在 linux 上包含我的二进制文件的文件夹,并在那里运行它并且它工作。如果我从该文件夹上方运行它,则它不会加载静态 wwwroot 文件。不知道为什么这样做。
【解决方案3】:

我刚刚遇到了一个非常相似的问题。我无法让 Kestrel 提供任何静态内容。我的配置在 .net core 1.1 中运行良好,但在 .net core 2.0 中无法运行。

我调试了一下,静态文件中间件使用的IFileProvider实例是NullFileProvider。我必须在 Startup.cs 中执行此操作才能获得静态内容:

app.UseFileServer(
    new FileServerOptions() {
        FileProvider = new PhysicalFileProvider("some_path")
    });

【讨论】:

    【解决方案4】:

    我尝试了很多无用的东西,这就是我的解决方法:

    WebHost.CreateDefaultBuilder(args)
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup<Startup>()
    .UseWebRoot("E:\\xyz\\wwwroot")
    .UseUrls("http://localhost:5050")
        .Build();
    

    我添加后,服务静态文件就开始工作了:

    .UseWebRoot("E:\\xyz\\wwwroot")
    

    我在 5000 端口上运行的一项服务发生冲突,因此我指定从 5050 端口启动。


    .Net Core 2.2 更新

    对于 .NET Core 2.2,以下工作:.UseWebRoot("wwwroot")

    但是,获取路径的更易读和更明确的方法:

    static string webRoot = Path.Combine(AppContext.BaseDirectory, "wwwroot");

    然后 UseWebRoot(webRoot);

    【讨论】:

    • 在.NET Core 2.1上测试,应用.UseWebRoot(@"C:\xxx\xxx\wwwroot")后,浏览器可以加载图片、js、css等...谢谢。
    • 这是对我的修复。以及在不进行硬编码的情况下获得对 linux 友好的路径 :)
    • 对于 .NET Core 2.2,我必须添加 .UseWebRoot("wwwroot")
    • 我想补充一下如何动态获取路径static string webRoot = Path.Combine(AppContext.BaseDirectory, "wwwroot");然后UseWebRoot(webRoot);
    • 我使用的是 .NET Core v3.1,但这个扩展似乎不存在?
    【解决方案5】:

    经过反复试验,我意识到一旦开始使用 Kestrel,静态文件的 web 根目录会突然映射到 bin 文件夹而不是 development 文件夹。要解决此问题,您可以执行以下两项操作之一。

    1. 您可以将要包含的所有静态文件设置为复制到输出目录
    2. 您可以将根目录重新映射到某个路径:

      .UseKestrel(...)
      .UseWebRoot(@"C:\MyProject\wwwroot\");
      

    我使用我在其中开发的 wwwroot 文件夹,因此我不必确保将所有新项目都添加到复制到输出目录中。

    【讨论】:

      【解决方案6】:

      对我来说,问题在于工作目录。尝试使用dotnet /var/www/project/project.dll 启动应用程序时,我没有注意我所在的目录。当您以这种方式启动应用程序时,它会自动使用您的当前目录作为工作目录。

      当我查看另一个项目的 .service 文件时,我意识到了这一点,该文件指定了 WorkingDirectory:

      ...
      WorkingDirectory=/var/www/project/
      ExecStart=/usr/bin/dotnet /var/www/project/project.dll
      ...
      

      因此,请确保在运行项目时位于正确的目录中,或者确保在 .service 文件中正确设置了 WorkingDirectory。

      【讨论】:

      • 您的回答帮助了我——我使用 Supervisor 来保持我的 Kestrel 运行——第二行需要匹配第三行目录。 [程序:MyApp] 命令=/usr/bin/dotnet /var/MyApp.dll 目录=/var/ autostart=true autorestart=true stderr_logfile=/var/log/myapp.err.log stdout_logfile=/var/log/myapp .out.log environment=ASPNETCORE_ENVIRONMENT=生产用户=www-data stopsignal=INT
      【解决方案7】:

      我已经使用 MS 模板创建了一个带有 asp.net core 2.1 (MVC) 的新项目,然后包含了一个带有一些动画的 css 文件 animate.css

      为了能够使用它,必须在 _Layout.cshtml
      中添加一个 href 因此,我注意到,MS“忘记”添加环境“Staging”和“Production” 所以..如果在“开发”环境中添加了href,那么在调试(IIS Express)中一切正常,但它不适用于selfhost(我假设也不是在“真正的”IIS上),因为这个不是开发环境和 hrefs 是不是在运行时设置的。
      因此,我还为“暂存”和“生产”复制粘贴了“开发”环境(请参阅下面的片段)。

        <environment include="Development">
              <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
              <link rel="stylesheet" href="~/css/site.css" />
              <link rel="stylesheet" href="~/css/animate.css">
          </environment>
          <environment exclude="Development">
              <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
                    asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
                    asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
              <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
          </environment>
      
          @*<environment include="Staging,Production"> -> was missing completely!copy pasted from Development*@
          <environment include="Staging,Production">
              <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
              <link rel="stylesheet" href="~/css/site.css" />
              <link rel="stylesheet" href="~/css/animate.css">
          </environment>
          <environment exclude="Staging,Production">
              <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
                    asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
                    asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
              <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
          </environment>
          @*End manually inserted*@
      

      【讨论】:

      • 不,你错了。检查生成的 HTML。 exclude="Development" 将为 Staging 和 Production 执行,并正确使用 CDN 中的 Bootstrap 样式表,而不是直接从 Web 服务器加载并选择缩小版本的 site.css。如果您希望“animate.css”在所有环境中加载,请将其放在环境标签之外。请在此处阅读基础知识以获取更多详细信息:docs.microsoft.com/en-us/aspnet/core/fundamentals/…
      【解决方案8】:

      如果您在 Docker 中遇到此问题,您需要知道“根”是基于您执行 dotnet 命令的位置。我不确定这是否最有意义,但事实就是如此。容易出错的地方是你需要在执行命令之前确保你的 Docker 容器在正确的目录中。

      WORKDIR /app
      # Example publish/build command:
      RUN dotnet publish -o out
      # Your publish folder is /app/out so...
      # ENTRYPOINT ["dotnet", "/app/out/myapp.dll"]
      # will run but you'll get 404s on all your static content. 
      # Instead use:
      WORKDIR /app/out
      ENTRYPOINT ["dotnet", "myapp.dll"]
      

      不要将我的脚本用作正确的 Docker 发布脚本的示例。这只是一个例子。

      【讨论】:

        【解决方案9】:

        我遇到了类似的问题。 (我在 Win 中开发并托管在 Linux 上,以防它有所作为)。只有几个文件有效(大部分是默认文件),但我自己的内容导致了 404。

        罪魁祸首是:文件和文件夹名称中的大写字母对我不起作用。 将所有内容转换为小写,它工作正常。

        【讨论】:

          【解决方案10】:

          在 .NET Core 2.2 MVC 中遇到了同样的问题,将其作为“本地系统”用户的独立 Windows 服务运行。

          问题是windows服务使用“C:\Windows\System32”中的默认目录,所以需要定义新路径:

          .UseWebRoot(@"C:\MyProject\wwwroot\");
          

          这是我用于在运行时检测路径的代码:

          // Find app directory.
          var isService = !(Debugger.IsAttached || args.Contains("--console"));
          var currentDir = Directory.GetCurrentDirectory();
          if (isService)
          {
              var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
              currentDir = Path.GetDirectoryName(pathToExe);
          }
          
          // Configure web host
          var host = WebHost.CreateDefaultBuilder(args)
                  .UseKestrel()
                  .UseContentRoot(currentDir)
                  .UseWebRoot(Path.Combine(currentDir, "wwwroot"));
                  .UseStartup<Startup>()
                  .Build();
          
          // Run.
          if (isService)
          {
              host.RunAsService();
          }
          else
          {
              host.Run();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-14
            • 2019-10-24
            • 2019-10-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多