对MVC很新,所以如果我忽略了一个主要概念,请原谅我。
我将项目简化为两个基本项目,以查看我缺少的概念。我有两个MVC项目,一个名为“Path”,另一个名为“Guru”。作为启动项目的路径,我能够访问Guru控制器“Shine”的路径,但是当它尝试返回视图时,它无法找到视图。
然后我将views文件夹从Guru复制到Path并且程序运行良好我可以从Guru调用控制器,反过来它似乎使用Paths视图文件夹。我的问题是如何设置某种路由以到达Guru中的views文件夹?
我曾尝试过一个自定义视图引擎,但我不确定如何告诉所述引擎进入Guru而不是“Path”。将每个视图复制到Path项目中似乎非常不切实际,也不是最好的方法。
在下面的代码中,我只是简单地告诉程序查看与目前正在查看的位置相同的位置。
public class GuruViewEngine : VirtualPathProviderViewEngine
{
public GuruViewEngine()
{
// Define the location of the View file
this.ViewLocationFormats = new string[]
{ "~/Views/Shine/{1}/{0}", "~/Views/Shared/{0}" };
this.PartialViewLocationFormats = new string[]
{ "~/Views/{1}/{0}", "~/Views/Shared/{0}" };
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
var physicalpath = controllerContext.HttpContext.Server.MapPath(partialPath);
return new GuruView(physicalpath);
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var physicalpath = controllerContext.HttpContext.Server.MapPath(viewPath);
return new GuruView(physicalpath);
}
}
答案 0 :(得分:0)
要从程序集中获取View文件(其他项目也是如此),您可以使用下面的代码。您需要将视图的内容类型设置为嵌入式资源。
public class AssemblyVirtualPathProvider : VirtualPathProvider
{
private readonly Assembly assembly;
private readonly IEnumerable<VirtualPathProvider> providers;
public AssemblyVirtualPathProvider(Assembly assembly)
{
var engines = ViewEngines.Engines.OfType<VirtualPathProviderViewEngine>().ToList();
this.providers = engines.Select(x => x.GetType().GetProperty("VirtualPathProvider", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(x, null) as VirtualPathProvider).Distinct().ToList();
this.assembly = assembly;
}
public override CacheDependency GetCacheDependency(String virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (this.FindFileByPath(this.CorrectFilePath(virtualPath)) != null)
{
return (new AssemblyCacheDependency(assembly));
}
else
{
return (base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart));
}
}
public override Boolean FileExists(String virtualPath)
{
foreach (var provider in this.providers)
{
if (provider.FileExists(virtualPath) == true)
{
return (true);
}
}
var exists = this.FindFileByPath(this.CorrectFilePath(virtualPath)) != null;
return (exists);
}
public override VirtualFile GetFile(String virtualPath)
{
var resource = null as Stream;
foreach (var provider in this.providers)
{
var file = provider.GetFile(virtualPath);
if (file != null)
{
try
{
resource = file.Open();
return (file);
}
catch
{
}
}
}
var resourceName = this.FindFileByPath(this.CorrectFilePath(virtualPath));
return (new AssemblyVirtualFile(virtualPath, this.assembly, resourceName));
}
protected String FindFileByPath(String virtualPath)
{
var resourceNames = this.assembly.GetManifestResourceNames();
return (resourceNames.SingleOrDefault(r => r.EndsWith(virtualPath, StringComparison.OrdinalIgnoreCase) == true));
}
protected String CorrectFilePath(String virtualPath)
{
return (virtualPath.Replace("~", String.Empty).Replace('/', '.'));
}
}
public class AssemblyVirtualFile : VirtualFile
{
private readonly Assembly assembly;
private readonly String resourceName;
public AssemblyVirtualFile(String virtualPath, Assembly assembly, String resourceName) : base(virtualPath)
{
this.assembly = assembly;
this.resourceName = resourceName;
}
public override Stream Open()
{
return (this.assembly.GetManifestResourceStream(this.resourceName));
}
}
public class AssemblyCacheDependency : CacheDependency
{
private readonly Assembly assembly;
public AssemblyCacheDependency(Assembly assembly)
{
this.assembly = assembly;
this.SetUtcLastModified(File.GetCreationTimeUtc(assembly.Location));
}
}