我正在尝试创建一个web应用程序,我希望能够插入单独的程序集.我正在使用MVC预览4和Unity结合依赖注入,我用它来从我的插件程序集创建控制器.我正在使用WebForms(默认的aspx)作为我的视图引擎.
如果我想使用一个视图,我会坚持核心项目中定义的视图,因为ASPX部分的动态编译.我正在寻找一种将ASPX文件封装在不同程序集中的正确方法,而无需完成整个部署步骤.我错过了一些明显的东西吗 或者我应该以编程方式创建我的观点?
更新:我改变了接受的答案.尽管戴尔的答案非常彻底,但我还是选择了不同的虚拟路径提供商.它的工作方式就像一个魅力,我认为完全只需要20行代码.
我花了太长时间才能从各种部分样本中正常工作,所以这里是从共享库中的Views文件夹获取视图所需的完整代码,其结构与常规Views文件夹相同,但所有内容都设置为嵌入式构建资源.如果通常的文件不存在,它将只使用嵌入的文件.
Application_Start的第一行:
HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedViewPathProvider());
VirtualPathProvider
public class EmbeddedVirtualFile : VirtualFile { public EmbeddedVirtualFile(string virtualPath) : base(virtualPath) { } internal static string GetResourceName(string virtualPath) { if (!virtualPath.Contains("/Views/")) { return null; } var resourcename = virtualPath .Substring(virtualPath.IndexOf("Views/")) .Replace("Views/", "OrangeGuava.Common.Views.") .Replace("/", "."); return resourcename; } public override Stream Open() { Assembly assembly = Assembly.GetExecutingAssembly(); var resourcename = GetResourceName(this.VirtualPath); return assembly.GetManifestResourceStream(resourcename); } } public class EmbeddedViewPathProvider : VirtualPathProvider { private bool ResourceFileExists(string virtualPath) { Assembly assembly = Assembly.GetExecutingAssembly(); var resourcename = EmbeddedVirtualFile.GetResourceName(virtualPath); var result = resourcename != null && assembly.GetManifestResourceNames().Contains(resourcename); 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 EmbeddedVirtualFile(virtualPath); } else { return base.GetFile(virtualPath); } } }
使其工作的最后一步是根Web.Config必须包含解析强类型MVC视图的正确设置,因为将不使用views文件夹中的那个:
要使其与Mono一起使用,还需要几个额外的步骤.首先,您需要实现GetDirectory,因为在应用程序启动时而不是根据需要加载views文件夹中的所有文件:
public override VirtualDirectory GetDirectory(string virtualDir) { Log.LogInfo("GetDirectory - " + virtualDir); var b = base.GetDirectory(virtualDir); return new EmbeddedVirtualDirectory(virtualDir, b); } public class EmbeddedVirtualDirectory : VirtualDirectory { private VirtualDirectory FileDir { get; set; } public EmbeddedVirtualDirectory(string virtualPath, VirtualDirectory filedir) : base(virtualPath) { FileDir = filedir; } public override System.Collections.IEnumerable Children { get { return FileDir.Children; } } public override System.Collections.IEnumerable Directories { get { return FileDir.Directories; } } public override System.Collections.IEnumerable Files { get { if (!VirtualPath.Contains("/Views/") || VirtualPath.EndsWith("/Views/")) { return FileDir.Files; } var fl = new List(); foreach (VirtualFile f in FileDir.Files) { fl.Add(f); } var resourcename = VirtualPath.Substring(VirtualPath.IndexOf("Views/")) .Replace("Views/", "OrangeGuava.Common.Views.") .Replace("/", "."); Assembly assembly = Assembly.GetExecutingAssembly(); var rfl = assembly.GetManifestResourceNames() .Where(s => s.StartsWith(resourcename)) .Select(s => VirtualPath + s.Replace(resourcename, "")) .Select(s => new EmbeddedVirtualFile(s)); fl.AddRange(rfl); return fl; } } }
最后,强类型视图几乎可以完美地工作.模型将被视为无类型对象,因此要获得强大的键入,您需要使用类似的方式启动共享视图
<% var Model2 = Model as IEnumerable; %>
基本上这与人们使用WebForms并尝试将其UserControl ASCX文件编译为DLL的问题相同.我发现这个http://www.codeproject.com/KB/aspnet/ASP2UserControlLibrary.aspx也可能对你有用.
protected void Application_Start() { WebFormViewEngine engine = new WebFormViewEngine(); engine.ViewLocationFormats = new[] { "~/bin/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" }; engine.PartialViewLocationFormats = engine.ViewLocationFormats; ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(engine); RegisterRoutes(RouteTable.Routes); }
将视图的"复制到输出"属性设置为"始终复制"