如何将外部项目中的控制器和视图包含到MVC6中?
我有一些模块,有控制器和视图。 它基本上是我的Web应用程序的扩展。 每个模块都在一个类库中。
我想从我的Web应用程序加载这些程序集。 但我在这里没有运气。
我的解决方案文件结构如下:
src | |-- Web.Common (Class Library Project) | |- Files like: filters, my own controller etc... | |-- WebApplication (ASP.NET5 WebSite) | |- wwwroot | |- Controllers | |- Views | |- etc... | |-- Module 1 (Class Library Project) | |- Controllers | |- Views | |-- Module 2 etc...
这些是我试过的:
我试图实现自己的IViewLocationExpander
public class CustomViewLocationExpander : IViewLocationExpander { public IEnumerable ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) { yield return "/../Module1.Web/Views/Home/TestView.cshtml"; yield return "../Module1.Web/Views/Home/TestView.cshtml"; yield return "/Module1.Web/Views/Home/TestView.cshtml"; yield return "~/../Module1.Web/Views/Home/TestView.cshtml"; } public void PopulateValues(ViewLocationExpanderContext context) { } }
我尝试了各种各样的路径,但我没有运气:(
我明白了:
InvalidOperationException:找不到视图’TestView’。 搜索了以下位置:
〜/ Module1.Web / Views / Home / TestView.cshtml~ /../ Module1.Web / Views / Home / TestView.cshtml /Module1.Web/Views/Home/TestView.cshtml /../Module1.Web/Views /Home/TestView.cshtml
所以我想也许默认的IFileProvider看起来不在WebApp的根路径之外,并决定尝试实现我自己的IFileProvider。
但在这里我也没有任何成功。
也许有一个function是通过调用一些ASP.NET方法来实现这一点,但我不知道。
有什么建议?
控制器将自动加载。 要加载视图,您将需要EmbeddedFileProvider
和CompositeFileProvider
,这两者都是新的,因此您需要从aspnetvnext
提要中获取它们。
在你的启动MVC6项目的project.json
引用它们:
"Microsoft.AspNet.FileProviders.Composite": "1.0.0-*", "Microsoft.AspNet.FileProviders.Embedded": "1.0.0-*",
在Startup.cs
更新服务注册:
services.Configure(options => { options.FileProvider = new CompositeFileProvider( new EmbeddedFileProvider( typeof(BooksController).GetTypeInfo().Assembly, "BookStore.Portal" // your external assembly's base namespace ), options.FileProvider ); });
在外部程序集的project.json
中,添加以下内容:
"resource": "Views/**"
这是一个示例实现,您可以克隆并运行以查看它的实际运行情况: https : //github.com/johnnyoshika/mvc6-view-components
我认为除非您想使用某些非标准的第三方解决方案,否则视图必须存在于主Web应用程序中
我的理解是,在beta7中,我们将能够将视图和其他内容文件打包到我们使用VS 2015构建类库时创建的类库nuget中。但我的理解是,当主Web应用程序添加依赖于此类一个nuget,内容文件将被添加到主Web应用程序,即我的视图将添加到Views / MyModule或类似的东西下面,以便它们可以从主Web应用程序中使用。
至少这是我期望采取的方法,以便其他人可以稍后阅读和/或修改我的观点。
我认为另一种选择是预先编译视图,使得它们不像磁盘上的.cshtml文件一样存在,但这会使其他人更难以自定义视图。
我通过使用IViewLocationExpander
和PhysicalFileProvider
实现了这一点
我使用剃刀引擎的IFileProvider
来设置src文件夹的根路径。 通过附加程序集名称,我获得项目根路径的路径。
public class MultiAssemblyViewLocationExpander : IViewLocationExpander { public IEnumerable ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) { var actionContext = (ResultExecutingContext)context.ActionContext; var assembly = actionContext.Controller.GetType().Assembly; var assemblyName = assembly.GetName().Name; foreach (var viewLocation in viewLocations) yield return "/" + assemblyName + viewLocation; } public void PopulateValues(ViewLocationExpanderContext context) { } }
在ConfigureServices
方法中:
services.Configure(options => { options.FileProvider = new PhysicalFileProvider(HostingEnvironment.WebRootPath + "..\\..\\"); options.ViewLocationExpanders.Add(new MultiAssemblyViewLocationExpander ()); });
PS:我没有在已发布的应用程序上测试它。 但是如果出现一些路径问题,很容易解决它;)