Miniweb asp.net core

Embedded razor views in your assembly and serve them on runtime

View project on GitHub

This used to require some work, but...

But now we can just create just use a Razor Class Library. The old way used to work fine as well, will leave it here for reference if needed:


Embedded razor views in your assembly

To embed Razor Views into your assembly you not only need the same setupt as normal assets in the project.json file

"resource": "Resources/admin.js;Resources/admin.css;Resources/bootstrap-wysiwyg.js;Resources/adminview.cshtml",

But you also need to create an EmbeddedFileProvider that either serves your embedded file when it is called for by a specific path, which mostly will be a path other than the embedded path itself. You can create an EmbeddedFileProvider like this:

using ....
using Microsoft.Extensions.FileProviders;

public class MiniWebFileProvider : IFileProvider
{
    readonly IFileProvider _embeddedFileProvider;
    readonly string _embeddedFilePath;
    
    public MiniWebFileProvider(string embeddedFilePath)
    {
        // Set the Assembly and Namespace of the embedded Razor Views that need to be served, in this case the current assembly
        _embeddedFileProvider = new EmbeddedFileProvider(this.GetType().GetTypeInfo().Assembly, this.GetType().Namespace);
        // Set the path to listen to for the embedded files so you can differentiate between Physical en Embedded based on folder and filename
        _embeddedFilePath = embeddedFilePath;
    }
    
    public IDirectoryContents GetDirectoryContents(string subpath)
    {
        return null;
    }
    
    public IFileInfo GetFileInfo(string filepath)
    {
        // In this example only listen to one filename from the specified listening folder
        if (subpath == _embeddedFilePath + "adminview.cshtml")
        {
            // If so serve the embedded file (note the path is different in the embedded file that in the listening file, also make sure it is Case Correct because of Linux
            return  _embeddedFileProvider.GetFileInfo($"Resources/adminview.cshtml");
        }
        return null;
        
    }
    
    // Required overload, the EmbeddedFileProvider Watch just ignores the call for the embedded files.
    public IChangeToken Watch(string filter)
    {
        if (filter == _embeddedFilePath + "adminview.cshtml")
        {
            return _embeddedFileProvider.Watch(filter);
        }
        return null;
    }
}
        

So the main takeway is that you can listen for the file on a different path than the embedded path itself which is a good idea. This way you can make the listening path configurable so it will never clash with the paths fo the application that is uses the embedded views.

I don't think you need the GetDirectoryContens overload but you could easily implement it to switch on the filepath, and for serving multiple files you could try to find the in the embedded files by filename and return the specific FileInfo from that.

Finally you need to register you fileprovider in the ConfigureServices method of the Startup class of your application. Best to Insert it into the ProviderList at the zero index, this way the embedded file will take presidence above any other physical files.

    services.Configure<RazorViewEngineOptions>(options => { options.FileProviders.Insert(0, new MiniWebFileProvider(embeddedFilePath)); });

Thanks,

Rooc