Asp.net mvc 使用共享库跨项目共享razor视图
我正在尝试从一个项目到另一个项目共享razor视图。首先,我尝试使用RazorGenerator扩展() 但是,我只使用VS2013 Web Express,因此无法正确使用扩展(我只能使用Web Express) 现在,我尝试了这个:,但我无法让它找到视图。我所做的是创建了一个类库“ClassLibrary2”,添加了一个文件夹“Views”,并在其下添加了“Shared”。在“Shared”文件夹中,我添加了一个视图“MyView.cshtml”(这个文件是空的),然后用设置为嵌入资源的“MyView.cshtml”编译项目 在此之后,我创建了一个新的MVC项目(MVC模板),引用了“ClassLibrary2”,并添加了页面中提到的代码(“EmbeddedResourceViewPathProvider”和“EmbeddedResourceFile”类)。还添加了应用程序_Start()上的代码,在“EmbeddedResourceFile”的代码中,我改为: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
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")]