formatc
formatc

Reputation: 4323

Confusion about VirtualPathProvider, bundling, embedded static files an views

I am trying to share SOME static files(css, images, scripts) and SOME views from separate libraries to few MVC applications, here is my directory structure:

Solution
   Directory 1
      MyContent
        css
          site.css
        images
          img.png
      MyViews
         Account
           Login.cshtml
   Directory 2
      MVCApp1
   Directory 3
      MVCApp2

Here is my ResolveVppPath method:

public static string ResolveVppPath(string path)
{
    // path before looks like ex. ~/shared/content/css/site.css

    path = path.ToLower().Replace("~/shared/","~/my");
    var vp = Path.GetFullPath(Path.Combine(HostingEnvironment.MapPath("~"), "../" + path)); 

    // returns full path + ...  /mycontent/css/site.css ...
    return vp;
}

public static string ResolveSharedControllerPath(string path)
{

        // path before looks like, "~/shared" is ommited in by routing ex. /content/css/site.css

        path = "/my" + path.ToLower().TrimStart(new char[]{'/'})
        var vp = Path.GetFullPath(Path.Combine(HostingEnvironment.MapPath("~"), "../" + path)); 

        // returns full path + ...  /mycontent/css/site.css ...
        return vp;
    }

Original idea was to create abstract controller from which would one controller per app inherit and it was used to resolve paths and return static files from dll, whole thing worked but I was unable to use Bundling because files weren't physical.

Abstract controller to inherit once per app:

public FilesController : Controller
{
    public ActionResult(string path)
        {
       var vp = ResolveSharedControllerPath(path);
           return File(path, MethodToGetMIMEType(path));
    }
}

Once per app:

public SharedController : FilesController {}

Route:

routes.MapRoute(
    "Shared",
    "shared/{*path}",
    new { controller = "Files", action = "Index" }
    );

Then I learned that new beta release of System.Web.Optimization supports bundling from VirtualPathProvider(for which I heard for the first time). So I created two classes: One which inherits from VPP and one which inherits VirtualFile.

Code is to long but in short, since I have physical file it was piece of cake to implement, my Exists() overide just call File.Exist, Open just opens it as stream, So I set:

BundleTable.VirtualPathProvider = new SharedVirtualPathProvider();

Now bundling started working and I got css and scripts to render.

But I got feeling files are being fetched from Controller that I created to serve files, so I tried removing it and shared route, since it didn't make sense to have both Controller to serve files and VirtualPathProvider. After I removed controller bundles stopped working and I could see in firebug 20 not found requests, so I put breakpoint in VPP to see if it is being called, and I could clearly see it called FileExists method in VPP and GetFile with correct path and Open. But this static resources weren't available through browser.

So I decided to put IgnoreRoutes for files with static extensions:

{file}.css
{file}.js
...etc

No luck...

Since that didn't do anything I included controller and route agian for serving files. Everything started working again.

Next step was to move some of views to DLL, I cut and pasted views to MyViewsDLL but now I get XML parsing error in firefox on first line at "@model.." and besides this couldn't work since I don't want people to see my Views unrendered code. I also had to Implement custom ViewEngine, which overidded path where engine looks for views, I added

"~/Shared/views/{1}/{0}

to paths and and added my ViewEngine to ViewEngines collection in global.asax thinking maybe that's why evrything is going through controller, I also registered my VirtualPathProvider but nothing changed

My question is:

I have VPS hosting(so I have full controll over IIS), will I have troubles trying to go up folder(and then in DLL folder) from application for files?

Do I really need both VPP and and Controller to return static files?

How do I get views from DLL without them being available through browser so anyone can see them?

Can I serve static files with only VPP?

UPDATE: Updated directory structure

Upvotes: 3

Views: 2117

Answers (1)

mcintyre321
mcintyre321

Reputation: 13306

My EmbeddedResourceVirtualPathProvider will help you out. It allows having some, or all static files and views in other projects.

http://nuget.org/packages/EmbeddedResourceVirtualPathProvider/

You shouldn't need a controller, the VPP and some mappings (which are set up in web.config by the Nuget package) are enough.

edit: I haven't tested it with the Bundler, but I don't see why it shouldn't work.

Upvotes: 4

Related Questions