21

ScottGu mentioned that we should be able to load a Razor view from a database (check the comments section), so does anybody have an example on how to do that?

Thanks.

pbz
  • 8,865
  • 14
  • 56
  • 70

1 Answers1

30

You might want to check Pulling a View from a database rather than a file or Using VirtualPathProvider to load ASP.NET MVC views from DLLs

Taking the code from my previous question on the subject.

In your FileExists() method on the other page you replace the test code I have there with some db code that actually checks to see if the virtualPath has an entry in your database. Your database would look something like:

Views --tablename
    Path --view's virtual path
    SomeOtherValue

...and your call would then be something like

public class DbPathProvider : VirtualPathProvider {
    public DbPathProvider() : base() {

    }

    public override bool FileExists(string virtualPath) {
        Database db = new Database();
        return db.Views.Any(w => w.Path == virtualPath);
    }

    public override VirtualFile GetFile(string virtualPath) {
        return new DbVirtualFile(virtualPath);
    }
}

And now we modify the DbVirtualFile

public class DbVirtualFile : System.Web.Hosting.VirtualFile {

    public DbVirtualFile(string path) : base (path) {

    }

    public override System.IO.Stream Open() {
        Database db = new Database();
        return new System.IO.MemoryStream(
                   db.Views.Single(v => v.Path == this.VirtualPath));
    }
}

The virtualPath doesn't have to correspond to a real filesystem if you don't want it to. You can override the functionality by implementing these two classes.

You can then register your new VirtualPathProvider in the global.asax like so

HostingEnvironment.RegisterVirtualPathProvider(new DbPathProvider());

I hope this better answers your question.

Community
  • 1
  • 1
Buildstarted
  • 26,529
  • 10
  • 84
  • 95
  • Maybe I'm missing something, but in the tutorial the solution points to (http://www.umbraworks.net/bl0g/rebuildall/2009/11/17/ASP_NET_MVC_and_virtual_views) the condition is to have an actual file on disk (/View/Pages/Test.aspx) and just supply the "filling." I'm looking for a solution that allows me to specify the entire page. – pbz Nov 19 '10 at 00:56
  • Updated question based on confusion as to the virtual paths – Buildstarted Nov 19 '10 at 15:16
  • I'm working with an example right now that doesn't use a database. In FileExists I check for "/View/Home/Test.cshtml" (my virtual file) and in the Open method I return new MemoryStream(Encoding.ASCII.GetBytes("

    Hi

    ")); When I do this I get "Directory '[..]\View\Home' does not exist. Failed to start monitoring file changes." Any thoughts? Thanks for your help!
    – pbz Nov 20 '10 at 02:23
  • Could you post your code in your question - the simplest way to test is to forcibly return true in the `FileExists` method - also did you register your VirtualPathProvider? – Buildstarted Nov 21 '10 at 06:30
  • If the file doesn't exist on disk you need to implement the directory components of the VirtualPathProvider - when I set up something similar I found that the system was actually working from a list of all available views loaded on the first request rather than just calling FileExists on each request. – Tom Clarkson Mar 03 '11 at 00:20
  • 7
    @pbz override GetCacheDependency in your vpp returning null where the view is from your db – Anthony Johnston Apr 25 '11 at 10:50