关于VirtualPathProvider的混淆,捆绑,嵌入静态文件的视图

时间:2013-05-23 10:39:33

标签: c# asp.net-mvc asp.net-mvc-routing

我正在尝试分享一些静态文件(css,图像,脚本)和从单独的库到少数MVC应用程序的一些视图,这是我的目录结构:

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

这是我的ResolveVppPath方法:

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;
    }

最初的想法是创建抽象控制器,每个应用程序将继承一个控制器并且它用于解析路径并从dll返回静态文件,整个工作正常但我无法使用Bundling,因为文件不是物理的。

抽象控制器每个应用程序继承一次:

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

每个应用一次:

public SharedController : FilesController {}

路线:

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

然后我了解到System.Web.Optimization的新beta版本支持从VirtualPathProvider捆绑(我第一次听到)。所以我创建了两个类:一个继承自VPP,另一个继承VirtualFile。

代码很长,但简而言之,因为我有物理文件,它实现了一块蛋糕,我的Exists()只是调用File.Exist,Open只是打开它作为流,所以我设置:

BundleTable.VirtualPathProvider = new SharedVirtualPathProvider();

现在捆绑开始工作了,我得到了css和脚本来渲染。

但是我感觉文件是从我创建的控制器中提取文件的,所以我尝试删除它和共享路由,因为让控制器提供文件和VirtualPathProvider是没有意义的。我删除控制器捆绑后停止工作,我可以在firebug 20中看到未找到请求,所以我在VPP中放置断点以查看它是否被调用,我可以清楚地看到它在VPP和GetFile中使用正确的路径和OpenFile方法。但是这些静态资源无法通过浏览器获得。

所以我决定将IgnoreRoutes放在具有静态扩展名的文件中:

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

没有运气......

由于没有做任何事情,我将控制器和路由agian包含在服务文件中。一切都开始了。

下一步是将一些视图移动到DLL,我将视图剪切并粘贴到MyViewsDLL,但现在我在第一行的“@model ..”中获得了Firefox解析错误,此外这不起作用,因为我不知道不希望别人看到我的视图未呈现的代码。我还必须实现自定义的ViewEngine,它覆盖了引擎查找视图的路径,我添加了

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

到路径并将我的ViewEngine添加到global.asax中的ViewEngines集合中思考也许这就是为什么evrything通过控制器,我也注册了我的VirtualPathProvider但没有改变

我的问题是:

我有VPS主机(因此我对IIS有完全的控制权),我是否会遇到从文件应用程序上升文件夹(然后在DLL文件夹中)的麻烦?

我真的需要VPP和Controller来返回静态文件吗?

如果没有通过浏览器访问DLL,我如何从DLL获取视图,以便任何人都可以看到它们?

我可以只使用VPP提供静态文件吗?

更新:更新了目录结构

1 个答案:

答案 0 :(得分:4)

我的EmbeddedResourceVirtualPathProvider将帮助您。它允许在其他项目中拥有一些或所有静态文件和视图。

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

您不需要控制器,VPP和一些映射(由Nuget包在web.config中设置)就足够了。

编辑:我没有用Bundler测试它,但我不明白为什么它不应该工作。