ASP.NET Core 極簡風 - Minimal API 提到只需加一行 UseFileServer(),ASP.NET Core 空白網站就可以像 ASP.NET MVC 一樣,將 .html/.css/.js/圖檔放在 wwwroot 資料夾,支援靜態檔案存取。若要實測,用 dotnet new web 開一個 Minimal API 空白網站,在專案新增 wwwroot 資料夾,放入 ui.html 及 .png [1],Program.cs 則加入一行 UseFileServer() [2],按下 F5 偵測程式,瀏覽器網址輸入 /ui.html [3],網頁順利顯示,是不是超簡單?

適逢農曆新年,順便藉這個 ASP.NET Core 範例跟大家拜年,祝大家健康平安,萬事順心。

如果要用靜態檔案 HTML 當首頁,將其名命為 index.html 放在 wwwroot 下,並移除 app.Get("/", ...) 即可。

使用 dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true --no-self-contained 產生部署檔(參考:使用 dotnet 命令列工具發行 .NET 6 專案),除了 .exe 外,wwwroot 也會一併輸出:

除了 exe 檔外還需要複製 wwwroot 資料夾減損簡潔性,在我心目中,像 GiteaHugo 靠單一執行檔搞定才稱得上是王者風範。所幸,ASP.NET Core 已有內建方法能讓我們實現夢想。(隨著了解愈深,我愈覺得 ASP.NET Core 已成熟到可普遍商用的程度)

ASP.NET Core 有個 Manifest Embedded File Provider,可將 .html/.css/.js/圖檔等靜態檔以內嵌資源(Embedded Resource)形式包進 .exe 或 .dll 檔使用,步驟不多:

  1. 使用 dotnet add package Microsoft.Extensions.FileProviders.Embedded 參照 NuGet 套件
  2. 修改 .csproj,加上 <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> 並以 <EmbeddedResource Include="..." /> 宣告要轉為內嵌資源的目錄或檔案。例如:我將 wwwroot 更名為 ui 資料夾,其下的 index.html 與 happy-new-year.png 用 EmbeddedResource 宣告為內嵌資源,完整名稱為 minApiStFiles.ui.index.html 及 minApiStFiles.ui.happy-new-year.png。csproj 修改如下:
     <Project Sdk="Microsoft.NET.Sdk.Web">
       <PropertyGroup>
         <TargetFramework>net6.0</TargetFramework>
         <Nullable>enable</Nullable>
         <ImplicitUsings>enable</ImplicitUsings>
         <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
       </PropertyGroup>
       <ItemGroup>
         <EmbeddedResource Include="ui\**" />
       </ItemGroup>
       <ItemGroup>
         <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.1" />
       </ItemGroup>
     </Project>
    
  3. 修改 Program.cs,UseFileServer() 時傳入 FileServerOptions,宣告 ManifestEmbeddedFileProvider 並提示命名空間以 ui 起首:
    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.UseFileServer(new FileServerOptions {
        RequestPath = "",
        FileProvider = new Microsoft.Extensions.FileProviders
                        .ManifestEmbeddedFileProvider(
            typeof(Program).Assembly, "ui"
        ) 
    });
    //app.MapGet("/", () => "Hello World!");
    
    app.Run();
    
    註:如果改用 ManifestEmbeddedFileProvider 前曾用過 wwwroot 實體檔案,bin 目錄會殘留 .staticwebasets.runtim.json,請手動刪除或用 dotnet clean 清除,否則會出現找不到 wwwroot 錯誤。我在這上面卡了二十分鐘... orz

就醬,只靠一個 exe 檔,ASP.NET Core 憑空生出 index.html 與 happy-new-year.png,這才是我理想中的極簡風。

ASP.NET Core 好威,.NET 6 真棒!

Tutorial of how to embed wwwroot files into ASP.NET Core executable file to simplify deployment.


Comments

# by 小黑

真的不錯~

# by 螢火蟲

我朋友有一個網站 從舊主機到新主機之後,部署到IIS之後wwwroot底下的img,css,js都不能正常載入,請問您知道可能是什麼原因嗎

# by 螢火蟲

我朋友有一個.netcore網站,從舊主機搬到新主機,wwwroot下的js,css,img都不能正常載入,您知道大概是什麼原因嗎,之前明明可以的。

# by Jeffrey

to 螢火蟲,光由這些描述不太能斷定原因,新主機有安裝 ASP.NET Core Hosting Bundle 嗎? https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-aspnetcore-6.0.4-windows-hosting-bundle-installer 只有這個 ASP.NET Core 網站出問題?若隨便開個空白 ASP.NET Core MVC 專案部署上去可以運作嗎?

# by matt

想請問使用這個方法後,我的靜態檔案是angular build出來的, route不是根目錄時覽器上執行重新整理後出現404,必須要在跟目錄下才能正常運作,目前有解法嗎?

# by Jeffrey

to matt, 對 Anuglar Route 外行,不太懂問題關鍵,如果問題出在 .js 要放在根目錄,我以為放在 /wwwroot 第一層就可以了。

# by matt

謝謝,找到方法了,原本重新導到index.html,改成導到 空字串 就行了。

Post a comment