Why are no embedded files found in EmbeddedFileProvider in asp.net core mvc?

Viewed 5558

I'm currently trying to load embedded ViewComponents from external assemblies.

I've included this in my project file:

<EmbeddedResource Include="Views\**\*.cshtml" />

so when I inspect the actual assembly and run GetManifestResourceNames() I see that the file is embedded.

I'm then calling this method in ConfigureService() in Startup.cs:

public static IMvcBuilder GetModules(this IMvcBuilder mvcBuilder)
    {
        var embeddedFileProviders = new List<EmbeddedFileProvider>
        {
            new EmbeddedFileProvider(Assembly.GetCallingAssembly())
        };

        mvcBuilder.ConfigureApplicationPartManager(apm =>
        {
            foreach (string modulePath in Directory.GetFiles(Configuration.Settings.Path, "*.Module.dll"))
            {
                var assembly = Assembly.LoadFrom(modulePath);
                var startUpType = (from t in assembly.GetTypes()
                                   where t.GetInterfaces().Contains(typeof(IModuleStartup))
                                   select t).FirstOrDefault();

                RegisterModuleServices(mvcBuilder, startUpType);

                apm.ApplicationParts.Add(new AssemblyPart(assembly));        

                embeddedFileProviders.Add(new EmbeddedFileProvider(assembly));

                Modules.Assemblies.Add(assembly);                
            }

            var compositeFileProvider = new CompositeFileProvider(embeddedFileProviders);

            mvcBuilder.Services.AddSingleton<IFileProvider>(compositeFileProvider);

        });

        return mvcBuilder;
    }

I'm also not using

mvcBuilder.Services.Configure<RazorViewEngineOptions>(o => { o.FileProviders.Add(compositeFileProvider); });

as this doesn't work at all and the action o.FileProviders.Add(compositeFileProvider) is not even called.

All the embedded file providers are found when I inject IFileProvider but none of the files are found when I run _fileProvider.GetDirectoryContents("");

Does anybody have any idea why?

5 Answers

In my case I had '.' (period) in the resource filename.

Watch also your project root namespace setting. My case was the reverse - I copy-n-pasted a project file and it did not retain the namespace setting from the previous project. This was because I did not explicitly set <RootNamespace>YourNameSpaceNameHere</RootNamespace> in the .csproj settings (nested under the <PropertyGroup> block at the top), so it took my file name as the namespace! It was quite a "gotcha" moment, and much time lost, to find out my code correctly sets the baseNameSpace parameter, but the whole time the project was storing the files under a different namespace! (you can open the DLL in any text editor, scroll to the bottom, and you should easily be able to make out the embedded text to verify). It was there, just not found. In case someone has this correct, you can also dump ALL files using {Assembly}.GetManifestResourceNames() and make sure your names are correct.

We had another root cause leading to this problem. We had migrate our build agents from windows to linux, and FS case-sensitivity of the latter did the trick - it didn't found embedded resources:

<EmbeddedResource Include="swagger\ui\*" />

because on file system we have Swagger\ui\

So the @(EmbeddedResource) path must be the same as the File System path:

<EmbeddedResource Include="Swagger\ui\*" />

(or rename files/directories, to match the @(EmbeddedResource).

I had this error in an ASPNET Core 3.0 project, where my external class library had the file correctly embedded, but the web application was not locating them at runtime. It turns out the example I copied from the internet had a namespace provided and I copied that example namespace without considering the implications...

After a bit of research, I was able to fix it by simply using the proper root namespace defined my own Class Library:

    var embeddedFileProvider =
        new Microsoft.Extensions.FileProviders
             .EmbeddedFileProvider(assembly, "ViewComponentLibrary");

changed to

var embeddedFileProvider =
    new Microsoft.Extensions.FileProviders
         .EmbeddedFileProvider(assembly, "MyProjectLibrary");
Related