Embedded razor views

2020-07-18 09:36发布

Recently, I read a post where the author describes how we can compile razor views into separate libraries. I would like to ask, is it possible to embed views in libraries without compiling? And then, add custom VirtualPathProvider to read the views.

2条回答
Emotional °昔
2楼-- · 2020-07-18 10:07

In your "shell" MVC project's Global.asax Application_Start register your custom VirtualPathProvider:

HostingEnvironment.RegisterVirtualPathProvider(new CustomVirtualPathProvider());

The actual implementation would be more complex than this because you would likely do some interface-based, reflection, database lookup, etc as a means of pulling metadata, but this would be the general idea (assume you have another MVC project named "AnotherMvcAssembly" with a Foo controller and the Index.cshtml View is marked as an embedded resource:

public class CustomVirtualPathProvider : VirtualPathProvider {
    public override bool DirectoryExists(string virtualDir) {
        return base.DirectoryExists(virtualDir);
    }

    public override bool FileExists(string virtualPath) {
        if (virtualPath == "/Views/Foo/Index.cshtml") {
            return true;
        }
        else {
            return base.FileExists(virtualPath);
        }
    }

    public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart) {
        if (virtualPath == "/Views/Foo/Index.cshtml") {
            Assembly asm = Assembly.Load("AnotherMvcAssembly");
            return new CacheDependency(asm.Location);
        }
        else {
            return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }
    }

    public override string GetCacheKey(string virtualPath) {
        return base.GetCacheKey(virtualPath);
    }

    public override VirtualDirectory GetDirectory(string virtualDir) {
        return base.GetDirectory(virtualDir);
    }

    public override VirtualFile GetFile(string virtualPath) {
        if (virtualPath == "/Views/Foo/Index.cshtml") {
            return new CustomVirtualFile(virtualPath);
        }
        else {
            return base.GetFile(virtualPath);
        }
    }
}

public class CustomVirtualFile : VirtualFile {
    public CustomVirtualFile(string virtualPath) : base(virtualPath) { }

    public override System.IO.Stream Open() {
        Assembly asm = Assembly.Load("AnotherMvcAssembly");
        return asm.GetManifestResourceStream("AnotherMvcAssembly.Views.Foo.Index.cshtml");
    }
}
查看更多
啃猪蹄的小仙女
3楼-- · 2020-07-18 10:22

You can use my EmbeddedResourceVirtualPathProvider which can be installed via Nuget. It loads resources from referenced assemblies, and also can be set to take dependencies on the source files during development so you can update views without needing a recompile.

查看更多
登录 后发表回答