我在尝试自己做类似的事情时发现了这个问题,并且我能够使用链接的文章(共享 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);
}
}
}
希望对您有所帮助,并感谢您将我指向帮助我解决问题的那篇文章!