Embed files for a Nuget ASP.NET Core package

For NetCoreBlockly I have the need to embed some files in the NUGET package (https://www.nuget.org/packages/NetCore2Blockly ) to display a GUI.

After unsuccessful trying to deploy, I  have read https://weblog.west-wind.com/posts/2018/Jan/29/Distributing-Content-and-Showing-a-ReadMe-file-in-a-NET-Core-Nuget-Package .

So I must learn from the experts: e.g. , swagger : https://github.com/domaindrivendev/Swashbuckle.AspNetCore it is displaying the HTML UI.  How it does ? By embedding into the .csproj the index.html : https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerUI/Swashbuckle.AspNetCore.SwaggerUI.csproj

But NetCoreBlockly have more than 1 file – more js, more css … and I want to be done automatically.

So I solved this in 3 steps:

 

  1. I Embed all files from a folder in the nuget csproj

<ItemGroup>
<EmbeddedResource Include=”blocklyFiles\**\*”>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>

2. In the NuGet I obtain the files as embedded

var manifestEmbeddedProvider =
new ManifestEmbeddedFileProvider(Assembly.GetExecutingAssembly());

3. I generate ASP.NET Core endpoints for each file from the Embed, according to the tree :

private static void mapFile(string dirName, IFileProvider provider, IApplicationBuilder appBuilder)
{
var folder = provider.GetDirectoryContents(dirName);
foreach (var item in folder)
{
    if (item.IsDirectory)
    {
        mapFile(dirName + "/" + item.Name, provider, appBuilder);
        continue;
    }
    string map = (dirName + "/" + item.Name).Substring("blocklyFiles".Length);
    appBuilder.Map(map, app =>
    {
        var f = item;

        app.Run(async cnt =>
        {
            //TODO: find from extension
            //cnt.Response.ContentType = "text/html";
            using var stream = new MemoryStream();
            using var cs = f.CreateReadStream();
            byte[] buffer = new byte[2048]; // read in chunks of 2KB
            int bytesRead;
            while ((bytesRead = cs.Read(buffer, 0, buffer.Length)) > 0)
            {
                stream.Write(buffer, 0, bytesRead);
            }
            byte[] result = stream.ToArray();
            var m = new Memory<byte>(result);
            await cnt.Response.BodyWriter.WriteAsync(m);
        });
    });
}

}        

Optional:

4. Because I need to test , copy the files in the CI from a real ASP.NET Core website to the .csproj with the NUGET package

5. You can replace some tags with your values – or just use a .js file that generates options ( see BlocklyUIOptions  below)

 

If you want to see in Action, browse to https://netcoreblockly.herokuapp.com/blockly.html

If you want to see the code, goto https://github.com/ignatandrei/NETCoreBlockly/blob/master/src/NetCore2Blockly/NetCore2Blockly/ExtensionMethods/CLIExtension.cs and see public static void UseBlocklyUI(this IApplicationBuilder appBuilder, BlocklyUIOptions options =null)