diff --git a/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs new file mode 100644 index 0000000000..7c8deb9dd7 --- /dev/null +++ b/src/Umbraco.Web.Website/ViewEngines/PluginViewEngine.cs @@ -0,0 +1,48 @@ +using System.Diagnostics; +using System.Text.Encodings.Web; +using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace Umbraco.Web.Website.ViewEngines +{ + /// + /// A view engine to look into the App_Plugins folder for views for packaged controllers + /// + public class PluginViewEngine : RazorViewEngine + { + public PluginViewEngine( + IRazorPageFactoryProvider pageFactory, + IRazorPageActivator pageActivator, + HtmlEncoder htmlEncoder, + ILoggerFactory loggerFactory, + DiagnosticListener diagnosticListener) + : base(pageFactory, pageActivator, htmlEncoder, OverrideViewLocations(), loggerFactory, diagnosticListener) + { + } + + private static IOptions OverrideViewLocations() + { + return Options.Create(new RazorViewEngineOptions() + { + AreaViewLocationFormats = + { + //set all of the area view locations to the plugin folder + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), + + //will be used when we have partial view and child action macros + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"), + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml"), + //for partialsCurrent. + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), + }, + ViewLocationFormats = + { + string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), + } + }); + } + } +} diff --git a/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs new file mode 100644 index 0000000000..070c3f4e65 --- /dev/null +++ b/src/Umbraco.Web.Website/ViewEngines/ProfilingViewEngine.cs @@ -0,0 +1,45 @@ + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewEngines; +using Umbraco.Core.Logging; + +namespace Umbraco.Web.Website.ViewEngines +{ + public class ProfilingViewEngine: IViewEngine + { + internal readonly IViewEngine Inner; + private readonly IProfiler _profiler; + private readonly string _name; + + public ProfilingViewEngine(IViewEngine inner, IProfiler profiler) + { + Inner = inner; + _profiler = profiler; + _name = inner.GetType().Name; + } + + public ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage) + { + using (_profiler.Step(string.Format("{0}.FindView, {1}, {2}", _name, viewName, isMainPage))) + { + return WrapResult(Inner.FindView(context, viewName, isMainPage)); + } + } + + private static ViewEngineResult WrapResult(ViewEngineResult innerResult) + { + var profiledResult = innerResult.View is null + ? ViewEngineResult.NotFound(innerResult.ViewName, innerResult.SearchedLocations) + : ViewEngineResult.Found(innerResult.ViewName, innerResult.View); + return profiledResult; + } + + public ViewEngineResult GetView(string executingFilePath, string viewPath, bool isMainPage) + { + using (_profiler.Step(string.Format("{0}.GetView, {1}, {2}, {3}", _name, executingFilePath, viewPath, isMainPage))) + { + return Inner.GetView(executingFilePath, viewPath, isMainPage); + } + } + } +} diff --git a/src/Umbraco.Web/Mvc/RenderViewEngine.cs b/src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs similarity index 79% rename from src/Umbraco.Web/Mvc/RenderViewEngine.cs rename to src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs index 5f508e8d61..2c81687091 100644 --- a/src/Umbraco.Web/Mvc/RenderViewEngine.cs +++ b/src/Umbraco.Web.Website/ViewEngines/RenderViewEngine.cs @@ -2,13 +2,13 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Web.Mvc; -using Umbraco.Core.Composing; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.AspNetCore.Mvc.ViewEngines; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Web.Models; -namespace Umbraco.Web.Mvc +namespace Umbraco.Web.Website.ViewEngines { /// /// A view engine to look into the template location specified in the config for the front-end/Rendering part of the cms, @@ -24,24 +24,24 @@ namespace Umbraco.Web.Mvc // http://issues.umbraco.org/issue/U4-1287, http://issues.umbraco.org/issue/U4-1215 private readonly IEnumerable _supplementedPartialViewLocations = new[] { "/Partials/{0}.cshtml", "/MacroPartials/{0}.cshtml", "/{0}.cshtml" }; - /// - /// Constructor - /// - public RenderViewEngine(IHostingEnvironment hostingEnvironment) - { - _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); - - const string templateFolder = Constants.ViewLocation; - - // the Render view engine doesn't support Area's so make those blank - ViewLocationFormats = _supplementedViewLocations.Select(x => templateFolder + x).ToArray(); - PartialViewLocationFormats = _supplementedPartialViewLocations.Select(x => templateFolder + x).ToArray(); - - AreaPartialViewLocationFormats = Array.Empty(); - AreaViewLocationFormats = Array.Empty(); - - EnsureFoldersAndFiles(); - } + // /// + // /// Constructor + // /// + // public RenderViewEngine(IHostingEnvironment hostingEnvironment) + // { + // _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); + // + // const string templateFolder = Constants.ViewLocation; + // + // // the Render view engine doesn't support Area's so make those blank + // ViewLocationFormats = _supplementedViewLocations.Select(x => templateFolder + x).ToArray(); + // PartialViewLocationFormats = _supplementedPartialViewLocations.Select(x => templateFolder + x).ToArray(); + // + // AreaPartialViewLocationFormats = Array.Empty(); + // AreaViewLocationFormats = Array.Empty(); + // + // EnsureFoldersAndFiles(); + // } /// /// Ensures that the correct web.config for razor exists in the /Views folder, the partials folder exist and the ViewStartPage exists. diff --git a/src/Umbraco.Web/Mvc/PluginViewEngine.cs b/src/Umbraco.Web/Mvc/PluginViewEngine.cs deleted file mode 100644 index aa81cb9a57..0000000000 --- a/src/Umbraco.Web/Mvc/PluginViewEngine.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.IO; -using System.Linq; -using System.Web.Mvc; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - /// - /// A view engine to look into the App_Plugins folder for views for packaged controllers - /// - public class PluginViewEngine : RazorViewEngine - { - - /// - /// Constructor - /// - public PluginViewEngine() - { - SetViewLocations(); - } - - private void SetViewLocations() - { - //these are the originals: - - //base.AreaViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/{1}/{0}.vbhtml", "~/Areas/{2}/Views/Shared/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.vbhtml" }; - //base.AreaMasterLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/{1}/{0}.vbhtml", "~/Areas/{2}/Views/Shared/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.vbhtml" }; - //base.AreaPartialViewLocationFormats = new string[] { "~/Areas/{2}/Views/{1}/{0}.cshtml", "~/Areas/{2}/Views/{1}/{0}.vbhtml", "~/Areas/{2}/Views/Shared/{0}.cshtml", "~/Areas/{2}/Views/Shared/{0}.vbhtml" }; - //base.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/{1}/{0}.vbhtml", "~/Views/Shared/{0}.cshtml", "~/Views/Shared/{0}.vbhtml" }; - //base.MasterLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/{1}/{0}.vbhtml", "~/Views/Shared/{0}.cshtml", "~/Views/Shared/{0}.vbhtml" }; - //base.PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.cshtml", "~/Views/{1}/{0}.vbhtml", "~/Views/Shared/{0}.cshtml", "~/Views/Shared/{0}.vbhtml" }; - //base.FileExtensions = new string[] { "cshtml", "vbhtml" }; - - var viewLocationsArray = new[] - { - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), - }; - - //set all of the area view locations to the plugin folder - AreaViewLocationFormats = viewLocationsArray - .Concat(new[] - { - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), - }) - .ToArray(); - - AreaMasterLocationFormats = viewLocationsArray; - - AreaPartialViewLocationFormats = new[] - { - //will be used when we have partial view and child action macros - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Partials/{0}.cshtml"), - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/MacroPartials/{0}.cshtml"), - //for partialsCurrent. - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/{1}/{0}.cshtml"), - string.Concat(Core.Constants.SystemDirectories.AppPlugins, "/{2}/Views/Shared/{0}.cshtml"), - }; - - } - - /// - /// Ensures that the correct web.config for razor exists in the /Views folder. - /// - private void EnsureFolderAndWebConfig(ViewEngineResult result) - { - if (result.View == null) return; - var razorResult = result.View as RazorView; - if (razorResult == null) return; - - var folder = Path.GetDirectoryName(Current.IOHelper.MapPath(razorResult.ViewPath)); - //now we need to get the /View/ folder - var viewFolder = folder.Substring(0, folder.LastIndexOf("\\Views\\")) + "\\Views"; - - //ensure the web.config file is in the ~/Views folder - Directory.CreateDirectory(viewFolder); - if (!File.Exists(Path.Combine(viewFolder, "web.config"))) - { - using (var writer = File.CreateText(Path.Combine(viewFolder, "web.config"))) - { - writer.Write(Strings.WebConfigTemplate); - } - } - } - - public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) - { - var result = base.FindView(controllerContext, viewName, masterName, useCache); - EnsureFolderAndWebConfig(result); - return result; - } - - public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) - { - var result = base.FindPartialView(controllerContext, partialViewName, useCache); - EnsureFolderAndWebConfig(result); - return result; - } - } -} diff --git a/src/Umbraco.Web/Mvc/ProfilingViewEngine.cs b/src/Umbraco.Web/Mvc/ProfilingViewEngine.cs deleted file mode 100644 index 097434541c..0000000000 --- a/src/Umbraco.Web/Mvc/ProfilingViewEngine.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Web.Mvc; -using Umbraco.Web.Composing; - -namespace Umbraco.Web.Mvc -{ - public class ProfilingViewEngine: IViewEngine - { - internal readonly IViewEngine Inner; - private readonly string _name; - - public ProfilingViewEngine(IViewEngine inner) - { - Inner = inner; - _name = inner.GetType().Name; - } - - public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) - { - using (Current.Profiler.Step(string.Format("{0}.FindPartialView, {1}, {2}", _name, partialViewName, useCache))) - { - return WrapResult(Inner.FindPartialView(controllerContext, partialViewName, useCache)); - } - } - - public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) - { - using (Current.Profiler.Step(string.Format("{0}.FindView, {1}, {2}, {3}", _name, viewName, masterName, useCache))) - { - return WrapResult(Inner.FindView(controllerContext, viewName, masterName, useCache)); - } - } - - private static ViewEngineResult WrapResult(ViewEngineResult innerResult) - { - var profiledResult = innerResult.View != null ? - new ViewEngineResult(new ProfilingView(innerResult.View), innerResult.ViewEngine) : - new ViewEngineResult(innerResult.SearchedLocations); - return profiledResult; - } - - public void ReleaseView(ControllerContext controllerContext, IView view) - { - using (Current.Profiler.Step(string.Format("{0}.ReleaseView, {1}", _name, view.GetType().Name))) - { - Inner.ReleaseView(controllerContext, view); - } - } - } -} diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index d02ccdd01e..10623a1ed8 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -78,7 +78,7 @@ namespace Umbraco.Web.Runtime viewEngines.Clear(); foreach (var engine in originalEngines) { - var wrappedEngine = engine is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine); + var wrappedEngine = engine;// TODO introduce in NETCORE: is ProfilingViewEngine ? engine : new ProfilingViewEngine(engine); viewEngines.Add(wrappedEngine); } } @@ -95,7 +95,7 @@ namespace Umbraco.Web.Runtime // set the render & plugin view engines ViewEngines.Engines.Add(new RenderViewEngine(_hostingEnvironment)); ViewEngines.Engines.Add(new PluginViewEngine()); - + ////add the profiling action filter //GlobalFilters.Filters.Add(new ProfilingActionFilter()); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index a881e3f704..0d23f8d83b 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -230,7 +230,6 @@ - @@ -295,7 +294,6 @@ - @@ -316,7 +314,6 @@ -