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

Posted

技术标签:

【中文标题】与多个 Web 应用程序共享控制器和视图【英文标题】:Sharing Controllers and Views with Multiple Web Applications 【发布时间】:2011-06-15 14:36:25 【问题描述】:

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

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

有没有我错过的更简单的方法?

【问题讨论】:

【参考方案1】:

我已经修改了 here 发布的想法,以使用 MVC3。这非常快速和容易。唯一的小缺点是共享视图需要嵌入资源,因此需要编译。

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

在库项目中,将所有视图的 Build Action 属性设置为 Embedded Resource。

在库项目中添加以下代码,将视图的内容写入 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);

【讨论】:

在我的情况下 resStream 为空。ReflectionPermissions (msdn.microsoft.com/en-us/library/xc4235zt(v=vs.110).aspx) 可能存在一些问题。有人有同样的问题吗? 这确实有效。迄今为止最简单的解决方案。道具!【参考方案2】:

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

【讨论】:

我看过 los techies 的帖子。我确信它对人们来说效果很好,但对于我需要的东西来说它完全是矫枉过正。与总线和其他配置的消息传递对我来说似乎很沉重。 Razor 视图编译是视图上的一个属性设置(尽管在每个视图上),仅此而已。【参考方案3】:

只是对 Carson Herrick 的优秀帖子的一些补充...

    您需要解析一些引用(您需要将System.Runtime.Remoting 包含到您的项目中)。

    Utils.SaveStreamToFile需要改为->

    System.Runtime.Remoting.MetadataServices.MetaData.SaveStreamToFile(resStream, rootPath + fileName + "." + extension);
    

    您可能会收到错误消息 - 视图必须派生自 WebViewPageWebViewPage&lt;TModel&gt;。答案就在这里:The view must derive from WebViewPage, or WebViewPage<TModel>

    部署项目时,加载项目时很可能会出错。您需要授予您正在使用的 APP POOL 对该文件夹的(完全)权限。

【讨论】:

以上是关于与多个 Web 应用程序共享控制器和视图的主要内容,如果未能解决你的问题,请参考以下文章

如何在多个视图控制器之间全局共享数据

使用 Core Data 在多个视图控制器之间共享数据

在 MVC 中,与多个 HTML Helpers 共享 Layout 对象的最佳方式是啥

如何将UIWeb视图控制器的内容共享到社交网站?

与多个视图共享数据 - 重构

如何从容器/父视图控制器和多个子视图控制器共享数据数组