使用多个Web应用程序共享控制器和视图

时间:2011-01-26 02:05:42

标签: asp.net-mvc-3 razor

我想将控制器和视图分解为单独的类库,以便可以在多个ASP.NET MVC 3应用程序中重用它们。使用单独的程序集时控制器部分不是问题,但是让视图引擎定位视图是。

我最终使用了Compile your asp.net mvc Razor views into a seperate dll

我错过了一种更容易的方法吗?

3 个答案:

答案 0 :(得分:18)

我修改了发布here的想法,以便与MVC3合作。它非常快速和简单。唯一的小缺点是共享视图需要嵌入资源,因此需要编译。

  • 将您的共享视图(.cshtml,.vbhtml文件)放入库项目中。 (我在这个项目中也有一些共享控制器。)如果你想使用你的应用程序中的_Layout.cshtml,请确保你的共享视图中包含一个指向它的_ViewStart.cshtml。

    < / LI>
  • 在库项目中,将所有视图的“构建操作”属性设置为“嵌入资源”。

  • 在库项目中添加以下代码,将您的视图内容写入tmp / Views目录。

public class EmbeddedResourceViewEngine : RazorViewEngine
{
    public EmbeddedResourceViewEngine()
    {
        ViewLocationFormats = new[] {
        "~/Views/{1}/{0}.aspx",
        "~/Views/{1}/{0}.ascx",
        "~/Views/Shared/{0}.aspx",
        "~/Views/Shared/{0}.ascx",
        "~/Views/{1}/{0}.cshtml",
        "~/Views/{1}/{0}.vbhtml",
        "~/Views/Shared/{0}.cshtml",
        "~/Views/Shared/{0}.vbhtml",
        "~/tmp/Views/{0}.cshtml",
        "~/tmp/Views/{0}.vbhtml"
    };
        PartialViewLocationFormats = ViewLocationFormats;

        DumpOutViews();
    }

    private static void DumpOutViews()
    {
        IEnumerable<string> resources = typeof(EmbeddedResourceViewEngine).Assembly.GetManifestResourceNames().Where(name => name.EndsWith(".cshtml"));
        foreach (string res in resources) { DumpOutView(res); }
    }

    private static void DumpOutView(string res)
    {
        string rootPath = HttpContext.Current.Server.MapPath("~/tmp/Views/");
        if (!Directory.Exists(rootPath))
        {
            Directory.CreateDirectory(rootPath);
        }

        Stream resStream = typeof(EmbeddedResourceViewEngine).Assembly.GetManifestResourceStream(res);
        int lastSeparatorIdx = res.LastIndexOf('.');
        string extension = res.Substring(lastSeparatorIdx + 1);
        res = res.Substring(0, lastSeparatorIdx);
        lastSeparatorIdx = res.LastIndexOf('.');
        string fileName = res.Substring(lastSeparatorIdx + 1);

        Util.SaveStreamToFile(rootPath + fileName + "." + extension, resStream);
    }
}

我正在使用Adrian的StreamToFile编写器,找到了here

  • 在应用程序的Global.asax.cs中添加:

public static void RegisterCustomViewEngines(ViewEngineCollection viewEngines)
{
   //viewEngines.Clear(); //This seemed like a bad idea to me.
   viewEngines.Add(new EmbeddedResourceViewEngine());
}

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    RegisterCustomViewEngines(ViewEngines.Engines);
}

答案 1 :(得分:3)

看看mvc contrib的便携区域: http://www.lostechies.com/blogs/hex/archive/2009/11/01/asp-net-mvc-portable-areas-via-mvccontrib.aspx 它们是专门为此目的而制作的。如果你走那条路,你需要的代码就少了; - )

答案 2 :(得分:3)

卡森赫里克的优秀帖子只增加了一些......

  1. 您需要解决一些参考资料(您需要在项目中加入System.Runtime.Remoting)。

  2. Utils.SaveStreamToFile需要更改为 - &gt;

    System.Runtime.Remoting.MetadataServices.MetaData.SaveStreamToFile(resStream, rootPath + fileName + "." + extension);
    
  3. 您可能会收到错误 - 视图必须来自WebViewPageWebViewPage<TModel>。答案在这里:The view must derive from WebViewPage, or WebViewPage<TModel>

  4. 部署项目时,很有可能在加载项目时出现错误。您需要向APP POOL提供您正在使用该文件夹的(完整)权限。