我正在尝试从一个项目到另一个项目共享剃刀视图。起初,我尝试使用RazorGenerator扩展程序(Precompile your MVC Razor views using RazorGenerator)
但是,我只使用VS 2013 Web Express,因此无法正常使用扩展程序(我只能使用Web Express)。
现在,我已经尝试了这个:Sharing MVC Views,但我无法让它找到视图。我所做的是创建了一个类库" ClassLibrary2",添加了一个文件夹" Views"在它下面"共享"。在"共享"文件夹,我添加了一个视图" MyView.cshtml" (此文件为空)然后使用" MyView.cshtml"编译项目。设置为嵌入式资源。
在此之后,我创建了一个新的MVC项目(MVC模板),引用了" ClassLibrary2"并添加了页面中提到的代码(" EmbeddedResourceViewPathProvider"以及" EmbeddedResourceFile"类)。还在Application_Start()和#34; EmbeddedResourceFile"的代码中添加了代码,我已更改为:
var resourcename =
virtualPath
.Substring(virtualPath.IndexOf("Views/"))
// NB: Your assembly name here
.Replace("Views/", "ClassLibrary2.")
.Replace("/", ".");
但是,仍然找不到视图。
答案 0 :(得分:0)
我在尝试自己做类似的事情时发现了这个问题,并且我能够使用链接文章(共享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("/", ".");
可能会产生误导,因为它说'#34;你的汇编名称在这里",当你真正想要的时候有一个命名空间(不一定是相同的,在我的情况下确实不一样)。我发现实现建议的解决方案很有帮助,然后通过ResourceFileExists函数调试以查看解决方案正在寻找什么。让我们举一个例子:
假设我有一个名为ViewLibrary的项目,其文件夹/文件结构如下:
ViewLibrary
|-->Web
|---->Views
|------>_example.cshtml
在一个引用ViewLibrary的Web项目中,我有一个Razor文件要求〜/ Views / _example.cshtml。 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);
}
}
}
希望有所帮助,感谢您指点我帮助我解决问题的文章!
答案 1 :(得分:0)
这是Mira Javora使用Visual Studio Extension 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")]
我遵循了写作的说明,并且它第一次工作。好文章。