Asp.net mvc 使用共享库跨项目共享razor视图

Asp.net mvc 使用共享库跨项目共享razor视图,asp.net-mvc,asp.net-mvc-4,razor,Asp.net Mvc,Asp.net Mvc 4,Razor,我正在尝试从一个项目到另一个项目共享razor视图。首先,我尝试使用RazorGenerator扩展() 但是,我只使用VS2013 Web Express,因此无法正确使用扩展(我只能使用Web Express) 现在,我尝试了这个:,但我无法让它找到视图。我所做的是创建了一个类库“ClassLibrary2”,添加了一个文件夹“Views”,并在其下添加了“Shared”。在“Shared”文件夹中,我添加了一个视图“MyView.cshtml”(这个文件是空的),然后用设置为嵌入资源的“M

我正在尝试从一个项目到另一个项目共享razor视图。首先,我尝试使用RazorGenerator扩展()

但是,我只使用VS2013 Web Express,因此无法正确使用扩展(我只能使用Web Express)

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

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

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

但是仍然找不到视图。

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

具体来说,EmbeddedResourceFile类上的GetResourceName函数将采用虚拟路径(如“~/Views/\u foo.cshtml”)并尝试将其转换为资源的名称(如MyApplication.SomeNamespace.\u 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项目中,我有一个Razor文件,它要求~/Views/\u example.cshtml。MVC将尝试在其所有VirtualPathProviders中查找资源,因此最终将调用GetResourceName函数,以将~/Views/\u example.cshtml解析为资源名称。在我们的例子中。资源名为ViewLibrary.Web.Views.\u 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);
        }
    }
}
使用系统;
使用System.Linq;
运用系统反思;
使用系统线程;
使用System.Web.Hosting;
命名空间视图库
{
公共类EmbeddedResourceViewPathProvider:VirtualPathProvider
{
私有只读惰性资源名=
新建Lazy(()=>Assembly.GetExecutionGassembly().GetManifestResourceNames(),
LazyThreadSafetyMode.执行和发布);
私有布尔资源文件存在(字符串virtualPath)
{
var resourcename=EmbeddedResourceFile
.GetResourceName(虚拟路径);
var result=resourcename!=null
&&_resourceNames.Value.Select(v=>v.ToLower()).Contains(resourcename.ToLower());
返回结果;
}
公共覆盖布尔文件存在(字符串virtualPath)
{
return base.FileExists(virtualPath)
||ResourceFileExists(虚拟路径);
}
公共重写VirtualFile GetFile(字符串virtualPath)
{
如果(!base.FileExists(virtualPath))
{
返回新的EmbeddedResourceFile(virtualPath,_resourceNames);
}
返回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);
        }
    }
}
使用系统;
使用System.IO;
使用System.Linq;
运用系统反思;
使用System.Web.Hosting;
命名空间视图库
{
公共类EmbeddedResourceFile:VirtualFile
{
私有只读资源名称;
公共EmbeddedResourceFile(字符串virtualPath):
基本(虚拟路径)
{
resourceNames=null;
}
公共EmbeddedResourceFile(字符串virtualPath,惰性资源名称):
基本(虚拟路径)
{
this.resourceNames=resourceNames;
}
公共静态字符串GetResourceName(字符串virtualPath)
{
如果(!virtualPath.Contains(“/Views/”)
{
返回null;
}
变量resourceName=
虚拟路径
.Substring(virtualPath.IndexOf(“视图/”))
.Replace(“视图/”,“ViewLibrary.Web.Views.”)
.替换(“/”,“);
返回resourceName;
}
公共覆盖流打开()
{
var assembly=assembly.getExecutionGassembly();
var resourceName=GetResourceName(VirtualPath);
//使资源搜索不区分大小写
if(resourceNames!=null)
{
string foundResource=resourceNames.Value.FirstOrDefault(v=>v.ToLower()==resourceName.ToLower());
if(foundResource!=null)
{
resourceName=foundResource;
}
}
返回assembly.GetManifestResourceStream(resourceName);
}
}
}
[System.Web.WebPages.PageVirtualPathAttribute("~/Views/Shared/Error.cshtml")]