mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Fixing Razor templates invalidation
This commit is contained in:
@@ -15,14 +15,15 @@ using Orchard.Utility.Extensions;
|
||||
namespace Orchard.Templates.Drivers {
|
||||
public class ShapePartDriver : ContentPartDriver<ShapePart> {
|
||||
private readonly IEnumerable<ITemplateProcessor> _processors;
|
||||
private readonly IRazorTemplateCache _cache;
|
||||
private readonly ITemplateService _service;
|
||||
private readonly IRazorTemplateHolder _templateHolder;
|
||||
private readonly ITransactionManager _transactions;
|
||||
|
||||
public ShapePartDriver(IEnumerable<ITemplateProcessor> processors, IRazorTemplateCache cache, ITemplateService service,ITransactionManager transactions) {
|
||||
public ShapePartDriver(
|
||||
IEnumerable<ITemplateProcessor> processors,
|
||||
IRazorTemplateHolder templateHolder,
|
||||
ITransactionManager transactions) {
|
||||
_processors = processors;
|
||||
_cache = cache;
|
||||
_service = service;
|
||||
_templateHolder = templateHolder;
|
||||
_transactions = transactions;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
@@ -51,7 +52,7 @@ namespace Orchard.Templates.Drivers {
|
||||
try {
|
||||
var processor = _processors.FirstOrDefault(x => String.Equals(x.Type, part.Language, StringComparison.OrdinalIgnoreCase));
|
||||
processor.Verify(part.Template);
|
||||
_cache.Set(part.Name, part.Template);
|
||||
_templateHolder.Set(part.Name, part.Template);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
updater.AddModelError("", T("Template processing error: {0}", ex.Message));
|
||||
|
@@ -1,16 +1,20 @@
|
||||
using Orchard.Caching;
|
||||
using Orchard.Compilation.Razor;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data;
|
||||
using Orchard.Templates.Models;
|
||||
using Orchard.Templates.Services;
|
||||
|
||||
namespace Orchard.Templates.Handlers {
|
||||
public class ShapePartHandler : ContentHandler {
|
||||
public ShapePartHandler(IRepository<ShapePartRecord> repository, ISignals signals) {
|
||||
private readonly IRazorTemplateHolder _razorTemplateHolder;
|
||||
|
||||
public ShapePartHandler(
|
||||
IRepository<ShapePartRecord> repository,
|
||||
IRazorTemplateHolder razorTemplateHolder) {
|
||||
_razorTemplateHolder = razorTemplateHolder;
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
OnGetContentItemMetadata<ShapePart>((ctx, part) => ctx.Metadata.DisplayText = part.Name);
|
||||
OnCreated<ShapePart>((ctx, part) => signals.Trigger(DefaultTemplateService.TemplatesSignal));
|
||||
OnUpdated<ShapePart>((ctx, part) => _razorTemplateHolder.Set(part.Name, part.Template));
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,8 +12,6 @@ using Orchard.Templates.Models;
|
||||
namespace Orchard.Templates.Services {
|
||||
public class DefaultTemplateService : ITemplateService {
|
||||
|
||||
public const string TemplatesSignal = "Orchard.Templates";
|
||||
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly IDisplayHelperFactory _displayHelperFactory;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
|
@@ -16,7 +16,6 @@ using Orchard.Themes.Models;
|
||||
namespace Orchard.Templates.Services {
|
||||
public class RazorTemplateProcessor : TemplateProcessorImpl {
|
||||
private readonly IRazorCompiler _compiler;
|
||||
private readonly IRazorTemplateCache _cache;
|
||||
private readonly ISiteService _siteService;
|
||||
private readonly IHttpContextAccessor _hca;
|
||||
|
||||
@@ -24,9 +23,8 @@ namespace Orchard.Templates.Services {
|
||||
get { return "Razor"; }
|
||||
}
|
||||
|
||||
public RazorTemplateProcessor(IRazorCompiler compiler, IRazorTemplateCache cache, ISiteService siteService, IHttpContextAccessor hca) {
|
||||
public RazorTemplateProcessor(IRazorCompiler compiler, ISiteService siteService, IHttpContextAccessor hca) {
|
||||
_compiler = compiler;
|
||||
_cache = cache;
|
||||
_siteService = siteService;
|
||||
_hca = hca;
|
||||
Logger = NullLogger.Instance;
|
||||
|
@@ -15,13 +15,13 @@ using Orchard.Themes.Models;
|
||||
namespace Orchard.Templates.Services {
|
||||
public class TemplateBindingStrategy : IShapeTableProvider {
|
||||
private readonly IWorkContextAccessor _wca;
|
||||
private readonly ICacheManager _cache;
|
||||
private readonly ISignals _signals;
|
||||
private readonly IRazorTemplateHolder _templateProvider;
|
||||
|
||||
public TemplateBindingStrategy(IWorkContextAccessor wca, ICacheManager cache, ISignals signals) {
|
||||
public TemplateBindingStrategy(
|
||||
IWorkContextAccessor wca,
|
||||
IRazorTemplateHolder templateProvider) {
|
||||
_wca = wca;
|
||||
_cache = cache;
|
||||
_signals = signals;
|
||||
_templateProvider = templateProvider;
|
||||
}
|
||||
|
||||
public void Discover(ShapeTableBuilder builder) {
|
||||
@@ -31,7 +31,6 @@ namespace Orchard.Templates.Services {
|
||||
private void BuildShapes(ShapeTableBuilder builder) {
|
||||
|
||||
var templateService = _wca.GetContext().Resolve<ITemplateService>();
|
||||
var templateCache = _wca.GetContext().Resolve<IRazorTemplateCache>();
|
||||
var siteService = _wca.GetContext().Resolve<ISiteService>();
|
||||
var extensionManager = _wca.GetContext().Resolve<IExtensionManager>();
|
||||
|
||||
@@ -49,28 +48,23 @@ namespace Orchard.Templates.Services {
|
||||
Priority = int.MaxValue
|
||||
};
|
||||
|
||||
var shapes = _cache.Get(
|
||||
DefaultTemplateService.TemplatesSignal,
|
||||
ctx => {
|
||||
ctx.Monitor(_signals.When(DefaultTemplateService.TemplatesSignal));
|
||||
return templateService
|
||||
.GetTemplates()
|
||||
.Select(r => new {
|
||||
r.Name,
|
||||
r.Language,
|
||||
r.Template })
|
||||
.ToList();
|
||||
});
|
||||
var shapes = templateService.GetTemplates().Select(r =>
|
||||
new {
|
||||
r.Name,
|
||||
r.Language,
|
||||
r.Template
|
||||
})
|
||||
.ToList();
|
||||
|
||||
foreach (var record in shapes) {
|
||||
templateCache.Set(record.Name, record.Template);
|
||||
_templateProvider.Set(record.Name, record.Template);
|
||||
var shapeType = AdjustName(record.Name);
|
||||
|
||||
builder.Describe(shapeType)
|
||||
.From(new Feature { Descriptor = hackedDescriptor })
|
||||
.BoundAs("Template::" + shapeType,
|
||||
descriptor => context => {
|
||||
var template = templateCache.Get(record.Name);
|
||||
var template = _templateProvider.Get(record.Name);
|
||||
return template != null ? PerformInvoke(context, record.Name, record.Language, template) : new HtmlString("");
|
||||
});
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Compilation {
|
||||
public interface ICompiler{
|
||||
public interface ICompiler : IDependency {
|
||||
object Compile(string code, IDictionary<string, object> parameters);
|
||||
T Compile<T>(string code, IDictionary<string, object> parameters);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
namespace Orchard.Compilation.Razor {
|
||||
public interface IRazorTemplateCache {
|
||||
public interface IRazorTemplateHolder : ISingletonDependency {
|
||||
string Get(string name);
|
||||
void Set(string name, string template);
|
||||
}
|
@@ -8,7 +8,6 @@ using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web.Razor;
|
||||
using System.Web.Razor.Generator;
|
||||
using Microsoft.CSharp;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Logging;
|
||||
@@ -17,25 +16,51 @@ using Orchard.Utility.Extensions;
|
||||
namespace Orchard.Compilation.Razor {
|
||||
public class RazorCompiler : IRazorCompiler {
|
||||
private readonly ICacheManager _cache;
|
||||
private readonly IWorkContextAccessor _wca;
|
||||
const string DynamicallyGeneratedClassName = "RazorTemplate";
|
||||
const string NamespaceForDynamicClasses = "Orchard.Compilation.Razor";
|
||||
private readonly ISignals _signals;
|
||||
private const string DynamicallyGeneratedClassName = "RazorTemplate";
|
||||
private const string NamespaceForDynamicClasses = "Orchard.Compilation.Razor";
|
||||
private const string ForceRecompile = "Razor.ForceRecompile";
|
||||
private static readonly string[] DefaultNamespaces = {
|
||||
"System",
|
||||
"System.IO",
|
||||
"System.Linq",
|
||||
"System.Collections",
|
||||
"System.Collections.Generic",
|
||||
"System.Dynamic",
|
||||
"System.Text",
|
||||
"System.Web",
|
||||
"System.Web.Mvc",
|
||||
"System.Web.Mvc.Html",
|
||||
"System.Web.Mvc.Ajax",
|
||||
"System.Web.UI",
|
||||
"System.Web.Routing",
|
||||
"Orchard.Compilation.Razor",
|
||||
"Orchard.ContentManagement",
|
||||
"Orchard.DisplayManagement",
|
||||
"Orchard.DisplayManagement.Shapes",
|
||||
"Orchard.Security.Permissions",
|
||||
"Orchard.UI.Resources",
|
||||
"Orchard.Security",
|
||||
"Orchard.Mvc.Spooling",
|
||||
"Orchard.Mvc.Html"
|
||||
};
|
||||
|
||||
public RazorCompiler(ICacheManager cache, IWorkContextAccessor wca) {
|
||||
public RazorCompiler(
|
||||
ICacheManager cache,
|
||||
ISignals signals) {
|
||||
_cache = cache;
|
||||
_wca = wca;
|
||||
_signals = signals;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
ILogger Logger { get; set; }
|
||||
private ILogger Logger { get; set; }
|
||||
|
||||
public IRazorTemplateBase<TModel> CompileRazor<TModel>(string code, string name, IDictionary<string, object> parameters) {
|
||||
return (RazorTemplateBase<TModel>)Compile(code, name, typeof(TModel), parameters);
|
||||
return (RazorTemplateBase<TModel>) Compile(code, name, typeof (TModel), parameters);
|
||||
}
|
||||
|
||||
public IRazorTemplateBase CompileRazor(string code, string name, IDictionary<string, object> parameters) {
|
||||
return (IRazorTemplateBase)Compile(code, name, null, parameters);
|
||||
return (IRazorTemplateBase) Compile(code, name, null, parameters);
|
||||
}
|
||||
|
||||
public object Compile(string code, IDictionary<string, object> parameters) {
|
||||
@@ -47,15 +72,12 @@ namespace Orchard.Compilation.Razor {
|
||||
}
|
||||
|
||||
private object Compile(string code, string name, Type modelType, IDictionary<string, object> parameters) {
|
||||
ISignals signals = _wca.GetContext().TryResolve(out signals) ? signals : null;
|
||||
|
||||
var cacheKey = name ?? GetHash(code);
|
||||
|
||||
var cacheKey = (name ?? DynamicallyGeneratedClassName) + GetHash(code);
|
||||
var generatedClassName = name != null ? name.Strip(c => !c.IsLetter() && !Char.IsDigit(c)) : DynamicallyGeneratedClassName;
|
||||
|
||||
var assembly = _cache.Get(cacheKey, ctx => {
|
||||
if (signals != null) {
|
||||
ctx.Monitor(signals.When(ForceRecompile));
|
||||
}
|
||||
_signals.When(ForceRecompile);
|
||||
|
||||
var modelTypeName = "dynamic";
|
||||
var reader = new StringReader(code);
|
||||
@@ -81,32 +103,7 @@ namespace Orchard.Compilation.Razor {
|
||||
DefaultNamespace = NamespaceForDynamicClasses
|
||||
};
|
||||
|
||||
var namespaces = new List<string> {
|
||||
"System",
|
||||
"System.IO",
|
||||
"System.Linq",
|
||||
"System.Collections",
|
||||
"System.Collections.Generic",
|
||||
"System.Dynamic",
|
||||
"System.Text",
|
||||
"System.Web",
|
||||
"System.Web.Mvc",
|
||||
"System.Web.Mvc.Html",
|
||||
"System.Web.Mvc.Ajax",
|
||||
"System.Web.UI",
|
||||
"System.Web.Routing",
|
||||
"Orchard.Compilation.Razor",
|
||||
"Orchard.ContentManagement",
|
||||
"Orchard.DisplayManagement",
|
||||
"Orchard.DisplayManagement.Shapes",
|
||||
"Orchard.Security.Permissions",
|
||||
"Orchard.UI.Resources",
|
||||
"Orchard.Security",
|
||||
"Orchard.Mvc.Spooling",
|
||||
"Orchard.Mvc.Html"
|
||||
};
|
||||
|
||||
foreach (var n in namespaces) {
|
||||
foreach (var n in DefaultNamespaces) {
|
||||
host.NamespaceImports.Add(n);
|
||||
}
|
||||
|
||||
@@ -119,16 +116,17 @@ namespace Orchard.Compilation.Razor {
|
||||
return assembly.CreateInstance(NamespaceForDynamicClasses + "." + generatedClassName);
|
||||
}
|
||||
|
||||
public static string GetHash(string value)
|
||||
{
|
||||
public static string GetHash(string value) {
|
||||
var data = Encoding.ASCII.GetBytes(value);
|
||||
var hashData = new SHA1Managed().ComputeHash(data);
|
||||
var hashData = new MD5CryptoServiceProvider().ComputeHash(data);
|
||||
|
||||
return hashData.Aggregate(string.Empty, (current, b) => current + b.ToString("X2"));
|
||||
var strBuilder = new StringBuilder();
|
||||
hashData.Aggregate(strBuilder, (current, b) => strBuilder.Append(b));
|
||||
|
||||
return strBuilder.ToString();
|
||||
}
|
||||
|
||||
private static Assembly CreateCompiledAssemblyFor(CodeCompileUnit unitToCompile, string templateName)
|
||||
{
|
||||
private static Assembly CreateCompiledAssemblyFor(CodeCompileUnit unitToCompile, string templateName) {
|
||||
var compilerParameters = new CompilerParameters();
|
||||
compilerParameters.ReferencedAssemblies.AddRange(AppDomain.CurrentDomain
|
||||
.GetAssemblies()
|
||||
|
@@ -1,10 +1,10 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Orchard.Compilation.Razor {
|
||||
public class RazorTemplateCache : IRazorTemplateCache {
|
||||
public class RazorTemplateHolder : IRazorTemplateHolder {
|
||||
private readonly ConcurrentDictionary<string, string> _cache;
|
||||
|
||||
public RazorTemplateCache() {
|
||||
public RazorTemplateHolder() {
|
||||
_cache = new ConcurrentDictionary<string, string>();
|
||||
}
|
||||
public string Get(string name) {
|
||||
|
@@ -9,6 +9,7 @@ using System.Web.Mvc;
|
||||
using Autofac;
|
||||
using Autofac.Configuration;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Compilation.Razor;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment.AutofacUtil;
|
||||
using Orchard.Environment.Configuration;
|
||||
@@ -67,6 +68,7 @@ namespace Orchard.Environment {
|
||||
builder.RegisterType<ViewsBackgroundCompilation>().As<IViewsBackgroundCompilation>().SingleInstance();
|
||||
builder.RegisterType<DefaultExceptionPolicy>().As<IExceptionPolicy>().SingleInstance();
|
||||
builder.RegisterType<DefaultCriticalErrorProvider>().As<ICriticalErrorProvider>().SingleInstance();
|
||||
//builder.RegisterType<RazorTemplateCache>().As<IRazorTemplateProvider>().SingleInstance();
|
||||
|
||||
RegisterVolatileProvider<WebSiteFolder, IWebSiteFolder>(builder);
|
||||
RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder);
|
||||
|
@@ -153,7 +153,7 @@
|
||||
<Compile Include="Compilation\ICompiler.cs" />
|
||||
<Compile Include="Compilation\Razor\RazorModule.cs" />
|
||||
<Compile Include="Compilation\Razor\IRazorCompiler.cs" />
|
||||
<Compile Include="Compilation\Razor\IRazorTemplateCache.cs" />
|
||||
<Compile Include="Compilation\Razor\IRazorTemplateHolder.cs" />
|
||||
<Compile Include="Compilation\Razor\RazorCompiler.cs" />
|
||||
<Compile Include="Compilation\Razor\RazorTemplateBase.cs" />
|
||||
<Compile Include="Compilation\Razor\RazorTemplateCache.cs" />
|
||||
|
Reference in New Issue
Block a user