【问题标题】:Sharing razor views across projects using a shared library使用共享库跨项目共享剃须刀视图
【发布时间】:2015-10-12 02:46:04
【问题描述】:

我正在尝试从一个项目到另一个项目共享一个清晰的视图。起初,我尝试使用 RazorGenerator 扩展 (Precompile your MVC Razor views using RazorGenerator)

但是,我只使用 VS 2013 Web Express,所以我无法正确使用扩展程序(我只能使用 Web Express)。

现在,我已经尝试过:Sharing MVC Views,但我无法让它找到视图。我所做的是创建了一个类库“ClassLibrary2”,添加了一个文件夹“Views”,并在其下添加了“Shared”。在“Shared”文件夹中,我添加了一个视图“MyView.cshtml”(该文件为空),然后将“MyView.cshtml”设置为嵌入资源编译项目。

之后,我创建了一个新的 MVC 项目(MVC 模板),引用了“ClassLibrary2”并添加了页面中提到的代码(“EmbeddedResourceViewPathProvider”和“EmbeddedResourceFile”类)。还在 Application_Start() 和“EmbeddedResourceFile”的代码中添加了代码,我已更改为:

var resourcename = 
        virtualPath
        .Substring(virtualPath.IndexOf("Views/"))
        // NB: Your assembly name here
        .Replace("Views/", "ClassLibrary2.")
        .Replace("/", ".");

但还是找不到视图。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 razor


    【解决方案1】:

    我在尝试自己做类似的事情时发现了这个问题,并且我能够使用链接的文章(共享 MVC 视图)来完成将视图共享为来自另一个程序集的资源。如果您仍在尝试解决此问题,发布更多代码可能会有所帮助。我发现开箱即用的方法对我来说不太适用。根本问题是确保资源名称请求“命中”您的 EmbeddedResourceViewPathProvider 有点棘手。

    具体来说,EmbeddedResourceFile 类上的 GetResourceName 函数将采用虚拟路径(如“~/Views/_foo.cshtml”)并尝试将其转换为资源名称(如 MyApplication.SomeNamespace._foo.cshtml) ;这一行:

       var resourcename = 
            virtualPath
            .Substring(virtualPath.IndexOf("Views/"))
            // NB: Your assembly name here
            .Replace("Views/", "LeapingGorilla.Common.MVC.Views.")
            .Replace("/", ".");
    

    可能具有误导性,因为它说的是“您的程序集名称”,而您真正想要的是一个命名空间(不一定相同,在我的情况下也不一定相同)。我发现实施建议的解决方案很有帮助,然后通过 ResourceFileExists 函数进行调试以查看解决方案在寻找什么。举个例子:

    假设我有一个名为 ViewLibrary 的项目,其文件夹/文件结构如下:

    ViewLibrary
    |-->Web
    |---->Views
    |------>_example.cshtml
    

    在一个引用 ViewLibrary 的 Web 项目中,我有一个要求 ~/Views/_example.cshtml 的 Razor 文件。 MVC 将尝试在其所有 VirtualPathProviders 中查找资源,因此最终将调用 GetResourceName 函数以将 ~/Views/_example.cshtml 解析为资源名称。在我们的例子中。该资源名为 ViewLibrary.Web.Views._example.cshtml,因此替换需要如下所示:

    .Replace("Views/", "ViewLibrary.Web.Views.")
    

    我遇到的另一个问题是 MVC 会将路径名小写,因此您可能必须调整实际获取资源的函数,因此请考虑这一点。对于我的解决方案,我实际上让路径提供程序将资源文件对象传递给资源名称数组,以便以不区分大小写的方式解析它。这是一个完整的示例,说明了我如何将它们组合在一起:

    ViewLibrary/EmbeddedResourceViewPathProvider.cs:

    using System;
    using System.Linq;
    using System.Reflection;
    using System.Threading;
    using System.Web.Hosting;
    
    namespace ViewLibrary
    {
        public class EmbeddedResourceViewPathProvider : VirtualPathProvider
        {
            private readonly Lazy<string[]> _resourceNames =
                new Lazy<string[]>(() => Assembly.GetExecutingAssembly().GetManifestResourceNames(),
                    LazyThreadSafetyMode.ExecutionAndPublication);
    
            private bool ResourceFileExists(string virtualPath)
            {
                var resourcename = EmbeddedResourceFile
                                    .GetResourceName(virtualPath);
                var result = resourcename != null
                    && _resourceNames.Value.Select(v => v.ToLower()).Contains(resourcename.ToLower());
    
                return result;
            }
    
            public override bool FileExists(string virtualPath)
            {
                return base.FileExists(virtualPath)
                    || ResourceFileExists(virtualPath);
            }
    
            public override VirtualFile GetFile(string virtualPath)
            {
                if (!base.FileExists(virtualPath))
                {
                    return new EmbeddedResourceFile(virtualPath, _resourceNames);
                }
    
                return base.GetFile(virtualPath);
            }
        }
    }
    

    ViewLibrary/EmbeddedResourceFile.cs:

    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Web.Hosting;
    
    namespace ViewLibrary
    {
        public class EmbeddedResourceFile : VirtualFile
        {
            private readonly Lazy<string[]> resourceNames;
    
            public EmbeddedResourceFile(string virtualPath) :
                base(virtualPath)
            {
                resourceNames = null;
            }
    
            public EmbeddedResourceFile(string virtualPath, Lazy<string[]> resourceNames) :
                base(virtualPath)
            {
                this.resourceNames = resourceNames;
            }
    
            public static string GetResourceName(string virtualPath)
            {
                if (!virtualPath.Contains("/Views/"))
                {
                    return null;
                }
    
                var resourceName =
                    virtualPath
                    .Substring(virtualPath.IndexOf("Views/"))
                    .Replace("Views/", "ViewLibrary.Web.Views.")
                    .Replace("/", ".");
    
                return resourceName;
            }
    
            public override Stream Open()
            {
                var assembly = Assembly.GetExecutingAssembly();
                var resourceName = GetResourceName(VirtualPath);
                // Make resource search case-insensitive
                if (resourceNames != null)
                {
                    string foundResource = resourceNames.Value.FirstOrDefault(v => v.ToLower() == resourceName.ToLower());
                    if (foundResource != null)
                    {
                        resourceName = foundResource;
                    }
                }
                return assembly.GetManifestResourceStream(resourceName);
            }
        }
    }
    

    希望对您有所帮助,并感谢您将我指向帮助我解决问题的那篇文章!

    【讨论】:

      【解决方案2】:

      这是 Mira Javora 使用 Visual Studio 扩展 RazorGenerator 撰写的一篇不错的文章...

      http://blog.mirajavora.com/re-use-mvc-views-across-projects-with-razor-generator/

      实际上,这篇文章使用 RazorGenerator 工具将 .cshtml 文件编译为 .cs 文件。生成的 .cs 文件包含一个虚拟路径 - 例如...

      [System.Web.WebPages.PageVirtualPathAttribute("~/Views/Shared/Error.cshtml")]
      

      我按照文章中的说明进行操作,而且第一次效果非常好。好文章。

      【讨论】:

        猜你喜欢
        • 2019-02-17
        • 1970-01-01
        • 1970-01-01
        • 2011-10-31
        • 2013-02-23
        • 2013-08-05
        • 2015-12-12
        • 1970-01-01
        • 2018-07-14
        相关资源
        最近更新 更多