Removing the WebForms view engine

--HG--
branch : 1.x
This commit is contained in:
Sebastien Ros
2013-05-20 18:07:31 -07:00
parent cbaa5b6d0e
commit 784d6d85dc
9 changed files with 4 additions and 400 deletions

View File

@@ -27,7 +27,6 @@ using Orchard.Mvc.Routes;
using Orchard.Mvc.ViewEngines;
using Orchard.Mvc.ViewEngines.Razor;
using Orchard.Mvc.ViewEngines.ThemeAwareness;
using Orchard.Mvc.ViewEngines.WebForms;
using Orchard.Recipes.Services;
using Orchard.Settings;
using Orchard.Tasks;
@@ -53,7 +52,6 @@ namespace Orchard.Setup {
builder.RegisterType<RoutePublisher>().As<IRoutePublisher>().InstancePerLifetimeScope();
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().As<IShapeTemplateViewEngine>().SingleInstance();
builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().As<IShapeTemplateViewEngine>().SingleInstance();
builder.RegisterType<ThemedViewResultFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();

View File

@@ -51,7 +51,6 @@ namespace Orchard.Environment {
builder.RegisterType<DefaultHostEnvironment>().As<IHostEnvironment>().SingleInstance();
builder.RegisterType<DefaultHostLocalRestart>().As<IHostLocalRestart>().Named<IEventHandler>(typeof(IShellSettingsManagerEventHandler).Name).SingleInstance();
builder.RegisterType<DefaultBuildManager>().As<IBuildManager>().SingleInstance();
builder.RegisterType<WebFormVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
builder.RegisterType<DynamicModuleVirtualPathProvider>().As<ICustomVirtualPathProvider>().SingleInstance();
builder.RegisterType<AppDataFolderRoot>().As<IAppDataFolderRoot>().SingleInstance();
builder.RegisterType<DefaultExtensionCompiler>().As<IExtensionCompiler>().SingleInstance();

View File

@@ -89,7 +89,7 @@ namespace Orchard.Environment {
// Leave these at end (as a best effort)
"~/Core", "~/Modules", "~/Themes"
},
FileExtensionsToCompile = new[] { ".cshtml", ".acsx", ".aspx" },
FileExtensionsToCompile = new[] { ".cshtml" },
ProcessedDirectories = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
};

View File

@@ -1,52 +0,0 @@
using System.IO;
using System.Web.Hosting;
namespace Orchard.FileSystems.Dependencies {
public class WebFormVirtualFile : VirtualFile {
private readonly VirtualFile _actualFile;
private readonly string _assemblyDirective;
public WebFormVirtualFile(string virtualPath, VirtualFile actualFile, string assemblyDirective)
: base(virtualPath) {
_actualFile = actualFile;
_assemblyDirective = assemblyDirective;
}
public override string Name {
get {
return _actualFile.Name;
}
}
public override bool IsDirectory {
get {
return _actualFile.IsDirectory;
}
}
public override Stream Open() {
using (var actualStream = _actualFile.Open()) {
var reader = new StreamReader(actualStream);
var memoryStream = new MemoryStream();
int length;
using (var writer = new StreamWriter(memoryStream)) {
bool assemblyDirectiveAdded = false;
for (var line = reader.ReadLine(); line != null; line = reader.ReadLine()) {
if (!string.IsNullOrWhiteSpace(line) && !assemblyDirectiveAdded) {
line += _assemblyDirective;
assemblyDirectiveAdded = true;
}
writer.WriteLine(line);
}
writer.Flush();
length = (int) memoryStream.Length;
}
return new MemoryStream(memoryStream.GetBuffer(), 0, length);
}
}
}
}

View File

@@ -1,226 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Hosting;
using Orchard.Environment.Extensions.Loaders;
using Orchard.FileSystems.VirtualPath;
using Orchard.Logging;
namespace Orchard.FileSystems.Dependencies {
/// <summary>
/// The purpose of this class is to insert assembly directives in WebForms views served
/// from ~/Modules and ~/Themes. Inserting these directives ensures that the WebForms
/// build provider will add proper assembly references when calling the compiler.
/// For example, if Module A depends on Module Bar and some other 3rd party DLL "Foo.dll",
/// we will insert the following assembly directives to the view file when server:
/// &lt;%@ Assembly Src="~/Modules/Bar/Bar.csproj"%&gt;
/// &lt;%@ Assembly Name="Foo"%&gt;
/// </summary>
public class WebFormVirtualPathProvider : VirtualPathProvider, ICustomVirtualPathProvider {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IExtensionDependenciesManager _extensionDependenciesManager;
private readonly IEnumerable<IExtensionLoader> _loaders;
private readonly string[] _modulesPrefixes = { "~/Modules/" };
private readonly string[] _themesPrefixes = { "~/Themes/" };
private readonly string[] _extensions = { ".ascx", ".aspx", ".master" };
public WebFormVirtualPathProvider(IDependenciesFolder dependenciesFolder, IExtensionDependenciesManager extensionDependenciesManager, IEnumerable<IExtensionLoader> loaders) {
_dependenciesFolder = dependenciesFolder;
_extensionDependenciesManager = extensionDependenciesManager;
_loaders = loaders;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public override bool DirectoryExists(string virtualDir) {
return Previous.DirectoryExists(virtualDir);
}
public override bool FileExists(string virtualPath) {
return Previous.FileExists(virtualPath);
}
public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) {
var result = GetFileHashWorker(virtualPath, virtualPathDependencies);
Logger.Debug("GetFileHash(\"{0}\"): {1}", virtualPath, result);
return result;
}
private string GetFileHashWorker(string virtualPath, IEnumerable virtualPathDependencies) {
// We override the "GetFileHash()" behavior to take into account the dependencies folder
// state. This ensures that if any dependency changes, ASP.NET will recompile views that
// have been customized to include custom assembly directives.
var file = GetModuleVirtualOverride(virtualPath) ?? GetThemeVirtualOverride(virtualPath);
if (file == null) {
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
var dependencies =
virtualPathDependencies
.OfType<string>()
.Concat(file.Loaders.SelectMany(dl => _extensionDependenciesManager.GetVirtualPathDependencies(dl.Descriptor.Name)))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
if (Logger.IsEnabled(LogLevel.Debug)) {
Logger.Debug("GetFileHash(\"{0}\") - virtual path dependencies:", virtualPath);
foreach (var dependency in dependencies) {
Logger.Debug(" Dependency: \"{0}\"", dependency);
}
}
return base.GetFileHash(virtualPath, dependencies);
}
public override VirtualFile GetFile(string virtualPath) {
//Logger.Debug("GetFile(\"{0}\")", virtualPath);
var actualFile = Previous.GetFile(virtualPath);
return GetModuleCustomVirtualFile(virtualPath, actualFile) ??
GetThemeCustomVirtualFile(virtualPath, actualFile) ??
actualFile;
}
private VirtualFile GetModuleCustomVirtualFile(string virtualPath, VirtualFile actualFile) {
var file = GetModuleVirtualOverride(virtualPath);
if (file == null)
return null;
if (Logger.IsEnabled(LogLevel.Debug)) {
Logger.Debug("Virtual file from module \"{0}\" served with specific assembly directive:", file.ModuleName);
Logger.Debug(" Virtual path: {0}", virtualPath);
Logger.Debug(" Assembly directive: {0}", file.Directive);
}
return new WebFormVirtualFile(virtualPath, actualFile, file.Directive);
}
private VirtualFile GetThemeCustomVirtualFile(string virtualPath, VirtualFile actualFile) {
var file = GetThemeVirtualOverride(virtualPath);
if (file == null)
return null;
if (Logger.IsEnabled(LogLevel.Debug)) {
Logger.Debug("Virtual file from theme served with specific assembly directive:");
Logger.Debug(" Virtual path: {0}", virtualPath);
Logger.Debug(" Assembly directive: {0}", file.Directive);
}
return new WebFormVirtualFile(virtualPath, actualFile, file.Directive);
}
private VirtualFileOverride GetModuleVirtualOverride(string virtualPath) {
var appRelativePath = VirtualPathUtility.ToAppRelative(virtualPath);
var prefix = PrefixMatch(appRelativePath, _modulesPrefixes);
if (prefix == null)
return null;
var extension = ExtensionMatch(appRelativePath, _extensions);
if (extension == null)
return null;
var moduleName = ModuleMatch(appRelativePath, prefix);
if (moduleName == null)
return null;
var dependencyDescriptor = _dependenciesFolder.GetDescriptor(moduleName);
if (dependencyDescriptor == null)
return null;
var loader = _loaders.Where(l => l.Name == dependencyDescriptor.LoaderName).FirstOrDefault();
if (loader == null)
return null;
var references = loader.GetCompilationReferences(dependencyDescriptor).ToList();
if (!references.Any())
return null;
return new VirtualFileOverride {
ModuleName = moduleName,
Directive = CreateAssemblyDirectivesString(references),
Loaders = new[] { new DependencyLoader { Loader = loader, Descriptor = dependencyDescriptor } }
};
}
private VirtualFileOverride GetThemeVirtualOverride(string virtualPath) {
var appRelativePath = VirtualPathUtility.ToAppRelative(virtualPath);
var prefix = PrefixMatch(appRelativePath, _themesPrefixes);
if (prefix == null)
return null;
var extension = ExtensionMatch(appRelativePath, _extensions);
if (extension == null)
return null;
var dependencyLoaders = _loaders
.SelectMany(loader => _dependenciesFolder
.LoadDescriptors()
.Where(d => d.LoaderName == loader.Name),
(loader, desr) => new DependencyLoader { Loader = loader, Descriptor = desr })
.ToList();
var references = dependencyLoaders
.SelectMany(dl => dl.Loader.GetCompilationReferences(dl.Descriptor))
.ToList();
if (!references.Any())
return null;
return new VirtualFileOverride {
ModuleName = "",
Directive = CreateAssemblyDirectivesString(references),
Loaders = dependencyLoaders
};
}
private string CreateAssemblyDirectivesString(IEnumerable<ExtensionCompilationReference> references) {
var sb = new StringBuilder();
foreach (var reference in references) {
if (!string.IsNullOrEmpty(reference.AssemblyName)) {
sb.AppendFormat("<%@ Assembly Name=\"{0}\"%>", reference.AssemblyName);
}
if (!string.IsNullOrEmpty(reference.BuildProviderTarget)) {
sb.AppendFormat("<%@ Assembly Src=\"{0}\"%>", reference.BuildProviderTarget);
}
}
return sb.ToString();
}
private static string ModuleMatch(string virtualPath, string prefix) {
var index = virtualPath.IndexOf('/', prefix.Length, virtualPath.Length - prefix.Length);
if (index < 0)
return null;
var moduleName = virtualPath.Substring(prefix.Length, index - prefix.Length);
return (string.IsNullOrEmpty(moduleName) ? null : moduleName);
}
private static string ExtensionMatch(string virtualPath, params string[] extensions) {
return extensions
.FirstOrDefault(e => virtualPath.EndsWith(e, StringComparison.OrdinalIgnoreCase));
}
private static string PrefixMatch(string virtualPath, params string[] prefixes) {
return prefixes
.FirstOrDefault(p => virtualPath.StartsWith(p, StringComparison.OrdinalIgnoreCase));
}
VirtualPathProvider ICustomVirtualPathProvider.Instance {
get { return this; }
}
private class VirtualFileOverride {
public string ModuleName { get; set; }
public string Directive { get; set; }
public IEnumerable<DependencyLoader> Loaders { get; set; }
}
private class DependencyLoader {
public IExtensionLoader Loader { get; set; }
public DependencyDescriptor Descriptor { get; set; }
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Web.Mvc;
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
using Orchard.Logging;
using Orchard.Mvc.ViewEngines.WebForms;
using Orchard.Mvc.ViewEngines.ThemeAwareness;
namespace Orchard.Mvc.ViewEngines.Razor {
public class RazorViewEngineProvider : IViewEngineProvider, IShapeTemplateViewEngine {

View File

@@ -4,7 +4,7 @@ using System.Web.Caching;
using System.Web;
using System.Web.Hosting;
namespace Orchard.Mvc.ViewEngines.WebForms {
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public class ThemeViewLocationCache : IViewLocationCache {
private readonly string _requestTheme;

View File

@@ -1,112 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy;
using Orchard.Logging;
namespace Orchard.Mvc.ViewEngines.WebForms {
public class WebFormViewEngineProvider : IViewEngineProvider, IShapeTemplateViewEngine {
public WebFormViewEngineProvider() {
Logger = NullLogger.Instance;
}
static readonly string[] DisabledFormats = new[] { "~/Disabled" };
public ILogger Logger { get; set; }
public IViewEngine CreateThemeViewEngine(CreateThemeViewEngineParams parameters) {
// Area: if "area" in RouteData. Url hit for module...
// Area-Layout Paths - no-op because LayoutViewEngine uses multi-pass instead of layout paths
// Area-View Paths - no-op because LayoutViewEngine relies entirely on Partial view resolution
// Area-Partial Paths - enable theming views associated with a module based on the route
// Layout Paths - no-op because LayoutViewEngine uses multi-pass instead of layout paths
// View Paths - no-op because LayoutViewEngine relies entirely on Partial view resolution
// Partial Paths -
// {area}/{controller}/
// for "routed" request views...
// enable /Views/{area}/{controller}/{viewName}
// enable /Views/{partialName}
// enable /Views/"DisplayTemplates/"+{templateName}
// enable /Views/"EditorTemplates/+{templateName}
var partialViewLocationFormats = new[] {
parameters.VirtualPath + "/Views/{0}.ascx",
parameters.VirtualPath + "/Views/{0}.aspx",
};
//Logger.Debug("PartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", partialViewLocationFormats));
var areaPartialViewLocationFormats = new[] {
parameters.VirtualPath + "/Views/{2}/{1}/{0}.ascx",
parameters.VirtualPath + "/Views/{2}/{1}/{0}.aspx",
};
//Logger.Debug("AreaPartialViewLocationFormats (theme): \r\n\t-{0}", string.Join("\r\n\t-", areaPartialViewLocationFormats));
var viewEngine = new WebFormViewEngine {
MasterLocationFormats = DisabledFormats,
ViewLocationFormats = DisabledFormats,
PartialViewLocationFormats = partialViewLocationFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = DisabledFormats,
AreaPartialViewLocationFormats = areaPartialViewLocationFormats,
ViewLocationCache = new ThemeViewLocationCache(parameters.VirtualPath),
};
return viewEngine;
}
public IViewEngine CreateModulesViewEngine(CreateModulesViewEngineParams parameters) {
var areaFormats = new[] {
"~/Core/{2}/Views/{1}/{0}.ascx",
"~/Core/{2}/Views/{1}/{0}.aspx",
"~/Modules/{2}/Views/{1}/{0}.ascx",
"~/Modules/{2}/Views/{1}/{0}.aspx",
"~/Themes/{2}/Views/{1}/{0}.ascx",
"~/Themes/{2}/Views/{1}/{0}.aspx",
};
//Logger.Debug("AreaFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", areaFormats));
var universalFormats = parameters.VirtualPaths
.SelectMany(x => new[] {
x + "/Views/{0}.ascx",
x + "/Views/{0}.aspx",
})
.ToArray();
//Logger.Debug("UniversalFormats (module): \r\n\t-{0}", string.Join("\r\n\t-", universalFormats));
var viewEngine = new WebFormViewEngine {
MasterLocationFormats = DisabledFormats,
ViewLocationFormats = universalFormats,
PartialViewLocationFormats = universalFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = areaFormats,
AreaPartialViewLocationFormats = areaFormats,
};
return viewEngine;
}
public IViewEngine CreateBareViewEngine() {
return new WebFormViewEngine {
MasterLocationFormats = DisabledFormats,
ViewLocationFormats = DisabledFormats,
PartialViewLocationFormats = DisabledFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = DisabledFormats,
AreaPartialViewLocationFormats = DisabledFormats,
};
}
public IEnumerable<string> DetectTemplateFileNames(IEnumerable<string> fileNames) {
return fileNames.Where(fileName => fileName.EndsWith(".aspx", StringComparison.OrdinalIgnoreCase) ||
fileName.EndsWith(".ascx", StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@@ -268,6 +268,7 @@
<Compile Include="Mvc\ShapeResult.cs" />
<Compile Include="Mvc\Spooling\HtmlStringWriter.cs" />
<Compile Include="Mvc\ViewEngines\Razor\IRazorCompilationEvents.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeViewLocationCache.cs" />
<Compile Include="OrchardFatalException.cs" />
<Compile Include="Recipes\Events\IRecipeExecuteEventHandler.cs" />
<Compile Include="Recipes\Events\IRecipeSchedulerEventHandler.cs" />
@@ -670,8 +671,6 @@
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathMonitor.cs" />
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathProvider.cs" />
<Compile Include="FileSystems\VirtualPath\ICustomVirtualPathProvider.cs" />
<Compile Include="FileSystems\Dependencies\WebFormsExtensionsVirtualPathProvider.cs" />
<Compile Include="FileSystems\Dependencies\WebFormsExtensionsVirtualFile.cs" />
<Compile Include="Environment\IHostEnvironment.cs" />
<Compile Include="FileSystems\VirtualPath\IVirtualPathMonitor.cs" />
<Compile Include="FileSystems\Dependencies\IDependenciesFolder.cs" />
@@ -797,7 +796,6 @@
<Compile Include="Mvc\Routes\UrlPrefix.cs" />
<Compile Include="Mvc\Routes\UrlPrefixAdjustedHttpContext.cs" />
<Compile Include="Mvc\Routes\ShellRoute.cs" />
<Compile Include="Mvc\ViewEngines\WebForms\ThemeViewLocationCache.cs" />
<Compile Include="Mvc\ViewUserControl.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>
@@ -870,7 +868,6 @@
<Compile Include="Mvc\ViewEngines\IViewEngineProvider.cs" />
<Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemedViewResultFilter.cs" />
<Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineProvider.cs" />
<Compile Include="UI\Admin\AdminThemeSelector.cs" />
<Compile Include="UI\Navigation\INavigationManager.cs" />
<Compile Include="UI\Navigation\NavigationItemBuilder.cs" />