如何在单个ASP.NET项目中集成MVC Web应用并共享其视图文件夹
解决ASP.NET主应用共享MVC子应用视图文件夹的问题
以下是几种无需复制视图文件夹,让ASP.NET主应用直接使用MVC子应用视图的可行方案:
方案1:自定义Razor视图引擎,扩展视图搜索路径
通过自定义视图引擎,让主应用的视图搜索范围包含MVC子应用的视图目录,步骤如下:
- 在ASP.NET主应用中创建自定义视图引擎类:
public class CustomRazorViewEngine : RazorViewEngine { public CustomRazorViewEngine() { // 新增MVC子应用的视图搜索路径,替换为你的子应用名称 var subAppViewPaths = new[] { "~/../MvcSubApp/Views/{1}/{0}.cshtml", "~/../MvcSubApp/Views/Shared/{0}.cshtml", "~/../MvcSubApp/Views/{1}/{0}.vbhtml", "~/../MvcSubApp/Views/Shared/{0}.vbhtml" }; // 合并原有路径与新增路径 ViewLocationFormats = ViewLocationFormats.Union(subAppViewPaths).ToArray(); PartialViewLocationFormats = PartialViewLocationFormats.Union(subAppViewPaths).ToArray(); MasterLocationFormats = MasterLocationFormats.Union(subAppViewPaths).ToArray(); } }
- 在主应用的
Global.asax.cs的Application_Start方法中注册自定义视图引擎:
protected void Application_Start() { // 移除默认的Razor视图引擎 ViewEngines.Engines.Remove(ViewEngines.Engines.OfType<RazorViewEngine>().FirstOrDefault()); // 添加自定义视图引擎 ViewEngines.Engines.Add(new CustomRazorViewEngine()); // 其他初始化代码... }
方案2:将MVC子应用的视图打包为嵌入式资源
把MVC子应用的视图设置为嵌入式资源,然后通过自定义视图引擎读取这些资源:
在MVC子应用中,选中所有视图文件(.cshtml/.vbhtml),在属性窗口设置生成操作为
嵌入式资源。在MVC子应用的项目文件(.csproj)中添加配置,确保视图资源的命名规范:
<ItemGroup> <EmbeddedResource Include="Views\**\*.cshtml"> <LogicalName>Views.%(RecursiveDir)%(Filename)%(Extension)</LogicalName> </EmbeddedResource> </ItemGroup>
- 在ASP.NET主应用中创建嵌入式视图引擎:
public class EmbeddedViewEngine : RazorViewEngine { private readonly Assembly _subAppAssembly; public EmbeddedViewEngine(Assembly subAppAssembly) { _subAppAssembly = subAppAssembly; // 配置嵌入式视图的搜索路径模板 ViewLocationFormats = new[] { "Views/{1}/{0}.cshtml", "Views/Shared/{0}.cshtml" }; } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { var resourcePath = viewPath.TrimStart('~', '/'); return new EmbeddedRazorView(controllerContext, resourcePath, masterPath, false, FileExtensions, _subAppAssembly); } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { var resourcePath = partialPath.TrimStart('~', '/'); return new EmbeddedRazorView(controllerContext, resourcePath, null, false, FileExtensions, _subAppAssembly); } protected override bool FileExists(ControllerContext controllerContext, string virtualPath) { var resourcePath = virtualPath.TrimStart('~', '/'); return _subAppAssembly.GetManifestResourceInfo(resourcePath) != null; } } // 自定义嵌入式Razor视图实现 public class EmbeddedRazorView : RazorView { private readonly Assembly _assembly; public EmbeddedRazorView(ControllerContext controllerContext, string viewPath, string layoutPath, bool runViewStartPages, IEnumerable<string> viewStartFileExtensions, Assembly assembly) : base(controllerContext, viewPath, layoutPath, runViewStartPages, viewStartFileExtensions) { _assembly = assembly; } protected override IViewFile CreateViewFile(string virtualPath) { var resourcePath = virtualPath.TrimStart('~', '/'); var stream = _assembly.GetManifestResourceStream(resourcePath); return new EmbeddedViewFile(stream); } } public class EmbeddedViewFile : IViewFile { private readonly Stream _stream; public EmbeddedViewFile(Stream stream) { _stream = stream; } public Stream OpenRead() => _stream; }
- 在主应用的
Application_Start中注册该引擎:
protected void Application_Start() { var subAppAssembly = Assembly.Load("MvcSubApp"); // 替换为你的MVC子应用程序集名称 ViewEngines.Engines.Add(new EmbeddedViewEngine(subAppAssembly)); // 其他初始化代码... }
方案3:使用虚拟路径提供器映射子应用视图目录
通过自定义VirtualPathProvider,将MVC子应用的物理视图目录映射为主应用的虚拟路径,让主应用直接访问子应用的视图文件:
- 在主应用中创建自定义虚拟路径提供器:
public class SubAppViewPathProvider : VirtualPathProvider { private readonly string _subAppViewPhysicalPath; private readonly string _virtualPathPrefix = "~/SubAppViews/"; public SubAppViewPathProvider(string subAppViewPhysicalPath) { _subAppViewPhysicalPath = subAppViewPhysicalPath; } public override bool FileExists(string virtualPath) { if (virtualPath.StartsWith(_virtualPathPrefix, StringComparison.OrdinalIgnoreCase)) { var relativePath = virtualPath.Substring(_virtualPathPrefix.Length); var physicalPath = Path.Combine(_subAppViewPhysicalPath, relativePath); return File.Exists(physicalPath); } return base.FileExists(virtualPath); } public override VirtualFile GetFile(string virtualPath) { if (virtualPath.StartsWith(_virtualPathPrefix, StringComparison.OrdinalIgnoreCase)) { var relativePath = virtualPath.Substring(_virtualPathPrefix.Length); var physicalPath = Path.Combine(_subAppViewPhysicalPath, relativePath); return new PhysicalFile(virtualPath, physicalPath); } return base.GetFile(virtualPath); } }
- 在主应用的
Application_Start中注册路径提供器,并修改视图引擎的搜索路径:
protected void Application_Start() { // 替换为你的MVC子应用视图文件夹的物理路径 var subAppViewPath = @"D:\Projects\MvcSubApp\Views"; HostingEnvironment.RegisterVirtualPathProvider(new SubAppViewPathProvider(subAppViewPath)); // 修改视图引擎的搜索路径,添加虚拟路径前缀 var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().FirstOrDefault(); if (razorEngine != null) { var subAppPaths = new[] { "~/SubAppViews/{1}/{0}.cshtml", "~/SubAppViews/Shared/{0}.cshtml" }; razorEngine.ViewLocationFormats = razorEngine.ViewLocationFormats.Union(subAppPaths).ToArray(); } // 其他初始化代码... }
内容的提问来源于stack exchange,提问作者Amol
相关产品推荐
相关产品推荐

