diff --git a/src/Castle.MonoRail.Views.Spark.Tests/PrecompileInstallerTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/PrecompileInstallerTests.cs
index 244de8f9..7cbdef4e 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/PrecompileInstallerTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/PrecompileInstallerTests.cs
@@ -50,7 +50,11 @@ public void RunPrecompiler()
Assert.That(File.Exists(targetFile), "File exists");
var result = Assembly.LoadFrom(targetFile);
- Assert.AreEqual(3, result.GetTypes().Count());
+
+ var views = result.GetTypes().Where(x => x.BaseType == typeof(SparkView))
+ .ToArray();
+
+ Assert.AreEqual(3, views.Length);
}
public class ParentInstaller : Installer
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/SparkBatchCompilerTester.cs b/src/Castle.MonoRail.Views.Spark.Tests/SparkBatchCompilerTester.cs
index 90936835..3ae4bb27 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/SparkBatchCompilerTester.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/SparkBatchCompilerTester.cs
@@ -35,11 +35,12 @@ public class SparkBatchCompilerTester
[SetUp]
public void Init()
{
- var settings = new SparkSettings();
+ var settings = new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
var services = new StubMonoRailServices();
+ services.AddService(typeof(ISparkSettings), settings);
services.AddService(typeof(IViewSourceLoader), new FileAssemblyViewSourceLoader("MonoRail.Tests.Views"));
- services.AddService(typeof(ISparkViewEngine), new SparkViewEngine(settings));
services.AddService(typeof(IControllerDescriptorProvider), services.ControllerDescriptorProvider);
_factory = new SparkViewFactory();
_factory.Service(services);
@@ -59,7 +60,7 @@ public void CompileBatchDescriptor()
var assembly = _factory.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(3, assembly.GetTypes().Length);
+ Assert.AreEqual(3, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
@@ -98,7 +99,7 @@ public void MultipleLayoutFiles()
var assembly = _factory.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(4, assembly.GetTypes().Length);
+ Assert.AreEqual(4, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
@@ -131,7 +132,7 @@ public void WildcardIncludeRules()
var assembly = _factory.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(3, assembly.GetTypes().Length);
+ Assert.AreEqual(3, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewDataTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewDataTests.cs
index 77b8c423..9a06af17 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewDataTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewDataTests.cs
@@ -46,7 +46,7 @@ public void PropertyBagAvailable()
controllerContext.PropertyBag.Add("foo", "bar");
mocks.ReplayAll();
- view.Contextualize(engineContext, controllerContext, null, null);
+ view.Contextualize(engineContext, controllerContext, null, null, null);
Assert.AreEqual("bar", view.ViewData["foo"]);
}
@@ -71,7 +71,7 @@ public void MergingCollectionsLikeVelocity()
engineContext.Request.Params.Add("contextParamsKey", "contextParamsValue");
controllerContext.Resources.Add("controllerResourcesKey", resource);
- view.Contextualize(engineContext, controllerContext, null, null);
+ view.Contextualize(engineContext, controllerContext, null, null, null);
Assert.AreEqual("controllerPropertyBagValue", view.ViewData["controllerPropertyBagKey"]);
Assert.AreEqual("contextFlashValue", view.ViewData["contextFlashKey"]);
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryStrictNullBehaviourTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryStrictNullBehaviourTests.cs
index 13f4c57f..0f0078c6 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryStrictNullBehaviourTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryStrictNullBehaviourTests.cs
@@ -27,10 +27,13 @@ public class SparkViewFactoryStrictNullBehaviourTests : SparkViewFactoryTestsBas
{
protected override void Configure()
{
- var settings = new SparkSettings();
+ var settings =
+ new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
+
settings.SetNullBehaviour(NullBehaviour.Strict);
- var sparkViewEngine = new SparkViewEngine(settings);
- serviceProvider.AddService(typeof(ISparkViewEngine), sparkViewEngine);
+
+ serviceProvider.AddService(typeof(ISparkSettings), settings);
factory = new SparkViewFactory();
factory.Service(serviceProvider);
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryTests.cs
index e6bdc997..043f055e 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/SparkViewFactoryTests.cs
@@ -27,21 +27,27 @@ namespace Castle.MonoRail.Views.Spark.Tests
[TestFixture]
public class SparkViewFactoryTests : SparkViewFactoryTestsBase
- {
- protected override void Configure()
- {
- factory = new SparkViewFactory();
- factory.Service(serviceProvider);
-
- manager = new DefaultViewEngineManager();
- manager.Service(serviceProvider);
- serviceProvider.ViewEngineManager = manager;
- serviceProvider.AddService(typeof(IViewEngineManager), manager);
- serviceProvider.AddService(typeof(ISparkSettings), new SparkSettings());
+ {
+ protected override void Configure()
+ {
+ var settings = new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
- manager.RegisterEngineForExtesionLookup(factory);
- manager.RegisterEngineForView(factory);
- }
+ settings.AutomaticEncoding = true;
+
+ serviceProvider.AddService(typeof(ISparkSettings), settings);
+
+ factory = new SparkViewFactory();
+ factory.Service(serviceProvider);
+
+ manager = new DefaultViewEngineManager();
+ manager.Service(serviceProvider);
+ serviceProvider.ViewEngineManager = manager;
+ serviceProvider.AddService(typeof(IViewEngineManager), manager);
+
+ manager.RegisterEngineForExtesionLookup(factory);
+ manager.RegisterEngineForView(factory);
+ }
[Test]
public void ExtensionIsSpark()
@@ -69,7 +75,7 @@ public void ContextAndControllerContextAvailable()
descriptor.Templates.Add(string.Format("Shared{0}default.spark", Path.DirectorySeparatorChar));
var entry = factory.Engine.GetEntry(descriptor);
var view = (SparkView)entry.CreateInstance();
- view.Contextualize(engineContext, controllerContext, factory, null);
+ view.Contextualize(engineContext, controllerContext, serviceProvider.GetService(), factory, null);
var result = new StringWriter();
view.RenderView(result);
@@ -114,20 +120,22 @@ public void NullBehaviourConfiguredToLenient()
{
mocks.ReplayAll();
manager.Process(string.Format("Home{0}NullBehaviourConfiguredToLenient", Path.DirectorySeparatorChar), output, engineContext, controller, controllerContext);
- var content = output.ToString();
- Assert.IsFalse(content.Contains("default"));
+ var content = output.ToString();
+ Assert.IsFalse(content.Contains("default"));
- ContainsInOrder(content,
- "
name kaboom *${user.Name}*
",
- "
name silently **
",
- "
name fixed *fred*
");
- }
+ ContainsInOrder(content,
+ "
name kaboom *${user.Name}*
",
+ "
name silently **
",
+ "
name fixed *fred*
");
+ }
[Test]
public void TerseHtmlEncode()
{
mocks.ReplayAll();
manager.Process(string.Format("Home{0}TerseHtmlEncode", Path.DirectorySeparatorChar), output, engineContext, controller, controllerContext);
+
+ // See AutomaticEncoding = true in Configure() method
ContainsInOrder(output.ToString(),
"
This <contains/> html
");
}
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/Stubs/StubController.cs b/src/Castle.MonoRail.Views.Spark.Tests/Stubs/StubController.cs
index 9956d546..9572c999 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/Stubs/StubController.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/Stubs/StubController.cs
@@ -12,10 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+
using Castle.MonoRail.Framework;
namespace Castle.MonoRail.Views.Spark.Tests.Stubs
@@ -34,7 +31,6 @@ public void List()
[Layout("ajax")]
public void _Widget()
{
-
}
}
}
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/BaseViewComponentTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/BaseViewComponentTests.cs
index 226e183a..68ccc496 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/BaseViewComponentTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/BaseViewComponentTests.cs
@@ -29,8 +29,7 @@ public class BaseViewComponentTests
protected StubEngineContext engineContext;
protected SparkViewFactory factory;
protected IController controller;
- protected SparkViewEngine engine;
-
+
[SetUp]
public virtual void Init()
{
@@ -45,9 +44,11 @@ public virtual void Init()
services.AddService(typeof(IViewComponentFactory), viewComponentFactory);
services.AddService(typeof(IViewComponentRegistry), viewComponentFactory.Registry);
- var settings = new SparkSettings();
- engine = new SparkViewEngine(settings);
- services.AddService(typeof(ISparkViewEngine), engine);
+ var settings = new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
+ services.AddService(typeof(ISparkSettings), settings);
+
+ services.AddService(typeof(IResourcePathManager), new DefaultResourcePathManager(settings));
factory = new SparkViewFactory();
factory.Service(services);
diff --git a/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/ViewComponentRenderViewTests.cs b/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/ViewComponentRenderViewTests.cs
index 3b163180..c4dbf1dd 100644
--- a/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/ViewComponentRenderViewTests.cs
+++ b/src/Castle.MonoRail.Views.Spark.Tests/ViewComponents/ViewComponentRenderViewTests.cs
@@ -16,6 +16,7 @@
using System.Reflection;
using Castle.MonoRail.Framework;
using NUnit.Framework;
+using Spark;
using Spark.FileSystem;
namespace Castle.MonoRail.Views.Spark.Tests.ViewComponents
@@ -81,7 +82,7 @@ public void ComponentRenderViewFromEmbeddedResource()
Assembly.Load("Castle.MonoRail.Views.Spark.Tests"),
"Castle.MonoRail.Views.Spark.Tests.EmbeddedViews");
- engine.ViewFolder = engine.ViewFolder.Append(embeddedViewFolder);
+ this.factory.Engine.ViewFolder = this.factory.Engine.ViewFolder.Append(embeddedViewFolder);
mocks.ReplayAll();
diff --git a/src/Castle.MonoRail.Views.Spark/Install/PrecompileInstaller.cs b/src/Castle.MonoRail.Views.Spark/Install/PrecompileInstaller.cs
index 138f6233..69f3d4f5 100644
--- a/src/Castle.MonoRail.Views.Spark/Install/PrecompileInstaller.cs
+++ b/src/Castle.MonoRail.Views.Spark/Install/PrecompileInstaller.cs
@@ -77,11 +77,12 @@ public override void Install(IDictionary stateSaver)
// Attempt to get the configuration from settings, otherwise use default settings
var settings =
(ISparkSettings)config.GetSection("spark") ??
- new SparkSettings();
+ new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
var services = new StubMonoRailServices();
+ services.AddService(typeof(ISparkSettings), settings);
services.AddService(typeof(IViewSourceLoader), new FileAssemblyViewSourceLoader(viewsLocation));
- services.AddService(typeof(ISparkViewEngine), new SparkViewEngine(settings));
services.AddService(typeof(IControllerDescriptorProvider), services.ControllerDescriptorProvider);
var factory = new SparkViewFactory();
diff --git a/src/Spark.Web/NullCacheService.cs b/src/Castle.MonoRail.Views.Spark/NullCacheService.cs
similarity index 100%
rename from src/Spark.Web/NullCacheService.cs
rename to src/Castle.MonoRail.Views.Spark/NullCacheService.cs
diff --git a/src/Castle.MonoRail.Views.Spark/SparkView.cs b/src/Castle.MonoRail.Views.Spark/SparkView.cs
index 8c5a1f16..e87ccdc4 100644
--- a/src/Castle.MonoRail.Views.Spark/SparkView.cs
+++ b/src/Castle.MonoRail.Views.Spark/SparkView.cs
@@ -15,7 +15,6 @@
namespace Castle.MonoRail.Views.Spark
{
using System;
- using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
@@ -35,6 +34,7 @@ protected SparkView()
private IEngineContext _context;
private IControllerContext _controllerContext;
+ private IResourcePathManager _resourcePathManager;
private SparkViewFactory _viewEngine;
private IDictionary _contextVars;
@@ -54,7 +54,7 @@ protected SparkView()
public string SiteRoot { get { return _context.ApplicationPath; } }
public string SiteResource(string path)
{
- return _viewEngine.Engine.ResourcePathManager.GetResourcePath(SiteRoot, path);
+ return this._resourcePathManager.GetResourcePath(SiteRoot, path);
}
public IDictionary PropertyBag { get { return _contextVars ?? _controllerContext.PropertyBag; } }
@@ -91,10 +91,11 @@ public string Eval(string expression, string format)
public T Helper() where T : class { return ControllerContext.Helpers[typeof(T).Name] as T; }
public T Helper(string name) where T : class { return ControllerContext.Helpers[name] as T; }
- public virtual void Contextualize(IEngineContext context, IControllerContext controllerContext, SparkViewFactory viewEngine, SparkView outerView)
+ public virtual void Contextualize(IEngineContext context, IControllerContext controllerContext, IResourcePathManager resourcePathManager, SparkViewFactory viewEngine, SparkView outerView)
{
_context = context;
_controllerContext = controllerContext;
+ _resourcePathManager = resourcePathManager;
_viewEngine = viewEngine;
if (_viewEngine != null && _viewEngine.CacheServiceProvider != null)
@@ -104,13 +105,33 @@ public virtual void Contextualize(IEngineContext context, IControllerContext con
OnceTable = outerView.OnceTable;
}
- public string H(object value)
+ public override void OutputValue(object value, bool automaticEncoding)
{
- if (value is HtmlString)
- return value.ToString();
- return Server.HtmlEncode(Convert.ToString(value));
+ // Always encode when automatic encoding enabled or HtmlString (includes MvcHtmlString)
+ if (automaticEncoding || value is HtmlString)
+ {
+ OutputEncodedValue(value);
+ }
+ else
+ {
+ Output.Write(value);
+ }
+ }
+
+ public void OutputEncodedValue(object value)
+ {
+ if (value is string stringValue)
+ {
+ var encoded = System.Web.HttpUtility.HtmlEncode(stringValue);
+
+ Output.Write(encoded);
+ }
+ else
+ {
+ Output.Write(value.ToString());
+ }
}
-
+
public object HTML(object value)
{
return new HtmlString(Convert.ToString(value));
@@ -132,7 +153,7 @@ public void RenderComponent(
var service = (IViewComponentFactory)_context.GetService(typeof(IViewComponentFactory));
var component = service.Create(name);
- IViewComponentContext viewComponentContext = new ViewComponentContext(this, _viewEngine, name, parameters, body, sections);
+ IViewComponentContext viewComponentContext = new ViewComponentContext(this, _resourcePathManager, _viewEngine, name, parameters, body, sections);
var oldContextVars = _contextVars;
try
diff --git a/src/Castle.MonoRail.Views.Spark/SparkViewFactory.cs b/src/Castle.MonoRail.Views.Spark/SparkViewFactory.cs
index 53cf70ac..9565d90d 100644
--- a/src/Castle.MonoRail.Views.Spark/SparkViewFactory.cs
+++ b/src/Castle.MonoRail.Views.Spark/SparkViewFactory.cs
@@ -26,7 +26,9 @@
using Castle.MonoRail.Framework.Resources;
using Castle.MonoRail.Framework.Routing;
using Castle.MonoRail.Views.Spark.Wrappers;
+using Spark.Bindings;
using Spark.Compiler;
+using Spark.Parser.Syntax;
namespace Castle.MonoRail.Views.Spark
{
@@ -36,6 +38,7 @@ public class SparkViewFactory : ViewEngineBase, IViewSourceLoaderContainer
{
private IControllerDescriptorProvider _controllerDescriptorProvider;
private IViewActivatorFactory _viewActivatorFactory;
+ private IResourcePathManager _resourcePathManager;
public override void Service(IServiceProvider provider)
{
@@ -43,9 +46,10 @@ public override void Service(IServiceProvider provider)
_controllerDescriptorProvider = (IControllerDescriptorProvider)provider.GetService(typeof(IControllerDescriptorProvider));
_viewActivatorFactory = (IViewActivatorFactory)provider.GetService(typeof(IViewActivatorFactory));
+ _resourcePathManager = (IResourcePathManager)provider.GetService(typeof(IResourcePathManager));
_cacheServiceProvider = (ICacheServiceProvider)provider.GetService(typeof(ICacheServiceProvider));
- SetEngine((ISparkViewEngine)provider.GetService(typeof(ISparkViewEngine)));
+ Engine = (ISparkViewEngine)provider.GetService(typeof(ISparkViewEngine));
}
private ISparkViewEngine _engine;
@@ -55,29 +59,35 @@ public ISparkViewEngine Engine
{
if (_engine == null)
{
- SetEngine(new SparkViewEngine(new SparkSettings()));
+ var settings =
+ (ISparkSettings)this.serviceProvider.GetService(typeof(ISparkSettings))
+ ?? new SparkSettings()
+ .SetBaseClassTypeName(typeof(SparkView));
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewFolder = new ViewSourceLoaderWrapper(this);
+
+ var batchCompiler = new RoslynBatchCompiler(new SparkSettings());
+
+ this._engine =
+ new SparkViewEngine(
+ settings,
+ new DefaultSyntaxProvider(settings),
+ this._viewActivatorFactory ?? new DefaultViewActivator(),
+ new DefaultLanguageFactory(batchCompiler, settings),
+ new CompiledViewHolder(),
+ viewFolder,
+ batchCompiler,
+ partialProvider,
+ new DefaultPartialReferenceProvider(partialProvider),
+ new DefaultBindingProvider(),
+ new ViewComponentExtensionFactory(this.serviceProvider));
}
return _engine;
}
- set
- {
- SetEngine(value);
- }
- }
-
- private void SetEngine(ISparkViewEngine engine)
- {
- _engine = engine;
- if (_engine == null)
- return;
-
- _engine.ViewFolder = new ViewSourceLoaderWrapper(this);
- _engine.ExtensionFactory = new ViewComponentExtensionFactory(serviceProvider);
- _engine.DefaultPageBaseType = typeof(SparkView).FullName;
-
- if (_viewActivatorFactory != null)
- _engine.ViewActivatorFactory = _viewActivatorFactory;
+ set => this._engine = value;
}
private ICacheServiceProvider _cacheServiceProvider;
@@ -156,7 +166,7 @@ public override void Process(string templateName, TextWriter output, IEngineCont
var entry = Engine.CreateEntry(descriptor);
var view = (SparkView)entry.CreateInstance();
- view.Contextualize(context, controllerContext, this, null);
+ view.Contextualize(context, controllerContext, _resourcePathManager, this, null);
if (view.Logger == null || view.Logger == NullLogger.Instance)
view.Logger = Logger;
view.RenderView(output);
diff --git a/src/Castle.MonoRail.Views.Spark/ViewComponentContext.cs b/src/Castle.MonoRail.Views.Spark/ViewComponentContext.cs
index df8430a0..1b0e7d20 100644
--- a/src/Castle.MonoRail.Views.Spark/ViewComponentContext.cs
+++ b/src/Castle.MonoRail.Views.Spark/ViewComponentContext.cs
@@ -26,6 +26,7 @@ namespace Castle.MonoRail.Views.Spark
public class ViewComponentContext : IViewComponentContext
{
private readonly SparkView _view;
+ private readonly IResourcePathManager _resourcePathManager;
private readonly SparkViewFactory _viewEngine;
private readonly string _name;
private readonly IDictionary _componentParameters;
@@ -33,10 +34,10 @@ public class ViewComponentContext : IViewComponentContext
private readonly IDictionary _sections;
private readonly IDictionary _contextVarsAdapter;
-
- public ViewComponentContext(SparkView view, SparkViewFactory viewEngine, string name, IDictionary componentParameters, Action body, IDictionary sections)
+ public ViewComponentContext(SparkView view, IResourcePathManager resourcePathManager, SparkViewFactory viewEngine, string name, IDictionary componentParameters, Action body, IDictionary sections)
{
_view = view;
+ _resourcePathManager = resourcePathManager;
_viewEngine = viewEngine;
_name = name;
_componentParameters = componentParameters;
@@ -68,7 +69,7 @@ public void RenderView(string name, TextWriter writer)
try
{
- componentView.Contextualize(_view.Context, _view.ControllerContext, _viewEngine, _view);
+ componentView.Contextualize(_view.Context, _view.ControllerContext, _resourcePathManager, _viewEngine, _view);
componentView.RenderView(writer);
}
finally
diff --git a/src/Castle.MonoRail.Views.Spark/Wrappers/HybridCacheService.cs b/src/Castle.MonoRail.Views.Spark/Wrappers/HybridCacheService.cs
index f9bab1a3..a8a36ab0 100644
--- a/src/Castle.MonoRail.Views.Spark/Wrappers/HybridCacheService.cs
+++ b/src/Castle.MonoRail.Views.Spark/Wrappers/HybridCacheService.cs
@@ -32,7 +32,7 @@ public HybridCacheService(IEngineContext context)
}
else
{
- _fallbackCacheService = new DefaultCacheService(context.UnderlyingContext.Cache);
+ _fallbackCacheService = new WebCacheService(context.UnderlyingContext.Cache);
}
}
diff --git a/src/Spark.AspNetCore.Mvc/AspNetCoreDescriptorBuilder.cs b/src/Spark.AspNetCore.Mvc/AspNetCoreDescriptorBuilder.cs
new file mode 100644
index 00000000..ef8142d9
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/AspNetCoreDescriptorBuilder.cs
@@ -0,0 +1,77 @@
+using Spark.Descriptors;
+using Spark.FileSystem;
+
+namespace Spark.AspNetCore.Mvc;
+
+public class AspNetCoreDescriptorBuilder : DescriptorBuilder
+{
+ public AspNetCoreDescriptorBuilder(ISparkSettings settings, IViewFolder viewFolder) : base(settings, viewFolder)
+ {
+ }
+
+ protected override IEnumerable PotentialViewLocations(string controllerName, string viewName, IDictionary extra)
+ {
+ if (extra.TryGetValue("area", out var value))
+ {
+ var area = value as string;
+
+ return ApplyFilters([
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}{controllerName}{Path.DirectorySeparatorChar}{viewName}.spark",
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Shared{Path.DirectorySeparatorChar}{viewName}.spark",
+ $"{controllerName}{Path.DirectorySeparatorChar}{viewName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{viewName}.spark"
+ ], extra);
+ }
+
+ return ApplyFilters([
+ $"{controllerName}{Path.DirectorySeparatorChar}{viewName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{viewName}.spark"
+ ], extra);
+ }
+
+ protected override IEnumerable PotentialMasterLocations(string masterName, IDictionary extra)
+ {
+ if (extra.TryGetValue("area", out var value))
+ {
+ var area = value as string;
+
+ return ApplyFilters([
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Layouts{Path.DirectorySeparatorChar}{masterName}.spark",
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Shared{Path.DirectorySeparatorChar}{masterName}.spark",
+ $"Layouts{Path.DirectorySeparatorChar}{masterName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{masterName}.spark"
+ ], extra);
+ }
+
+ return ApplyFilters([
+ $"Layouts{Path.DirectorySeparatorChar}{masterName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{masterName}.spark"
+ ], extra);
+ }
+
+ protected override IEnumerable PotentialDefaultMasterLocations(string controllerName, IDictionary extra)
+ {
+ if (extra.TryGetValue("area", out var value))
+ {
+ var area = value as string;
+
+ return ApplyFilters([
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Layouts{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Shared{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Layouts{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Layouts{Path.DirectorySeparatorChar}Application.spark",
+ $"Areas{Path.DirectorySeparatorChar}{area}{Path.DirectorySeparatorChar}Views{Path.DirectorySeparatorChar}Shared{Path.DirectorySeparatorChar}Application.spark",
+ $"Layouts{Path.DirectorySeparatorChar}Application.spark",
+ $"Shared{Path.DirectorySeparatorChar}Application.spark",
+ ], extra);
+ }
+
+ return ApplyFilters([
+ $"Layouts{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Shared{Path.DirectorySeparatorChar}{controllerName}.spark",
+ $"Layouts{Path.DirectorySeparatorChar}Application.spark",
+ $"Shared{Path.DirectorySeparatorChar}Application.spark"
+ ], extra);
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/EntryPoint.cs b/src/Spark.AspNetCore.Mvc/EntryPoint.cs
new file mode 100644
index 00000000..09c85e9f
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/EntryPoint.cs
@@ -0,0 +1,10 @@
+namespace Spark.AspNetCore.Mvc
+{
+ public static class EntryPoint
+ {
+ public static void Main(string[] arguments)
+ {
+ throw new NotImplementedException("This method should never be called. It is only here to satisfy the compiler (see in the .csproj file)");
+ }
+ }
+}
diff --git a/src/Spark.AspNetCore.Mvc/Extensions/ServiceCollectionExtensions.cs b/src/Spark.AspNetCore.Mvc/Extensions/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..034d8aa0
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/Extensions/ServiceCollectionExtensions.cs
@@ -0,0 +1,72 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using Spark.Bindings;
+using Spark.Compiler;
+using Spark.Compiler.Roslyn;
+using Spark.Descriptors;
+using Spark.FileSystem;
+using Spark.Parser;
+using Spark.Parser.Syntax;
+
+namespace Spark.AspNetCore.Mvc.Extensions
+{
+ public static class ServiceCollectionExtensions
+ {
+ public static IServiceCollection AddSpark(this IServiceCollection services, Action? setupAction = null)
+ {
+ if (services == null)
+ {
+ throw new ArgumentNullException(nameof(services));
+ }
+
+ services
+ .AddOptions()
+ .AddSingleton, SparkOptionsSetup>()
+ .AddTransient(f => f.GetService>()?.Value)
+ .AddTransient(f => f.GetService>()?.Value);
+
+ services
+ .AddMemoryCache()
+ .AddTransient();
+
+ if (setupAction != null)
+ {
+ services.Configure(setupAction);
+ }
+
+ // TODO: Reduce memory consumption cause by loading the assembly of the views compiled dynamically
+ services
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton();
+
+ services
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton(f => f.GetService().CreateDefaultViewFolder())
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton();
+
+ services.AddSingleton(c => null);
+
+ services
+ .AddSingleton();
+
+ services
+ .AddSingleton();
+
+ services
+ .AddTransient, SparkMvcOptionsSetup>()
+ .AddTransient, SparkMvcViewOptionsSetup>()
+ .AddSingleton();
+
+ return services;
+ }
+ }
+}
diff --git a/src/Spark.AspNetCore.Mvc/Filters/HtmlHelperResultFilter.cs b/src/Spark.AspNetCore.Mvc/Filters/HtmlHelperResultFilter.cs
new file mode 100644
index 00000000..534aafc6
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/Filters/HtmlHelperResultFilter.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.AspNetCore.Mvc.Rendering;
+
+namespace Spark.AspNetCore.Mvc.Filters
+{
+ ///
+ /// Result filter to pass the HTML Helper down to the spark view.
+ ///
+ public class HtmlHelperResultFilter(IHtmlHelper htmlHelper) : IAlwaysRunResultFilter
+ {
+ public void OnResultExecuting(ResultExecutingContext context)
+ {
+ if (context.Controller is Controller controller)
+ {
+ // The HtmlHelper will have to contextualised before being used in the view
+ // See SparkView.RenderAsync()
+ controller.ViewData["Html"] = htmlHelper;
+ }
+ }
+
+ public void OnResultExecuted(ResultExecutedContext context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/Helpers/PathHelper.cs b/src/Spark.AspNetCore.Mvc/Helpers/PathHelper.cs
new file mode 100644
index 00000000..4a1dbc1f
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/Helpers/PathHelper.cs
@@ -0,0 +1,37 @@
+namespace Spark.AspNetCore.Mvc.Helpers;
+
+public static class PathHelper
+{
+ public static string GetAbsolutePath(string executingFilePath, string pagePath)
+ {
+ // Path is not valid or a page name; no change required.
+ if (string.IsNullOrEmpty(pagePath) || !IsRelativePath(pagePath))
+ {
+ return pagePath;
+ }
+
+ if (IsAbsolutePath(pagePath))
+ {
+ // An absolute path already; no change required.
+ return pagePath.Replace("~/", string.Empty);
+ }
+
+ // Given a relative path i.e. not yet application-relative (starting with "~/" or "/"), interpret
+ // path relative to currently-executing view, if any.
+ if (string.IsNullOrEmpty(executingFilePath))
+ {
+ // Not yet executing a view. Start in app root.
+ return $"/{pagePath}";
+ }
+
+ // Get directory name (including final slash) but do not use Path.GetDirectoryName() to preserve path
+ // normalization.
+ var index = executingFilePath.LastIndexOf('/');
+ return executingFilePath.Substring(0, index + 1) + pagePath;
+ }
+
+ public static bool IsAbsolutePath(string name) => name.StartsWith("~/") || name.StartsWith("/");
+
+ // Though ./ViewName looks like a relative path, framework searches for that view using view locations.
+ public static bool IsRelativePath(string name) => !IsAbsolutePath(name);
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/Properties/launchSettings.json b/src/Spark.AspNetCore.Mvc/Properties/launchSettings.json
new file mode 100644
index 00000000..c1e85032
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "Spark.AspNetCore.Mvc": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:49470;http://localhost:49471"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/Spark.AspNetCore.Mvc.csproj b/src/Spark.AspNetCore.Mvc/Spark.AspNetCore.Mvc.csproj
new file mode 100644
index 00000000..e541238c
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/Spark.AspNetCore.Mvc.csproj
@@ -0,0 +1,32 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ \
+
+
+ True
+ \
+
+
+ SparkKey.snk
+
+
+
+
diff --git a/src/Spark.AspNetCore.Mvc/SparkMvcOptionsSetup.cs b/src/Spark.AspNetCore.Mvc/SparkMvcOptionsSetup.cs
new file mode 100644
index 00000000..94d60065
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkMvcOptionsSetup.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using Spark.AspNetCore.Mvc.Filters;
+
+namespace Spark.AspNetCore.Mvc;
+
+public class SparkMvcOptionsSetup : IConfigureOptions
+{
+ public void Configure(MvcOptions options)
+ {
+ options.Filters.Add();
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/SparkMvcViewOptionsSetup.cs b/src/Spark.AspNetCore.Mvc/SparkMvcViewOptionsSetup.cs
new file mode 100644
index 00000000..7aa5c9f0
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkMvcViewOptionsSetup.cs
@@ -0,0 +1,23 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+
+namespace Spark.AspNetCore.Mvc;
+
+public class SparkMvcViewOptionsSetup(ISparkViewEngine sparkCoreViewEngine) : IConfigureOptions
+{
+ private readonly ISparkViewEngine SparkCoreViewEngine = sparkCoreViewEngine ?? throw new ArgumentNullException(nameof(sparkCoreViewEngine));
+
+ ///
+ /// Configures to use .
+ ///
+ /// The to configure.
+ public void Configure(MvcViewOptions options)
+ {
+ if (options == null)
+ {
+ throw new ArgumentNullException(nameof(options));
+ }
+
+ options.ViewEngines.Add(SparkCoreViewEngine);
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/SparkOptionsSetup.cs b/src/Spark.AspNetCore.Mvc/SparkOptionsSetup.cs
new file mode 100644
index 00000000..21b06e1c
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkOptionsSetup.cs
@@ -0,0 +1,10 @@
+using Microsoft.Extensions.Options;
+
+namespace Spark.AspNetCore.Mvc;
+
+public class SparkOptionsSetup : IConfigureOptions
+{
+ public void Configure(SparkSettings options)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/SparkView.cs b/src/Spark.AspNetCore.Mvc/SparkView.cs
new file mode 100644
index 00000000..ba50b383
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkView.cs
@@ -0,0 +1,169 @@
+using System.Configuration;
+using System.Text.Encodings.Web;
+using Microsoft.AspNetCore.Html;
+using Microsoft.AspNetCore.Mvc.Rendering;
+using Microsoft.AspNetCore.Mvc.ViewEngines;
+using Microsoft.AspNetCore.Mvc.ViewFeatures;
+
+namespace Spark.AspNetCore.Mvc;
+
+public abstract class SparkView : SparkViewBase, IView
+{
+ /// Set by method.
+ protected ViewContext? ViewContext;
+
+ public string Path { get; set; }
+
+ #region Exposing properties
+
+ ///
+ /// Html encoder used to encode content.
+ ///
+ protected HtmlEncoder HtmlEncoder { get; set; } = HtmlEncoder.Default;
+
+ ///
+ /// Url encoder used to encode content.
+ ///
+ protected UrlEncoder UrlEncoder { get; set; } = UrlEncoder.Default;
+
+ ///
+ /// JavaScript encoder used to encode content.
+ ///
+ protected JavaScriptEncoder JavaScriptEncoder { get; set; } = JavaScriptEncoder.Default;
+
+ public ViewDataDictionary ViewData => this.ViewContext.ViewData;
+
+ public dynamic ViewBag => this.ViewContext.ViewBag;
+
+ public ITempDataDictionary TempData => this.ViewContext.TempData;
+
+ public HttpContext Context => this.ViewContext.HttpContext;
+
+ public HttpRequest Request => this.ViewContext.HttpContext.Request;
+
+ public HttpResponse Response => this.ViewContext.HttpContext.Response;
+
+ public IHtmlHelper Html
+ {
+ get
+ {
+ if (this.ViewContext.ViewData.TryGetValue("Html", out object value))
+ {
+ return (IHtmlHelper) value;
+ }
+
+ throw new ConfigurationErrorsException($"Html not set in ViewData, is {nameof(Spark.AspNetCore.Mvc.Filters.HtmlHelperResultFilter)} configured?");
+ }
+ }
+
+ #endregion
+
+ public override void OutputValue(object value, bool automaticEncoding)
+ {
+ // Always encode when automatic encoding is enabled or value is IHtmlContent
+ if (automaticEncoding || value is IHtmlContent)
+ {
+ OutputEncodedValue(value);
+ }
+ else
+ {
+ Output.Write(value);
+ }
+ }
+
+ public void OutputEncodedValue(object value)
+ {
+ if (value is string stringValue)
+ {
+ var encoded = HtmlEncoder.Default.Encode(stringValue);
+
+ Output.Write(encoded);
+ }
+ else if (value is IHtmlContent htmlContent)
+ {
+ htmlContent.WriteTo(Output, HtmlEncoder.Default);
+ }
+ else
+ {
+ Output.Write(value.ToString());
+ }
+ }
+
+ public IHtmlContent HTML(object value)
+ {
+ return new HtmlString(Convert.ToString(value));
+ }
+
+ public object Eval(string expression)
+ {
+ return ViewData.Eval(expression);
+ }
+ public string Eval(string expression, string format)
+ {
+ return ViewData.Eval(expression, format);
+ }
+
+ public Task RenderAsync(ViewContext context)
+ {
+ this.ViewContext = context;
+
+ // Checks if HtmlHelperResultFilter set the HTML helper in the view data
+ if (this.ViewContext.ViewData.TryGetValue("Html", out var htmlHelper))
+ {
+ if (htmlHelper is IViewContextAware viewContextAware)
+ {
+ viewContextAware.Contextualize(this.ViewContext);
+ }
+ }
+
+ var outerView = this.ViewContext.View as SparkViewBase;
+ var isNestedView = outerView != null && ReferenceEquals(this, outerView) == false;
+
+ var priorContent = this.Content;
+ var priorOnce = this.OnceTable;
+ TextWriter priorContentView = null;
+
+ if (isNestedView)
+ {
+ // set aside the "view" content, to avoid modification
+ if (outerView.Content.TryGetValue("view", out priorContentView))
+ {
+ outerView.Content.Remove("view");
+ }
+
+ // assume the values of the outer view collections
+ this.Content = outerView.Content;
+ this.OnceTable = outerView.OnceTable;
+ }
+
+ this.RenderView(context.Writer);
+
+ if (isNestedView)
+ {
+ this.Content = priorContent;
+ this.OnceTable = priorOnce;
+
+ // restore previous state of "view" content
+ if (priorContentView != null)
+ {
+ outerView.Content["view"] = priorContentView;
+ }
+ else if (outerView.Content.ContainsKey("view"))
+ {
+ outerView.Content.Remove("view");
+ }
+ }
+ else
+ {
+ // proactively dispose named content. pools spoolwriter pages. avoids finalizers.
+ foreach (var content in this.Content.Values)
+ {
+ content.Close();
+ }
+ }
+
+ this.Content.Clear();
+
+ return Task.CompletedTask;
+ }
+}
diff --git a/src/Spark.AspNetCore.Mvc/SparkViewEngine.cs b/src/Spark.AspNetCore.Mvc/SparkViewEngine.cs
new file mode 100644
index 00000000..dbed9edc
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkViewEngine.cs
@@ -0,0 +1,110 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.ViewEngines;
+using Spark.AspNetCore.Mvc.Helpers;
+using Spark.Descriptors;
+
+namespace Spark.AspNetCore.Mvc;
+
+public interface ISparkViewEngine : IViewEngine;
+
+public class SparkViewEngine : ISparkViewEngine
+{
+ private readonly Spark.ISparkViewEngine ViewEngine;
+ private readonly IDescriptorBuilder DescriptorBuilder;
+ private readonly ICacheService CacheService;
+
+ private readonly Dictionary _cache;
+
+ public SparkViewEngine(Spark.ISparkViewEngine viewEngine, IDescriptorBuilder descriptorBuilder, ICacheService cacheService)
+ {
+ ViewEngine = viewEngine;
+ DescriptorBuilder = descriptorBuilder;
+ CacheService = cacheService;
+
+ _cache = new Dictionary();
+ }
+
+ public ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage)
+ {
+ return FindViewInternal(context, viewName, null, true, false);
+ }
+
+ public ViewEngineResult GetView(string executingFilePath, string viewPath, bool isMainPage)
+ {
+ var applicationRelativePath = PathHelper.GetAbsolutePath(executingFilePath, viewPath);
+
+ return ViewEngineResult.NotFound(applicationRelativePath, Enumerable.Empty());
+ }
+
+ private ViewEngineResult FindViewInternal(ActionContext context, string viewName, string masterName, bool findDefaultMaster, bool useCache)
+ {
+ var searchedLocations = new List();
+
+ var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
+ if (controllerActionDescriptor == null)
+ {
+ return ViewEngineResult.NotFound(viewName, searchedLocations);
+ }
+
+ var targetNamespace = controllerActionDescriptor.ControllerTypeInfo.Namespace;
+ var controllerName = controllerActionDescriptor.ControllerName;
+
+ var descriptorParams = new BuildDescriptorParams(
+ targetNamespace,
+ controllerName,
+ viewName,
+ masterName,
+ findDefaultMaster,
+ DescriptorBuilder.GetExtraParameters(new SparkRouteData(context.RouteData.Values)));
+
+ ISparkViewEntry entry;
+ if (useCache)
+ {
+ if (TryGetCacheValue(descriptorParams, out entry) && entry.IsCurrent())
+ {
+ return BuildResult(viewName, entry);
+ }
+
+ return ViewEngineResult.NotFound(viewName, searchedLocations);
+ }
+
+ var descriptor = DescriptorBuilder.BuildDescriptor(
+ descriptorParams,
+ searchedLocations);
+
+ if (descriptor == null)
+ {
+ return ViewEngineResult.NotFound(viewName, searchedLocations);
+ }
+
+ entry = ViewEngine.CreateEntry(descriptor);
+
+ SetCacheValue(descriptorParams, entry);
+
+ return BuildResult(viewName, entry);
+ }
+
+ private bool TryGetCacheValue(BuildDescriptorParams descriptorParams, out ISparkViewEntry entry)
+ {
+ lock (_cache) return _cache.TryGetValue(descriptorParams, out entry);
+ }
+
+ private void SetCacheValue(BuildDescriptorParams descriptorParams, ISparkViewEntry entry)
+ {
+ lock (_cache) _cache[descriptorParams] = entry;
+ }
+
+ private ViewEngineResult BuildResult(string viewName, ISparkViewEntry entry)
+ {
+ var view = (IView) entry.CreateInstance();
+
+ if (view is SparkView sparkView)
+ {
+ sparkView.Path = entry.Descriptor.Templates[0];
+ sparkView.CacheService = this.CacheService;
+ }
+
+ return ViewEngineResult.Found(viewName, view);
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.AspNetCore.Mvc/SparkViewOfT.cs b/src/Spark.AspNetCore.Mvc/SparkViewOfT.cs
new file mode 100644
index 00000000..c4109bf2
--- /dev/null
+++ b/src/Spark.AspNetCore.Mvc/SparkViewOfT.cs
@@ -0,0 +1,54 @@
+using System.Configuration;
+using System.Reflection;
+using System.Text.Encodings.Web;
+using Microsoft.AspNetCore.Mvc.Rendering;
+using Microsoft.AspNetCore.Mvc.ViewEngines;
+using Microsoft.AspNetCore.Mvc.ViewFeatures;
+using Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers;
+
+namespace Spark.AspNetCore.Mvc;
+
+public abstract class SparkView : SparkView
+{
+ private ViewDataDictionary? viewData;
+ private IHtmlHelper? htmlHelper;
+
+ public TModel? Model => this.ViewData.Model;
+
+ public new ViewDataDictionary ViewData => this.viewData ??= new ViewDataDictionary(this.ViewContext.ViewData);
+
+ public new IHtmlHelper Html
+ {
+ get
+ {
+ if (this.htmlHelper == null)
+ {
+ if (this.ViewContext.ViewData.TryGetValue("Html", out object value))
+ {
+ var plainHelper = (IHtmlHelper)value;
+
+ // TODO: Improve this as using reflection will fail if Microsoft's HtmlHelper implementation fails
+ var htmlGenerator = (IHtmlGenerator) typeof(HtmlHelper).GetField("_htmlGenerator", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value);
+ var compositeViewEngine = (ICompositeViewEngine) typeof(HtmlHelper).GetField("_viewEngine", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value);
+ var viewBufferScope = (IViewBufferScope) typeof(HtmlHelper).GetField("_bufferScope", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value);
+ var htmlEncoder = (HtmlEncoder) typeof(HtmlEncoder).GetField("_htmlEncoder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(value);
+
+ this.htmlHelper = new HtmlHelper(
+ htmlGenerator,
+ compositeViewEngine,
+ plainHelper.MetadataProvider,
+ viewBufferScope,
+ htmlEncoder,
+ plainHelper.UrlEncoder,
+ new ModelExpressionProvider(plainHelper.MetadataProvider));
+ }
+ else
+ {
+ throw new ConfigurationErrorsException($"Html not set in ViewData, is {nameof(Filters.HtmlHelperResultFilter)} configured?");
+ }
+ }
+
+ return this.htmlHelper;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spark.JsTests/Generate.ashx.cs b/src/Spark.JsTests/Generate.ashx.cs
index f4cc82f2..5e9b5ec8 100644
--- a/src/Spark.JsTests/Generate.ashx.cs
+++ b/src/Spark.JsTests/Generate.ashx.cs
@@ -1,3 +1,4 @@
+
// Copyright 2008-2009 Louis DeJardin - http://whereslou.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,7 +17,11 @@
using System.IO;
using System.Web;
using System.Web.Services;
+using Spark.Bindings;
+using Spark.Compiler;
using Spark.FileSystem;
+using Spark.Parser;
+using Spark.Parser.Syntax;
namespace Spark.JsTests
{
@@ -29,13 +34,31 @@ public class Generate : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
- var engine = new SparkViewEngine
- {
- ViewFolder = new VirtualPathProviderViewFolder("~/Views")
- };
- var entry = engine.CreateEntry(new SparkViewDescriptor()
- .SetLanguage(LanguageType.Javascript)
- .AddTemplate(context.Request.PathInfo.TrimStart('/', Path.DirectorySeparatorChar) + ".spark"));
+ var settings = new SparkSettings().SetDefaultLanguage(LanguageType.Javascript);
+
+ var viewFolder = new VirtualPathProviderViewFolder("~/Views");
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var batchCompiler = new RoslynBatchCompiler(new SparkSettings());
+
+ var engine = new SparkViewEngine(
+ settings,
+ new DefaultSyntaxProvider(settings),
+ new DefaultViewActivator(),
+ new DefaultLanguageFactory(batchCompiler, settings),
+ new CompiledViewHolder(),
+ viewFolder,
+ batchCompiler,
+ partialProvider,
+ new DefaultPartialReferenceProvider(partialProvider),
+ new DefaultBindingProvider(),
+ null);
+
+ var entry = engine.CreateEntry(
+ new SparkViewDescriptor()
+ .SetLanguage(LanguageType.Javascript)
+ .AddTemplate(context.Request.PathInfo.TrimStart('/', Path.DirectorySeparatorChar) + ".spark"));
//Spark.Simple._LiteralHtml({foo:'asoi'})
context.Response.ContentType = "text/javascript";
diff --git a/src/Spark.Python.Tests/PythonViewCompilerTests.cs b/src/Spark.Python.Tests/PythonViewCompilerTests.cs
index ceec7215..259d984f 100644
--- a/src/Spark.Python.Tests/PythonViewCompilerTests.cs
+++ b/src/Spark.Python.Tests/PythonViewCompilerTests.cs
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-using System;
+
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
@@ -27,17 +27,18 @@ namespace Spark.Python.Tests
[TestFixture]
public class PythonViewCompilerTests
{
+ private ISparkSettings _settings;
private PythonViewCompiler _compiler;
private PythonLanguageFactory _languageFactory;
[SetUp]
public void Init()
{
- _compiler = new PythonViewCompiler
- {
- BaseClass = typeof(StubSparkView).FullName
- };
- _languageFactory = new PythonLanguageFactory();
+ _settings = new SparkSettings();
+
+ _compiler = new PythonViewCompiler(_settings);
+
+ _languageFactory = new PythonLanguageFactory(new RoslynBatchCompiler(this._settings), _settings);
// Load up assemblies
IronPython.Hosting.Python.CreateEngine();
@@ -85,10 +86,9 @@ public void CodeInheritsBaseClass()
{
var chunks = Chunks();
- _compiler.BaseClass = "ThisIsTheBaseClass";
_compiler.GenerateSourceCode(chunks, chunks);
- Assert.That(_compiler.SourceCode.Contains(": ThisIsTheBaseClass"));
+ Assert.That(_compiler.SourceCode.Contains(": Spark.Tests.Stubs.StubSparkView"));
}
[Test]
@@ -96,10 +96,9 @@ public void CodeInheritsBaseClassWithTModel()
{
var chunks = Chunks(new ViewDataModelChunk { TModel = "ThisIsTheModelClass" });
- _compiler.BaseClass = "ThisIsTheBaseClass";
_compiler.GenerateSourceCode(chunks, chunks);
- Assert.That(_compiler.SourceCode.Contains(": ThisIsTheBaseClass"));
+ Assert.That(_compiler.SourceCode.Contains(": Spark.Tests.Stubs.StubSparkView"));
}
[Test]
diff --git a/src/Spark.Python.Tests/ScriptingLanguageFactoryTests.cs b/src/Spark.Python.Tests/ScriptingLanguageFactoryTests.cs
index 37b5e7d3..b167ac6c 100644
--- a/src/Spark.Python.Tests/ScriptingLanguageFactoryTests.cs
+++ b/src/Spark.Python.Tests/ScriptingLanguageFactoryTests.cs
@@ -12,7 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
+
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
+using Spark.Extensions;
using Spark.Python.Compiler;
using Spark.Tests.Stubs;
@@ -26,11 +29,15 @@ public class ScriptingLanguageFactoryTests
[SetUp]
public void Init()
{
- _engine = new SparkViewEngine(new SparkSettings())
- {
- LanguageFactory = new PythonLanguageFactory(),
- DefaultPageBaseType = typeof(StubSparkView).FullName
- };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(StubSparkView));
+
+ var sp = new ServiceCollection()
+ .AddSpark(settings)
+ .AddSingleton()
+ .BuildServiceProvider();;
+
+ _engine = (SparkViewEngine)sp.GetService();
+
IronPython.Hosting.Python.CreateEngine();
}
diff --git a/src/Spark.Python.Tests/Spark.Python.Tests.csproj b/src/Spark.Python.Tests/Spark.Python.Tests.csproj
index dabe7593..d05dcf03 100644
--- a/src/Spark.Python.Tests/Spark.Python.Tests.csproj
+++ b/src/Spark.Python.Tests/Spark.Python.Tests.csproj
@@ -20,7 +20,8 @@
-
+
+
diff --git a/src/Spark.Python/Compiler/PythonViewCompiler.cs b/src/Spark.Python/Compiler/PythonViewCompiler.cs
index 04ed8448..f182a61f 100644
--- a/src/Spark.Python/Compiler/PythonViewCompiler.cs
+++ b/src/Spark.Python/Compiler/PythonViewCompiler.cs
@@ -23,14 +23,14 @@
namespace Spark.Python.Compiler
{
- public class PythonViewCompiler : ViewCompiler
+ public class PythonViewCompiler(ISparkSettings settings) : ViewCompiler
{
public override void CompileView(IEnumerable> viewTemplates, IEnumerable> allResources)
{
GenerateSourceCode(viewTemplates, allResources);
- var compiler = new BatchCompiler();
- var assembly = compiler.Compile(Debug, "csharp", SourceCode);
+ var compiler = new RoslynBatchCompiler(new SparkSettings());
+ var assembly = compiler.Compile(settings.Debug, "csharp", null, new[] { SourceCode }, settings.ExcludeAssemblies);
CompiledType = assembly.GetType(ViewClassFullName);
}
@@ -83,13 +83,13 @@ public override void GenerateSourceCode(IEnumerable> viewTemplates,
}
}
- var baseClassGenerator = new BaseClassVisitor { BaseClass = BaseClass };
+ var baseClassGenerator = new BaseClassVisitor { BaseClass = settings.BaseClassTypeName };
foreach (var resource in allResources)
{
baseClassGenerator.Accept(resource);
}
- BaseClass = baseClassGenerator.BaseClassTypeName;
+ var baseClass = baseClassGenerator.BaseClassTypeName;
var source = new StringBuilder();
@@ -121,7 +121,7 @@ public override void GenerateSourceCode(IEnumerable> viewTemplates,
source.AppendLine(" })]");
}
- source.Append("public class ").Append(viewClassName).Append(" : ").Append(BaseClass).AppendLine(", global::Spark.Python.IScriptingSparkView");
+ source.Append("public class ").Append(viewClassName).Append(" : ").Append(baseClass).AppendLine(", global::Spark.Python.IScriptingSparkView");
source.AppendLine("{");
source.Append("static System.Guid _generatedViewId = new System.Guid(\"").Append(GeneratedViewId).AppendLine("\");");
diff --git a/src/Spark.Python/PythonLanguageFactory.cs b/src/Spark.Python/PythonLanguageFactory.cs
index 318a277e..791861c5 100644
--- a/src/Spark.Python/PythonLanguageFactory.cs
+++ b/src/Spark.Python/PythonLanguageFactory.cs
@@ -18,7 +18,7 @@
namespace Spark.Python
{
- public class PythonLanguageFactory : DefaultLanguageFactory
+ public class PythonLanguageFactory(IBatchCompiler batchCompiler, ISparkSettings settings) : DefaultLanguageFactory(batchCompiler, settings)
{
private PythonEngineManager _PythonEngineManager;
@@ -42,25 +42,14 @@ public override ViewCompiler CreateViewCompiler(ISparkViewEngine engine, SparkVi
{
case LanguageType.Default:
case LanguageType.Python:
- viewCompiler = new PythonViewCompiler();
+ viewCompiler = new PythonViewCompiler(settings);
break;
default:
return base.CreateViewCompiler(engine, descriptor);
}
- var pageBaseType = engine.Settings.PageBaseType;
- if (string.IsNullOrEmpty(pageBaseType))
- {
- pageBaseType = engine.DefaultPageBaseType;
- }
-
- viewCompiler.BaseClass = pageBaseType;
viewCompiler.Descriptor = descriptor;
- viewCompiler.Debug = engine.Settings.Debug;
- viewCompiler.NullBehaviour = engine.Settings.NullBehaviour;
- viewCompiler.UseAssemblies = engine.Settings.UseAssemblies;
- viewCompiler.UseNamespaces = engine.Settings.UseNamespaces;
-
+
return viewCompiler;
}
diff --git a/src/Spark.Python/Spark.Python.csproj b/src/Spark.Python/Spark.Python.csproj
index 3cd3964e..4f8693cf 100644
--- a/src/Spark.Python/Spark.Python.csproj
+++ b/src/Spark.Python/Spark.Python.csproj
@@ -1,6 +1,7 @@
net48
+ latestLibraryAllRules.rulesetFalse
diff --git a/src/Spark.Ruby.Tests/RubyViewCompilerTests.cs b/src/Spark.Ruby.Tests/RubyViewCompilerTests.cs
index 7c9df532..ad38a50a 100644
--- a/src/Spark.Ruby.Tests/RubyViewCompilerTests.cs
+++ b/src/Spark.Ruby.Tests/RubyViewCompilerTests.cs
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-using System;
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
@@ -27,17 +26,19 @@ namespace Spark.Ruby.Tests
[TestFixture]
public class RubyViewCompilerTests
{
+ private ISparkSettings _settings;
private RubyViewCompiler _compiler;
private RubyLanguageFactory _languageFactory;
[SetUp]
public void Init()
{
- _compiler = new RubyViewCompiler
- {
- BaseClass = typeof(StubSparkView).FullName,Debug = true
- };
- _languageFactory = new RubyLanguageFactory();
+ _settings = new SparkSettings
+ {
+ Debug = true
+ };
+ _compiler = new RubyViewCompiler(this._settings);
+ _languageFactory = new RubyLanguageFactory(new RoslynBatchCompiler(this._settings), this._settings);
//load assemblies
global::IronRuby.Ruby.CreateEngine();
@@ -86,10 +87,9 @@ public void CodeInheritsBaseClass()
{
var chunks = Chunks();
- _compiler.BaseClass = "ThisIsTheBaseClass";
_compiler.GenerateSourceCode(chunks, chunks);
- Assert.That(_compiler.SourceCode.Contains(": ThisIsTheBaseClass"));
+ Assert.That(_compiler.SourceCode.Contains(": Spark.Tests.Stubs.StubSparkView"));
}
[Test]
@@ -97,10 +97,9 @@ public void CodeInheritsBaseClassWithTModel()
{
var chunks = Chunks(new ViewDataModelChunk { TModel = "ThisIsTheModelClass" });
- _compiler.BaseClass = "ThisIsTheBaseClass";
_compiler.GenerateSourceCode(chunks, chunks);
- Assert.That(_compiler.SourceCode.Contains(": ThisIsTheBaseClass"));
+ Assert.That(_compiler.SourceCode.Contains(": Spark.Tests.Stubs.StubSparkView"));
}
[Test]
diff --git a/src/Spark.Ruby.Tests/Spark.Ruby.Tests.csproj b/src/Spark.Ruby.Tests/Spark.Ruby.Tests.csproj
index 04459c71..7199cc3b 100644
--- a/src/Spark.Ruby.Tests/Spark.Ruby.Tests.csproj
+++ b/src/Spark.Ruby.Tests/Spark.Ruby.Tests.csproj
@@ -24,7 +24,8 @@
-
+
+
diff --git a/src/Spark.Ruby/Compiler/RubyViewCompiler.cs b/src/Spark.Ruby/Compiler/RubyViewCompiler.cs
index 03123925..06f8501e 100644
--- a/src/Spark.Ruby/Compiler/RubyViewCompiler.cs
+++ b/src/Spark.Ruby/Compiler/RubyViewCompiler.cs
@@ -12,18 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-using System;
+
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spark.Compiler;
-using Spark.Ruby.Compiler;
using Spark.Ruby.Compiler.ChunkVisitors;
using BaseClassVisitor = Spark.Compiler.CSharp.ChunkVisitors.BaseClassVisitor;
namespace Spark.Ruby.Compiler
{
- public class RubyViewCompiler : ViewCompiler
+ public class RubyViewCompiler(ISparkSettings settings) : ViewCompiler
{
public string ScriptHeader { get; set; }
@@ -31,8 +30,8 @@ public override void CompileView(IEnumerable> viewTemplates, IEnume
{
GenerateSourceCode(viewTemplates, allResources);
- var compiler = new BatchCompiler();
- var assembly = compiler.Compile(Debug, "csharp", SourceCode);
+ var compiler = new RoslynBatchCompiler(new SparkSettings());
+ var assembly = compiler.Compile(settings.Debug, "csharp", null, new[] { SourceCode }, settings.ExcludeAssemblies);
CompiledType = assembly.GetType(ViewClassFullName);
}
@@ -105,13 +104,13 @@ public override void GenerateSourceCode(IEnumerable> viewTemplates,
script.WriteLine("view.render");
- var baseClassGenerator = new BaseClassVisitor { BaseClass = BaseClass };
+ var baseClassGenerator = new BaseClassVisitor { BaseClass = settings.BaseClassTypeName };
foreach (var resource in allResources)
{
baseClassGenerator.Accept(resource);
}
- BaseClass = baseClassGenerator.BaseClassTypeName;
+ var baseClass = baseClassGenerator.BaseClassTypeName;
var source = new StringBuilder();
@@ -143,7 +142,7 @@ public override void GenerateSourceCode(IEnumerable> viewTemplates,
source.AppendLine(" })]");
}
- source.Append("public class ").Append(viewClassName).Append(" : ").Append(BaseClass).AppendLine(", global::Spark.Ruby.IScriptingSparkView");
+ source.Append("public class ").Append(viewClassName).Append(" : ").Append(baseClass).AppendLine(", global::Spark.Ruby.IScriptingSparkView");
source.AppendLine("{");
source.Append("static System.Guid _generatedViewId = new System.Guid(\"").Append(GeneratedViewId).AppendLine("\");");
diff --git a/src/Spark.Ruby/RubyLanguageFactory.cs b/src/Spark.Ruby/RubyLanguageFactory.cs
index c8b339b1..0978e701 100644
--- a/src/Spark.Ruby/RubyLanguageFactory.cs
+++ b/src/Spark.Ruby/RubyLanguageFactory.cs
@@ -18,9 +18,9 @@
namespace Spark.Ruby
{
- public class RubyLanguageFactory : DefaultLanguageFactory
+ public class RubyLanguageFactory(IBatchCompiler batchCompiler, ISparkSettings settings)
+ : DefaultLanguageFactory(batchCompiler, settings)
{
-
private RubyEngineManager _RubyEngineManager;
public RubyEngineManager RubyEngineManager
@@ -40,23 +40,14 @@ public override ViewCompiler CreateViewCompiler(ISparkViewEngine engine, SparkVi
{
case LanguageType.Default:
case LanguageType.Ruby:
- viewCompiler = new RubyViewCompiler();
+ viewCompiler = new RubyViewCompiler(settings);
break;
default:
return base.CreateViewCompiler(engine, descriptor);
}
- var pageBaseType = engine.Settings.PageBaseType;
- if (string.IsNullOrEmpty(pageBaseType))
- pageBaseType = engine.DefaultPageBaseType;
-
- viewCompiler.BaseClass = pageBaseType;
viewCompiler.Descriptor = descriptor;
- viewCompiler.Debug = engine.Settings.Debug;
- viewCompiler.NullBehaviour = engine.Settings.NullBehaviour;
- viewCompiler.UseAssemblies = engine.Settings.UseAssemblies;
- viewCompiler.UseNamespaces = engine.Settings.UseNamespaces;
-
+
return viewCompiler;
}
diff --git a/src/Spark.Ruby/Spark.Ruby.csproj b/src/Spark.Ruby/Spark.Ruby.csproj
index bcbee7e1..4fbb3834 100644
--- a/src/Spark.Ruby/Spark.Ruby.csproj
+++ b/src/Spark.Ruby/Spark.Ruby.csproj
@@ -1,6 +1,7 @@
net48
+ latestLibraryAllRules.rulesetFalse
diff --git a/src/Spark.Tests/CompiledViewHolderTester.cs b/src/Spark.Tests/CompiledViewHolderTester.cs
index 39b271dc..4361dac6 100644
--- a/src/Spark.Tests/CompiledViewHolderTester.cs
+++ b/src/Spark.Tests/CompiledViewHolderTester.cs
@@ -17,6 +17,9 @@
using Spark.Parser;
using NUnit.Framework;
using Rhino.Mocks;
+using Spark.Bindings;
+using Spark.FileSystem;
+using Spark.Parser.Syntax;
namespace Spark.Tests
{
@@ -51,7 +54,21 @@ public void LookupNonExistentReturnsNull()
public void LookupReturnsStoredInstance()
{
var key = BuildKey(Path.Combine("c", "v"), Path.Combine("shared", "m"));
- var entry = new CompiledViewEntry { Descriptor = key, Loader = new ViewLoader() };
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ MockRepository.GenerateMock(),
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
+
+ var entry = new CompiledViewEntry { Descriptor = key, Loader = viewLoader };
Assert.IsNull(holder.Lookup(key));
holder.Store(entry);
Assert.AreSame(entry, holder.Lookup(key));
@@ -77,24 +94,43 @@ public void VariousKeyEqualities()
Assert.That(!Equals(null, key1));
}
- bool isCurrent;
+ public class FakeViewLoader : ViewLoader
+ {
+ public FakeViewLoader() : base(null, null, null, null, null, null, null)
+ {
+ }
+
+ public bool IsCurrentValue { get; set; }
+
+ public override bool IsCurrent()
+ {
+ return IsCurrentValue;
+ }
+ }
[Test]
public void ExpiredEntryReturnsNull()
{
- var loader = MockRepository.GenerateMock();
-
- isCurrent = true;
- Func foo = () => isCurrent;
- loader.Stub(x => x.IsCurrent()).Do(foo);
+ var loader = new FakeViewLoader
+ {
+ IsCurrentValue = true
+ };
var key = BuildKey(Path.Combine("c", "v"), Path.Combine("shared", "m"));
- var entry = new CompiledViewEntry { Descriptor = key, Loader = loader };
+
+ var entry = new CompiledViewEntry
+ {
+ Descriptor = key,
+ Loader = loader
+ };
+
holder.Store(entry);
+
Assert.AreSame(entry, holder.Lookup(key));
- isCurrent = false;
- Assert.IsNull(holder.Lookup(key));
+ loader.IsCurrentValue = false;
+
+ Assert.IsNull(holder.Lookup(key));
}
[Test]
diff --git a/src/Spark.Tests/InMemoryServiceTest.cs b/src/Spark.Tests/InMemoryServiceTest.cs
new file mode 100644
index 00000000..8599b4dd
--- /dev/null
+++ b/src/Spark.Tests/InMemoryServiceTest.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Threading;
+using Microsoft.Extensions.Caching.Memory;
+using NUnit.Framework;
+
+namespace Spark.Tests
+{
+ [TestFixture]
+ public class InMemoryServiceTest
+ {
+ [Test]
+ public void TestStoreValueThenRetrieveIt()
+ {
+ var service = new InMemoryCacheService(new MemoryCache(new MemoryCacheOptions()));
+
+ var item = new { };
+
+ service.Store("identifier", CacheExpires.Empty, null, item);
+
+ var retrieved = service.Get("identifier");
+
+ Assert.AreSame(item, retrieved);
+ }
+
+ [Test]
+ public void TestStoreValueThenRetrieveItAfterAbsoluteExpiration()
+ {
+ var service = new InMemoryCacheService(new MemoryCache(new MemoryCacheOptions()));
+
+ var item = new { };
+
+ service.Store("identifier", new CacheExpires(DateTime.UtcNow.AddMilliseconds(50)), null, item);
+
+ Thread.Sleep(100);
+
+ var retrieved = service.Get("identifier");
+
+ Assert.IsNull(retrieved);
+ }
+
+ [Test]
+ public void TestStoreValueThenRetrieveItWhenExpirationSlides()
+ {
+ var service = new InMemoryCacheService(new MemoryCache(new MemoryCacheOptions()));
+
+ var item = new { };
+
+ service.Store("identifier", new CacheExpires(TimeSpan.FromMilliseconds(75)), null, item);
+
+ object retrieved;
+
+ for (var i = 0; i < 3; i++)
+ {
+ Thread.Sleep(50);
+
+ retrieved = service.Get("identifier");
+ }
+
+ retrieved = service.Get("identifier");
+
+ Assert.IsNotNull(retrieved);
+
+ Assert.AreSame(item, retrieved);
+ }
+
+ [Test]
+ public void TestStoreValueWithSignal()
+ {
+ var service = new InMemoryCacheService(new MemoryCache(new MemoryCacheOptions()));
+
+ var item = new { };
+
+ var signal = new CacheSignal();
+
+ service.Store("identifier", null, signal, item);
+
+ var retrieved = service.Get("identifier");
+
+ Assert.AreSame(item, retrieved);
+
+ signal.FireChanged();
+
+ retrieved = service.Get("identifier");
+
+ Assert.IsNull(retrieved);
+ }
+ }
+}
diff --git a/src/Spark.Tests/Parser/ViewLoaderTester.cs b/src/Spark.Tests/Parser/ViewLoaderTester.cs
index 1becdc8d..f0445afd 100644
--- a/src/Spark.Tests/Parser/ViewLoaderTester.cs
+++ b/src/Spark.Tests/Parser/ViewLoaderTester.cs
@@ -47,17 +47,36 @@ public void Init()
viewFolder.Stub(x => x.ListViews(Arg.Is.Anything)).IgnoreArguments().Return(Array.Empty());
syntaxProvider = MockRepository.GenerateMock();
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
- loader = new ViewLoader { ViewFolder = viewFolder, SyntaxProvider = syntaxProvider };
+ loader = new ViewLoader(settings, viewFolder, partialProvider, new DefaultPartialReferenceProvider(partialProvider), null, syntaxProvider, null);
}
+ private static int syntaxCallbacks = 0;
+
IViewFile ExpectGetChunks(string path, params Chunk[] chunks)
{
var source = MockRepository.GenerateMock();
- viewFolder.Expect(x => x.GetViewSource(path)).Return(source);
- source.Expect(x => x.LastModified).Return(0);
- syntaxProvider.Expect(x => x.GetChunks(Arg.Is.Anything, Arg.Is.Anything)).Return(chunks);
+ viewFolder
+ .Expect(x => x.GetViewSource(path))
+ .Return(source);
+
+ source
+ .Expect(x => x.LastModified)
+ .Return(0);
+
+ syntaxProvider
+ .Expect(x => x.GetChunks(Arg.Is.Anything, Arg.Is.Anything))
+ .WhenCalled(
+ call =>
+ {
+ syntaxCallbacks++;
+ })
+ .Return(chunks);
return source;
}
@@ -145,14 +164,21 @@ public void FileNotFoundException()
[Test]
public void ExpiresWhenFilesChange()
{
- var viewFolder = new StubViewFolder { Path = Path.Combine("home", "changing.spark"), LastModified = 4 };
+ var settings = new SparkSettings();
- var viewLoader = new ViewLoader
- {
- ViewFolder = viewFolder,
- SyntaxProvider = MockRepository.GenerateStub()
- };
- viewLoader.SyntaxProvider
+ var viewFolder = new StubViewFolder
+ {
+ Path = Path.Combine("home", "changing.spark"),
+ LastModified = 4
+ };
+
+ this.syntaxProvider = MockRepository.GenerateStub();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(settings, viewFolder, partialProvider, new DefaultPartialReferenceProvider(partialProvider), null, this.syntaxProvider, null);
+
+ this.syntaxProvider
.Expect(x => x.GetChunks(null, null))
.IgnoreArguments()
.Return(Array.Empty());
@@ -181,12 +207,13 @@ public void BindingProviderIsCalledUsingTheCorrectBindingRequest()
syntaxProvider.Stub(x => x.GetChunks(null, null))
.IgnoreArguments()
.Return(new List());
- var viewLoader = new ViewLoader
- {
- ViewFolder = folder,
- SyntaxProvider = syntaxProvider,
- BindingProvider = bindingProvider
- };
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(settings, folder, partialProvider, new DefaultPartialReferenceProvider(partialProvider), null, syntaxProvider, bindingProvider);
+
viewLoader.Load(viewPath);
bindingProvider.VerifyAllExpectations();
@@ -234,7 +261,20 @@ public void LoadingPartialInsideNamedSection()
{Path.Combine("home", "_Guts.spark"), "
"},
{Path.Combine("home", "_Another.spark"), "
hello world
"}
};
- var viewLoader = new ViewLoader { SyntaxProvider = new DefaultSyntaxProvider(ParserSettings.DefaultBehavior), ViewFolder = viewFolder };
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ viewFolder,
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
+
var chunks = viewLoader.Load(Path.Combine("home", "index.spark"));
var everything = viewLoader.GetEverythingLoaded();
@@ -254,7 +294,19 @@ public void PartialsInSameFolderAreDiscovered()
{Path.Combine("invoice", "five.spark"), ""},
};
- var viewLoader = new ViewLoader { ViewFolder = viewFolder };
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ viewFolder,
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
+
var zero = viewLoader.FindPartialFiles(Path.Combine("home", "zero.spark"));
var product = viewLoader.FindPartialFiles(Path.Combine("product", "two.spark"));
var invoice = viewLoader.FindPartialFiles(Path.Combine("invoice", "five.spark"));
@@ -299,7 +351,18 @@ public void PartialsInCascadingBaseFoldersAndSharedFoldersAreDiscovered()
{Path.Combine("area2","Shared","_dontfind3.spark"), ""},
};
- var viewLoader = new ViewLoader { ViewFolder = viewFolder };
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ viewFolder,
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
var partials = viewLoader.FindPartialFiles(Path.Combine("area1","controller2","view3.spark"));
@@ -321,7 +384,20 @@ public void LoadingEmptyFile()
{
{ Path.Combine("home", "empty.spark"), "" },
};
- var viewLoader = new ViewLoader { SyntaxProvider = new DefaultSyntaxProvider(ParserSettings.DefaultBehavior), ViewFolder = viewFolder };
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ viewFolder,
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
+
var chunks = viewLoader.Load(Path.Combine("home", "empty.spark"));
var everything = viewLoader.GetEverythingLoaded();
@@ -335,7 +411,20 @@ public void LoadingEmptyShadeFile()
{
{ Path.Combine("home", "empty.shade"), "" },
};
- var viewLoader = new ViewLoader { SyntaxProvider = new DefaultSyntaxProvider(ParserSettings.DefaultBehavior), ViewFolder = viewFolder };
+
+ var settings = new SparkSettings();
+
+ var partialProvider = new DefaultPartialProvider();
+
+ var viewLoader = new ViewLoader(
+ settings,
+ viewFolder,
+ new DefaultPartialProvider(),
+ new DefaultPartialReferenceProvider(partialProvider),
+ null,
+ new DefaultSyntaxProvider(ParserSettings.DefaultBehavior),
+ null);
+
var chunks = viewLoader.Load(Path.Combine("home", "empty.shade"));
var everything = viewLoader.GetEverythingLoaded();
diff --git a/src/Spark.Tests/Spark.Tests.csproj b/src/Spark.Tests/Spark.Tests.csproj
index 6c2549ee..045b38d3 100644
--- a/src/Spark.Tests/Spark.Tests.csproj
+++ b/src/Spark.Tests/Spark.Tests.csproj
@@ -15,7 +15,8 @@
-
+
+
diff --git a/src/Spark.Tests/SparkViewExtensions.cs b/src/Spark.Tests/SparkViewExtensions.cs
index 194a1a04..dfab0c8c 100644
--- a/src/Spark.Tests/SparkViewExtensions.cs
+++ b/src/Spark.Tests/SparkViewExtensions.cs
@@ -21,9 +21,10 @@ public static class SparkViewExtensions
public static string RenderView(this ISparkView view)
{
var writer = new StringWriter();
+
view.RenderView(writer);
+
return writer.ToString();
}
-
}
}
diff --git a/src/Spark.Web.Mvc.Pdf.Tests/PdfViewResultTests.cs b/src/Spark.Web.Mvc.Pdf.Tests/PdfViewResultTests.cs
index 674f8b0a..1bd653f2 100644
--- a/src/Spark.Web.Mvc.Pdf.Tests/PdfViewResultTests.cs
+++ b/src/Spark.Web.Mvc.Pdf.Tests/PdfViewResultTests.cs
@@ -2,9 +2,11 @@
using System.IO;
using System.Web.Mvc;
using System.Web.Routing;
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using Rhino.Mocks;
using Spark.FileSystem;
+using Spark.Web.Mvc.Extensions;
using Spark.Web.Mvc.Tests;
namespace Spark.Web.Mvc.Pdf.Tests
@@ -62,17 +64,20 @@ private static IViewEngine MockViewEngine(ControllerContext controllerContext, o
public void PdfResultShouldWriteToOutputStream()
{
var settings = new SparkSettings();
- var viewFolder = new InMemoryViewFolder
- {
- {
- "foo/bar.spark",
- HelloWorldXml
- }
- };
- var factory = new SparkViewFactory(settings)
- {
- ViewFolder = viewFolder
- };
+
+ var sp = new ServiceCollection()
+ .AddSpark(settings)
+ .AddSingleton(
+ new InMemoryViewFolder
+ {
+ {
+ "foo/bar.spark",
+ HelloWorldXml
+ }
+ })
+ .BuildServiceProvider();
+
+ var factory = sp.GetService();
var stream = new MemoryStream();
var controllerContext = GetControllerContext(stream);
diff --git a/src/Spark.Web.Mvc.Pdf.Tests/Spark.Web.Mvc.Pdf.Tests.csproj b/src/Spark.Web.Mvc.Pdf.Tests/Spark.Web.Mvc.Pdf.Tests.csproj
index 5adfdc1a..33f50209 100644
--- a/src/Spark.Web.Mvc.Pdf.Tests/Spark.Web.Mvc.Pdf.Tests.csproj
+++ b/src/Spark.Web.Mvc.Pdf.Tests/Spark.Web.Mvc.Pdf.Tests.csproj
@@ -13,6 +13,7 @@
+
diff --git a/src/Spark.Web.Mvc.Python/PythonLanguageFactoryWithExtensions.cs b/src/Spark.Web.Mvc.Python/PythonLanguageFactoryWithExtensions.cs
index 6013fa35..edfe64bc 100644
--- a/src/Spark.Web.Mvc.Python/PythonLanguageFactoryWithExtensions.cs
+++ b/src/Spark.Web.Mvc.Python/PythonLanguageFactoryWithExtensions.cs
@@ -31,6 +31,10 @@ namespace Spark.Web.Mvc.Python
{
public class PythonLanguageFactoryWithExtensions : PythonLanguageFactory
{
+ public PythonLanguageFactoryWithExtensions(IBatchCompiler batchCompiler, ISparkSettings settings) : base(batchCompiler, settings)
+ {
+ }
+
private bool _initialized;
public override ViewCompiler CreateViewCompiler(ISparkViewEngine engine, SparkViewDescriptor descriptor)
diff --git a/src/Spark.Web.Mvc.Python/ServiceCollectionExtensions.cs b/src/Spark.Web.Mvc.Python/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..a8bbba34
--- /dev/null
+++ b/src/Spark.Web.Mvc.Python/ServiceCollectionExtensions.cs
@@ -0,0 +1,25 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Spark.Web.Mvc.Extensions;
+
+namespace Spark.Web.Mvc.Python
+{
+ public static class ServiceCollectionExtensions
+ {
+ ///
+ /// Registers spark dependencies in the service collection.
+ ///
+ ///
+ ///
+ ///
+ public static IServiceCollection AddSparkPython(this IServiceCollection services, ISparkSettings settings = null)
+ {
+ services.AddSpark(settings);
+
+ // Override ISparkLanguageFactory
+ services.AddSingleton();
+
+ return services;
+ }
+ }
+}
diff --git a/src/Spark.Web.Mvc.Python/SparkPythonEngineStarter.cs b/src/Spark.Web.Mvc.Python/SparkPythonEngineStarter.cs
deleted file mode 100644
index 8f01db2a..00000000
--- a/src/Spark.Web.Mvc.Python/SparkPythonEngineStarter.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2008-2009 Louis DeJardin - http://whereslou.com
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System.Collections.Generic;
-using System.Web.Mvc;
-using Spark.Web.Mvc.Python;
-
-namespace Spark.Web.Mvc.Python
-{
- public static class SparkPythonEngineStarter
- {
- ///
- /// Adds Asp.Net Mvc specific IViewEngine implementation and the IronPython
- /// view language factory to a spark service container.
- ///
- /// An instance of the spark service container to modify
- public static void ConfigureContainer(ISparkServiceContainer container)
- {
- container.SetServiceBuilder(c => new SparkViewFactory(c.GetService()));
- container.SetServiceBuilder(c => new PythonLanguageFactoryWithExtensions());
- }
-
- ///
- /// Create an IronPython enabled Spark service container
- ///
- /// A configured service container. Additional service builders may
- /// me added.
- public static ISparkServiceContainer CreateContainer()
- {
- var container = new SparkServiceContainer();
- ConfigureContainer(container);
- return container;
- }
-
- ///
- /// Create an IronPython enabled service container with explicit spark settings.
- ///
- /// Typically an instance of SparkSettings object
- /// A configured service container. Additional service builders may
- /// me added. May be passed to RegisterViewEngine.
- public static ISparkServiceContainer CreateContainer(ISparkSettings settings)
- {
- var container = new SparkServiceContainer(settings);
- ConfigureContainer(container);
- return container;
- }
-
- ///
- /// Creates a spark IViewEngine with IronPython as the default language.
- /// Settings come from config or are defaulted.
- ///
- /// An IViewEngine interface of the SparkViewFactory
- public static IViewEngine CreateViewEngine()
- {
- return CreateContainer().GetService();
- }
-
- ///
- /// Creates a spark IViewEngine with IronPython as the default language.
- ///
- /// Typically an instance of SparkSettings object
- /// An IViewEngine interface of the SparkViewFactory
- public static IViewEngine CreateViewEngine(ISparkSettings settings)
- {
- return CreateContainer(settings).GetService();
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings come from config or are defaulted.
- ///
- public static void RegisterViewEngine()
- {
- ViewEngines.Engines.Add(CreateViewEngine());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings passed in.
- ///
- public static void RegisterViewEngine(ISparkSettings settings)
- {
- ViewEngines.Engines.Add(CreateViewEngine(settings));
- }
-
- ///
- /// Installs the Spark view engine. Service container passed in.
- ///
- public static void RegisterViewEngine(ISparkServiceContainer container)
- {
- ViewEngines.Engines.Add(container.GetService());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings come from config or are defaulted.
- ///
- /// Typically in the ViewEngines.Engines collection
- public static void RegisterViewEngine(ICollection engines)
- {
- engines.Add(CreateViewEngine());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings passed in.
- ///
- /// Typically in the ViewEngines.Engines collection
- /// Typically an instance of SparkSettings object
- public static void RegisterViewEngine(ICollection engines, ISparkSettings settings)
- {
- engines.Add(CreateViewEngine(settings));
- }
-
- ///
- /// Install the view engine from the container. Typical usage is to call CreateContainer,
- /// provide additinal service builder functors to override certain classes, then call this
- /// method.
- ///
- /// Typically the ViewEngines.Engines collection
- /// A service container, often created with CreateContainer
- public static void RegisterViewEngine(ICollection engines, ISparkServiceContainer container)
- {
- engines.Add(container.GetService());
- }
- }
-}
\ No newline at end of file
diff --git a/src/Spark.Web.Mvc.Ruby.Tests/HtmlHelperExtensionsTester.cs b/src/Spark.Web.Mvc.Ruby.Tests/HtmlHelperExtensionsTester.cs
index a0d7b6b0..971badaa 100644
--- a/src/Spark.Web.Mvc.Ruby.Tests/HtmlHelperExtensionsTester.cs
+++ b/src/Spark.Web.Mvc.Ruby.Tests/HtmlHelperExtensionsTester.cs
@@ -12,17 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-using System;
-using System.Collections.Generic;
+
using System.IO;
-using System.Linq;
-using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Mvc;
using System.Web.Routing;
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
+using Spark.Compiler;
using Spark.FileSystem;
+using Spark.Web.Mvc.Extensions;
namespace Spark.Web.Mvc.Ruby.Tests
{
@@ -41,7 +41,12 @@ public class StubController : Controller
[Test]
public void BuildingScriptHeader()
{
- var languageFactory = new RubyLanguageFactoryWithExtensions();
+ var settings = new SparkSettings();
+
+ var batchCompiler = new RoslynBatchCompiler(settings);
+
+ var languageFactory = new RubyLanguageFactoryWithExtensions(batchCompiler, settings);
+
var header = languageFactory.BuildScriptHeader(languageFactory.GetType().Assembly);
Assert.That(header.Contains("ActionLink"));
@@ -51,15 +56,18 @@ public void BuildingScriptHeader()
private static ViewContext CompileView(string viewContents)
{
- var settings = new SparkSettings();
- var container = SparkRubyEngineStarter.CreateContainer(settings);
+ var services = new ServiceCollection()
+ .AddSpark(new SparkSettings());
+
+ var viewFolder = new InMemoryViewFolder { { $"stub{Path.DirectorySeparatorChar}index.spark", viewContents } };
- var viewFolder = new InMemoryViewFolder { { string.Format("stub{0}index.spark", Path.DirectorySeparatorChar), viewContents } };
- container.SetServiceBuilder(c => viewFolder);
- var viewEngine = container.GetService();
+ services.AddSingleton(viewFolder);
- var httpContext = new StubHttpContext();
+ var serviceProvider = services.BuildServiceProvider();
+ var viewEngine = serviceProvider.GetService();
+
+ var httpContext = new StubHttpContext();
var routeData = new RouteData();
routeData.Values.Add("controller", "stub");
diff --git a/src/Spark.Web.Mvc.Ruby.Tests/Spark.Web.Mvc.Ruby.Tests.csproj b/src/Spark.Web.Mvc.Ruby.Tests/Spark.Web.Mvc.Ruby.Tests.csproj
index 23253f1a..ec9c043a 100644
--- a/src/Spark.Web.Mvc.Ruby.Tests/Spark.Web.Mvc.Ruby.Tests.csproj
+++ b/src/Spark.Web.Mvc.Ruby.Tests/Spark.Web.Mvc.Ruby.Tests.csproj
@@ -15,6 +15,7 @@
+
diff --git a/src/Spark.Web.Mvc.Ruby/RubyLanguageFactoryWithExtensions.cs b/src/Spark.Web.Mvc.Ruby/RubyLanguageFactoryWithExtensions.cs
index 56d5a388..45b85f81 100644
--- a/src/Spark.Web.Mvc.Ruby/RubyLanguageFactoryWithExtensions.cs
+++ b/src/Spark.Web.Mvc.Ruby/RubyLanguageFactoryWithExtensions.cs
@@ -39,7 +39,12 @@ namespace Spark.Web.Mvc.Ruby
{
public class RubyLanguageFactoryWithExtensions : RubyLanguageFactory
{
+ public RubyLanguageFactoryWithExtensions(IBatchCompiler batchCompiler, ISparkSettings settings) : base(batchCompiler, settings)
+ {
+ }
+
private bool _initialized;
+
private string _scriptHeader;
public override ViewCompiler CreateViewCompiler(ISparkViewEngine engine, SparkViewDescriptor descriptor)
diff --git a/src/Spark.Web.Mvc.Ruby/ServiceCollectionExtensions.cs b/src/Spark.Web.Mvc.Ruby/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..f746e85e
--- /dev/null
+++ b/src/Spark.Web.Mvc.Ruby/ServiceCollectionExtensions.cs
@@ -0,0 +1,25 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Spark.Web.Mvc.Extensions;
+
+namespace Spark.Web.Mvc.Ruby
+{
+ public static class ServiceCollectionExtensions
+ {
+ ///
+ /// Registers spark dependencies in the service collection.
+ ///
+ ///
+ ///
+ ///
+ public static IServiceCollection AddSparkRuby(this IServiceCollection services, ISparkSettings settings = null)
+ {
+ services.AddSpark(settings);
+
+ // Override ISparkLanguageFactory
+ services.AddSingleton();
+
+ return services;
+ }
+ }
+}
diff --git a/src/Spark.Web.Mvc.Ruby/SparkRubyEngineStarter.cs b/src/Spark.Web.Mvc.Ruby/SparkRubyEngineStarter.cs
deleted file mode 100644
index 2b9579b8..00000000
--- a/src/Spark.Web.Mvc.Ruby/SparkRubyEngineStarter.cs
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2008-2009 Louis DeJardin - http://whereslou.com
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-using System.Collections.Generic;
-using System.Web.Mvc;
-
-namespace Spark.Web.Mvc.Ruby
-{
- public static class SparkRubyEngineStarter
- {
- ///
- /// Adds Asp.Net Mvc specific IViewEngine implementation and the IronPython
- /// view language factory to a spark service container.
- ///
- /// An instance of the spark service container to modify
- public static void ConfigureContainer(ISparkServiceContainer container)
- {
- container.SetServiceBuilder(c => new SparkViewFactory(c.GetService()));
- container.SetServiceBuilder(c => new RubyLanguageFactoryWithExtensions());
- }
-
- ///
- /// Create an IronPython enabled Spark service container
- ///
- /// A configured service container. Additional service builders may
- /// me added.
- public static ISparkServiceContainer CreateContainer()
- {
- var container = new SparkServiceContainer();
- ConfigureContainer(container);
- return container;
- }
-
- ///
- /// Create an IronPython enabled service container with explicit spark settings.
- ///
- /// Typically an instance of SparkSettings object
- /// A configured service container. Additional service builders may
- /// me added. May be passed to RegisterViewEngine.
- public static ISparkServiceContainer CreateContainer(ISparkSettings settings)
- {
- var container = new SparkServiceContainer(settings);
- ConfigureContainer(container);
- return container;
- }
-
- ///
- /// Creates a spark IViewEngine with IronPython as the default language.
- /// Settings come from config or are defaulted.
- ///
- /// An IViewEngine interface of the SparkViewFactory
- public static IViewEngine CreateViewEngine()
- {
- return CreateContainer().GetService();
- }
-
- ///
- /// Creates a spark IViewEngine with IronPython as the default language.
- ///
- /// Typically an instance of SparkSettings object
- /// An IViewEngine interface of the SparkViewFactory
- public static IViewEngine CreateViewEngine(ISparkSettings settings)
- {
- return CreateContainer(settings).GetService();
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings come from config or are defaulted.
- ///
- public static void RegisterViewEngine()
- {
- ViewEngines.Engines.Add(CreateViewEngine());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings passed in.
- ///
- public static void RegisterViewEngine(ISparkSettings settings)
- {
- ViewEngines.Engines.Add(CreateViewEngine(settings));
- }
-
- ///
- /// Installs the Spark view engine. Service container passed in.
- ///
- public static void RegisterViewEngine(ISparkServiceContainer container)
- {
- ViewEngines.Engines.Add(container.GetService());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings come from config or are defaulted.
- ///
- /// Typically in the ViewEngines.Engines collection
- public static void RegisterViewEngine(ICollection engines)
- {
- engines.Add(CreateViewEngine());
- }
-
- ///
- /// Installs the Spark+IronPython view engine. Settings passed in.
- ///
- /// Typically in the ViewEngines.Engines collection
- /// Typically an instance of SparkSettings object
- public static void RegisterViewEngine(ICollection engines, ISparkSettings settings)
- {
- engines.Add(CreateViewEngine(settings));
- }
-
- ///
- /// Install the view engine from the container. Typical usage is to call CreateContainer,
- /// provide additinal service builder functors to override certain classes, then call this
- /// method.
- ///
- /// Typically the ViewEngines.Engines collection
- /// A service container, often created with CreateContainer
- public static void RegisterViewEngine(ICollection engines, ISparkServiceContainer container)
- {
- engines.Add(container.GetService());
- }
- }
-}
\ No newline at end of file
diff --git a/src/Spark.Web.Mvc.Tests/AspNetMvc.Tests.Views/Home/html-encode-function-h.spark b/src/Spark.Web.Mvc.Tests/AspNetMvc.Tests.Views/Home/html-encode-function-h.spark
deleted file mode 100644
index ba084f1e..00000000
--- a/src/Spark.Web.Mvc.Tests/AspNetMvc.Tests.Views/Home/html-encode-function-h.spark
+++ /dev/null
@@ -1,5 +0,0 @@
-
${H(SomeHtml().ToString())}
-
-
-
<>
-
diff --git a/src/Spark.Web.Tests/Compiler/CSharpViewCompilerTester.cs b/src/Spark.Web.Mvc.Tests/Compiler/CSharpViewCompilerTester.cs
similarity index 73%
rename from src/Spark.Web.Tests/Compiler/CSharpViewCompilerTester.cs
rename to src/Spark.Web.Mvc.Tests/Compiler/CSharpViewCompilerTester.cs
index 2c55bd45..bd38c81a 100644
--- a/src/Spark.Web.Tests/Compiler/CSharpViewCompilerTester.cs
+++ b/src/Spark.Web.Mvc.Tests/Compiler/CSharpViewCompilerTester.cs
@@ -19,16 +19,19 @@
using Spark.Tests;
using Spark.Tests.Models;
using Spark.Tests.Stubs;
+using Spark.Web.Mvc;
namespace Spark.Compiler
{
[TestFixture]
public class CSharpViewCompilerTester
{
+ private IBatchCompiler batchCompiler;
[SetUp]
public void Init()
{
+ this.batchCompiler = new RoslynBatchCompiler(new SparkSettings());
}
private static void DoCompileView(ViewCompiler compiler, IList chunks)
@@ -39,7 +42,8 @@ private static void DoCompileView(ViewCompiler compiler, IList chunks)
[Test]
public void MakeAndCompile()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new[] { new SendLiteralChunk { Text = "hello world" } });
@@ -53,8 +57,9 @@ public void MakeAndCompile()
[Test]
public void UnsafeLiteralCharacters()
{
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
var text = "hello\t\r\n\"world";
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new[] { new SendLiteralChunk { Text = text } });
Assert.That(compiler.SourceCode.Contains("Write(\"hello\\t\\r\\n\\\"world\")"));
@@ -68,7 +73,8 @@ public void UnsafeLiteralCharacters()
[Test]
public void SimpleOutput()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new[] { new SendExpressionChunk { Code = "3 + 4" } });
var instance = compiler.CreateInstance();
string contents = instance.RenderView();
@@ -79,7 +85,8 @@ public void SimpleOutput()
[Test]
public void LocalVariableDecl()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new LocalVariableChunk { Name = "i", Value = "5" },
@@ -94,7 +101,8 @@ public void LocalVariableDecl()
[Test]
public void ForEachLoop()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new LocalVariableChunk {Name = "data", Value = "new[]{3,4,5}"},
@@ -120,7 +128,8 @@ public void ForEachLoop()
[Test]
public void GlobalVariables()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new SendExpressionChunk{Code="title"},
@@ -139,11 +148,12 @@ public void GlobalVariables()
[Test]
public void TargetNamespace()
{
- var compiler = new CSharpViewCompiler
- {
- BaseClass = "Spark.SparkViewBase",
- Descriptor = new SparkViewDescriptor { TargetNamespace = "Testing.Target.Namespace" }
- };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings)
+ {
+ Descriptor = new SparkViewDescriptor { TargetNamespace = "Testing.Target.Namespace" }
+ };
+
DoCompileView(compiler, new Chunk[] { new SendLiteralChunk { Text = "Hello" } });
var instance = compiler.CreateInstance();
@@ -154,7 +164,8 @@ public void TargetNamespace()
[Test]
public void ProvideFullException()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
Assert.That(
() =>
@@ -164,13 +175,14 @@ public void ProvideFullException()
{
new SendExpressionChunk { Code = "NoSuchVariable" }
}),
- Throws.TypeOf());
+ Throws.TypeOf());
}
[Test]
public void IfTrueCondition()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -193,7 +205,8 @@ public void IfTrueCondition()
[Test]
public void IfFalseCondition()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -216,7 +229,8 @@ public void IfFalseCondition()
[Test]
public void IfElseFalseCondition()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
var falseChunks = new Chunk[] { new SendLiteralChunk { Text = "wasfalse" } };
@@ -241,7 +255,8 @@ public void IfElseFalseCondition()
[Test]
public void UnlessTrueCondition()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -264,7 +279,8 @@ public void UnlessTrueCondition()
[Test]
public void UnlessFalseCondition()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -287,11 +303,12 @@ public void UnlessFalseCondition()
[Test]
public void LenientSilentNullDoesNotCauseWarningCS0168()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Lenient
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Lenient
+ }.AddAssembly(typeof(Spark.Tests.Models.Comment).Assembly);
+
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var chunks = new Chunk[]
{
@@ -307,11 +324,12 @@ public void LenientSilentNullDoesNotCauseWarningCS0168()
[Test]
public void LenientOutputNullDoesNotCauseWarningCS0168()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Lenient
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Lenient
+ }.AddAssembly(typeof(Spark.Tests.Models.Comment).Assembly);
+
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var chunks = new Chunk[]
{
new ViewDataChunk { Name = "comment", Type = "Spark.Tests.Models.Comment" },
@@ -326,11 +344,11 @@ public void LenientOutputNullDoesNotCauseWarningCS0168()
[Test]
public void StrictNullUsesException()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
var chunks = new Chunk[]
{
@@ -348,11 +366,12 @@ public void StrictNullUsesException()
[Test]
public void PageBaseTypeOverridesBaseClass()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
+
DoCompileView(compiler, new Chunk[]
{
new PageBaseTypeChunk { BaseClass="Spark.Tests.Stubs.StubSparkView2"},
@@ -368,11 +387,11 @@ public void PageBaseTypeOverridesBaseClass()
[Test]
public void PageBaseTypeWorksWithOptionalModel()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
DoCompileView(
compiler,
@@ -392,11 +411,12 @@ public void PageBaseTypeWorksWithOptionalModel()
[Test]
public void PageBaseTypeWorksWithGenericParametersIncluded()
{
- var compiler = new CSharpViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
+
DoCompileView(compiler, new Chunk[]
{
new PageBaseTypeChunk {BaseClass = "Spark.Tests.Stubs.StubSparkView3"},
@@ -413,24 +433,25 @@ public void PageBaseTypeWorksWithGenericParametersIncluded()
[Test]
public void Markdown()
{
- var compiler = new CSharpViewCompiler { BaseClass = "Spark.SparkViewBase" };
+ var settings = new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName);
+ var compiler = new CSharpViewCompiler(this.batchCompiler, settings);
- var innerChunks = new Chunk[] { new SendLiteralChunk { Text = "*test*" } };
+ var innerChunks = new Chunk[] { new SendLiteralChunk { Text = "*test*" } };
- DoCompileView(
- compiler,
- new Chunk[]
- {
- new MarkdownChunk { Body = innerChunks }
- });
+ DoCompileView(
+ compiler,
+ new Chunk[]
+ {
+ new MarkdownChunk { Body = innerChunks }
+ });
- Assert.That(compiler.SourceCode, Does.Contain("using(MarkdownOutputScope())"));
- Assert.That(compiler.SourceCode, Does.Contain("Output.Write(\"*test*\");"));
+ Assert.That(compiler.SourceCode, Does.Contain("using(MarkdownOutputScope())"));
+ Assert.That(compiler.SourceCode, Does.Contain("Output.Write(\"*test*\");"));
- var instance = compiler.CreateInstance();
- var contents = instance.RenderView().Trim();
+ var instance = compiler.CreateInstance();
+ var contents = instance.RenderView().Trim();
- Assert.That(contents, Is.EqualTo("
test
"));
+ Assert.That(contents, Is.EqualTo("
test
"));
}
}
}
\ No newline at end of file
diff --git a/src/Spark.Web.Tests/Compiler/VisualBasicViewCompilerTester.cs b/src/Spark.Web.Mvc.Tests/Compiler/VisualBasicViewCompilerTester.cs
similarity index 81%
rename from src/Spark.Web.Tests/Compiler/VisualBasicViewCompilerTester.cs
rename to src/Spark.Web.Mvc.Tests/Compiler/VisualBasicViewCompilerTester.cs
index 7b567a00..e111632d 100644
--- a/src/Spark.Web.Tests/Compiler/VisualBasicViewCompilerTester.cs
+++ b/src/Spark.Web.Mvc.Tests/Compiler/VisualBasicViewCompilerTester.cs
@@ -20,16 +20,20 @@
using Spark.Tests;
using Spark.Tests.Models;
using Spark.Tests.Stubs;
+using Spark.Web.Mvc;
namespace Spark.Compiler
{
[TestFixture]
public class VisualBasicViewCompilerTester
{
+ private IBatchCompiler batchCompiler;
[SetUp]
public void Init()
{
+ this.batchCompiler =
+ new RoslynBatchCompiler(new SparkSettings());
}
private static void DoCompileView(ViewCompiler compiler, IList chunks)
@@ -53,7 +57,8 @@ public void MakeAndCompile()
[Test]
public void StronglyTypedBase()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.Tests.Stubs.StubSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
@@ -82,23 +87,26 @@ public void UnsafeLiteralCharacters()
Assert.That(contents, Is.EqualTo(text));
}
- private static VisualBasicViewCompiler CreateCompiler()
+ private VisualBasicViewCompiler CreateCompiler(ISparkSettings settings = null)
{
- return new VisualBasicViewCompiler
+ if (settings == null)
{
- BaseClass = "Spark.AbstractSparkView",
- UseAssemblies = new[] { "Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" },
- UseNamespaces = new[] { "Microsoft.VisualBasic" }
- };
+ settings = new SparkSettings()
+ .AddAssembly("Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
+ .AddNamespace("Microsoft.VisualBasic");
+ }
+
+ return new VisualBasicViewCompiler(this.batchCompiler, settings);
}
[Test]
public void SimpleOutput()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new[] { new SendExpressionChunk { Code = "3 + 4" } });
var instance = compiler.CreateInstance();
- string contents = instance.RenderView();
+ var contents = instance.RenderView();
Assert.AreEqual("7", contents);
}
@@ -130,9 +138,13 @@ public void SilentNullBehavior()
[Test]
public void RethrowNullBehavior()
{
- var compiler = CreateCompiler();
- compiler.NullBehaviour = NullBehaviour.Strict;
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = CreateCompiler(settings);
+
DoCompileView(compiler, new[] { new SendExpressionChunk { Code = "CType(Nothing, String).Length" } });
var instance = compiler.CreateInstance();
@@ -142,7 +154,9 @@ public void RethrowNullBehavior()
[Test]
public void LocalVariableDecl()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new LocalVariableChunk { Name = "i", Value = "5" },
@@ -157,7 +171,8 @@ public void LocalVariableDecl()
[Test]
public void ForEachLoop()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new LocalVariableChunk {Name = "data", Value = "new Integer(){3,4,5}"},
@@ -183,7 +198,8 @@ public void ForEachLoop()
[Test]
public void ForEachAutoVariables()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new LocalVariableChunk {Name = "data", Value = "new Integer(){3,4,5}"},
@@ -213,7 +229,8 @@ public void ForEachAutoVariables()
[Test]
public void GlobalVariables()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new SendExpressionChunk{Code="title"},
@@ -233,9 +250,9 @@ public void GlobalVariables()
[Platform(Exclude = "Mono", Reason = "Problems with Mono-2.10+/Linux and the VB compiler prevent this from running.")]
public void TargetNamespace()
{
- var compiler = new VisualBasicViewCompiler
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings)
{
- BaseClass = "Spark.AbstractSparkView",
Descriptor = new SparkViewDescriptor { TargetNamespace = "Testing.Target.Namespace" }
};
@@ -248,19 +265,22 @@ public void TargetNamespace()
[Test]
public void ProvideFullException()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
+
Assert.That(() =>
DoCompileView(compiler, new Chunk[]
{
new SendExpressionChunk {Code = "NoSuchVariable"}
}),
- Throws.TypeOf());
+ Throws.TypeOf().Or.TypeOf());
}
[Test]
public void IfTrueCondition()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -280,7 +300,8 @@ public void IfTrueCondition()
[Test]
public void IfFalseCondition()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -300,7 +321,8 @@ public void IfFalseCondition()
[Test]
public void IfElseFalseCondition()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
var falseChunks = new Chunk[] { new SendLiteralChunk { Text = "wasfalse" } };
@@ -322,7 +344,8 @@ public void IfElseFalseCondition()
[Test]
public void UnlessTrueCondition()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -342,7 +365,8 @@ public void UnlessTrueCondition()
[Test]
public void UnlessFalseCondition()
{
- var compiler = new VisualBasicViewCompiler { BaseClass = "Spark.AbstractSparkView" };
+ var settings = new SparkSettings();
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var trueChunks = new Chunk[] { new SendLiteralChunk { Text = "wastrue" } };
@@ -362,11 +386,11 @@ public void UnlessFalseCondition()
[Test]
public void StrictNullUsesException()
{
- var compiler = new VisualBasicViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
var chunks = new Chunk[]
{
new ViewDataChunk { Name="comment", Type="Spark.Tests.Models.Comment"},
@@ -382,11 +406,11 @@ public void StrictNullUsesException()
[Test]
public void PageBaseTypeOverridesBaseClass()
{
- var compiler = new VisualBasicViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new PageBaseTypeChunk { BaseClass="Spark.Tests.Stubs.StubSparkView2"},
@@ -401,11 +425,11 @@ public void PageBaseTypeOverridesBaseClass()
[Test]
public void PageBaseTypeWorksWithOptionalModel()
{
- var compiler = new VisualBasicViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new PageBaseTypeChunk {BaseClass = "Spark.Tests.Stubs.StubSparkView2"},
@@ -421,11 +445,11 @@ public void PageBaseTypeWorksWithOptionalModel()
[Test]
public void PageBaseTypeWorksWithGenericParametersIncluded()
{
- var compiler = new VisualBasicViewCompiler()
- {
- BaseClass = "Spark.Tests.Stubs.StubSparkView",
- NullBehaviour = NullBehaviour.Strict
- };
+ var settings = new SparkSettings
+ {
+ NullBehaviour = NullBehaviour.Strict
+ };
+ var compiler = new VisualBasicViewCompiler(this.batchCompiler, settings);
DoCompileView(compiler, new Chunk[]
{
new PageBaseTypeChunk {BaseClass = "Spark.Tests.Stubs.StubSparkView3(Of Spark.Tests.Models.Comment, string)"},
diff --git a/src/Spark.Web.Mvc.Tests/DescriptorBuildingTester.cs b/src/Spark.Web.Mvc.Tests/DescriptorBuildingTester.cs
index 088da660..916042b7 100644
--- a/src/Spark.Web.Mvc.Tests/DescriptorBuildingTester.cs
+++ b/src/Spark.Web.Mvc.Tests/DescriptorBuildingTester.cs
@@ -16,34 +16,59 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text;
using System.Web;
using System.Web.Mvc;
-using System.Web.Routing;
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using Rhino.Mocks;
+using Spark.Descriptors;
using Spark.FileSystem;
using Spark.Parser;
using Spark.Web.Mvc.Descriptors;
+using Spark.Web.Mvc.Extensions;
+using RouteData = System.Web.Routing.RouteData;
namespace Spark.Web.Mvc.Tests
{
[TestFixture]
public class DescriptorBuildingTester
{
- private SparkViewFactory _factory;
+ private SparkWebPrecompiler _precompiler;
private InMemoryViewFolder _viewFolder;
private RouteData _routeData;
private ControllerContext _controllerContext;
+ public static IServiceProvider SetupServiceProvider(ISparkSettings settings, Action serviceOverrides = null)
+ {
+ IServiceCollection services = new ServiceCollection()
+ .AddSpark(settings);
+
+ if (serviceOverrides != null)
+ {
+ serviceOverrides.Invoke(services);
+ }
+
+ return services.BuildServiceProvider();
+ }
+
[SetUp]
public void Init()
{
- _factory = new SparkViewFactory();
+ var settings = new SparkSettings();
+
_viewFolder = new InMemoryViewFolder();
- _factory.ViewFolder = _viewFolder;
+ var sp = SetupServiceProvider(
+ settings,
+ services =>
+ {
+ services.AddSingleton(this._viewFolder);
+ services.AddSingleton();
+ });
+
+ this._precompiler = sp.GetService();
+
var httpContext = MockRepository.GenerateStub();
_routeData = new RouteData();
var controller = MockRepository.GenerateStub();
@@ -72,7 +97,7 @@ public void NormalViewAndNoDefaultLayout()
_viewFolder.Add(@"Home\Index.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -87,7 +112,7 @@ public void NormalViewAndNoDefaultLayoutWithShade()
_viewFolder.Add(@"Home\Index.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -103,7 +128,7 @@ public void NormalViewAndDefaultLayoutPresent()
_viewFolder.Add(@"Layouts\Application.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -120,7 +145,7 @@ public void NormalViewAndDefaultLayoutPresentWithShade()
_viewFolder.Add(@"Layouts\Application.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -138,7 +163,7 @@ public void NormalViewAndControllerLayoutOverrides()
_viewFolder.Add(@"Layouts\Home.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -156,7 +181,7 @@ public void NormalViewAndControllerLayoutOverridesWithShade()
_viewFolder.Add(@"Layouts\Home.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -175,7 +200,7 @@ public void NormalViewAndNamedMaster()
_viewFolder.Add(@"Layouts\Site.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -194,7 +219,7 @@ public void NormalViewAndNamedMasterWithShade()
_viewFolder.Add(@"Layouts\Site.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -214,7 +239,7 @@ public void PartialViewIgnoresDefaultLayouts()
_viewFolder.Add(@"Shared\Home.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -233,7 +258,7 @@ public void PartialViewIgnoresDefaultLayoutsWithShade()
_viewFolder.Add(@"Shared\Home.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -244,13 +269,13 @@ public void PartialViewIgnoresDefaultLayoutsWithShade()
[Test]
public void RouteAreaPresentDefaultsToNormalLocation()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.spark", "");
_viewFolder.Add(@"Layouts\Application.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -262,13 +287,13 @@ public void RouteAreaPresentDefaultsToNormalLocation()
[Test]
public void RouteAreaPresentDefaultsToNormalLocationWithShade()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.shade", "");
_viewFolder.Add(@"Layouts\Application.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -280,14 +305,14 @@ public void RouteAreaPresentDefaultsToNormalLocationWithShade()
[Test]
public void AreaFolderMayContainControllerFolder()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.spark", "");
_viewFolder.Add(@"Layouts\Application.spark", "");
_viewFolder.Add(@"Admin\Home\Index.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -299,14 +324,14 @@ public void AreaFolderMayContainControllerFolder()
[Test]
public void AreaFolderMayContainControllerFolderWithShade()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.shade", "");
_viewFolder.Add(@"Layouts\Application.shade", "");
_viewFolder.Add(@"Admin\Home\Index.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -324,7 +349,7 @@ public void AreaRouteValueAlsoRecognizedForBackCompatWithEarlierAssumptions() {
_viewFolder.Add(@"Admin\Home\Index.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -342,7 +367,7 @@ public void AreaRouteValueAlsoRecognizedForBackCompatWithEarlierAssumptionsWithS
_viewFolder.Add(@"Admin\Home\Index.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -354,7 +379,7 @@ public void AreaRouteValueAlsoRecognizedForBackCompatWithEarlierAssumptionsWithS
[Test]
public void AreaFolderMayContainLayoutsFolder()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.spark", "");
_viewFolder.Add(@"Layouts\Application.spark", "");
@@ -362,7 +387,7 @@ public void AreaFolderMayContainLayoutsFolder()
_viewFolder.Add(@"Admin\Layouts\Application.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -374,7 +399,7 @@ public void AreaFolderMayContainLayoutsFolder()
[Test]
public void AreaFolderMayContainLayoutsFolderWithShade()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.shade", "");
_viewFolder.Add(@"Layouts\Application.shade", "");
@@ -382,7 +407,7 @@ public void AreaFolderMayContainLayoutsFolderWithShade()
_viewFolder.Add(@"Admin\Layouts\Application.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -394,7 +419,7 @@ public void AreaFolderMayContainLayoutsFolderWithShade()
[Test]
public void AreaContainsNamedLayout()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.spark", "");
_viewFolder.Add(@"Layouts\Application.spark", "");
@@ -403,7 +428,7 @@ public void AreaContainsNamedLayout()
_viewFolder.Add(@"Admin\Layouts\Site.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -415,7 +440,7 @@ public void AreaContainsNamedLayout()
[Test]
public void AreaContainsNamedLayoutWithShade()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.shade", "");
_viewFolder.Add(@"Layouts\Application.shade", "");
@@ -424,7 +449,7 @@ public void AreaContainsNamedLayoutWithShade()
_viewFolder.Add(@"Admin\Layouts\Site.shade", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", "Site", true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -436,7 +461,7 @@ public void AreaContainsNamedLayoutWithShade()
[Test]
public void PartialViewFromAreaIgnoresLayout()
{
- _routeData.DataTokens.Add("area", "Admin");
+ _routeData.Values.Add("area", "Admin");
_routeData.Values.Add("controller", "Home");
_viewFolder.Add(@"Home\Index.spark", "");
_viewFolder.Add(@"Admin\Home\Index.spark", "");
@@ -447,7 +472,7 @@ public void PartialViewFromAreaIgnoresLayout()
_viewFolder.Add(@"Admin\Layouts\Site.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -467,7 +492,7 @@ public void UseMasterCreatesTemplateChain()
_viewFolder.Add(@"Layouts\Home.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -490,7 +515,7 @@ public void NamedMasterOverridesViewMaster()
_viewFolder.Add(@"Layouts\Home.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", "Red", true, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", "Red", true, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -512,7 +537,7 @@ public void PartialViewIgnoresUseMasterAndDefault()
_viewFolder.Add(@"Layouts\Home.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
+ var result = this._precompiler.CreateDescriptor(_controllerContext, "Index", null, false, searchedLocations);
AssertDescriptorTemplates(
result,
@@ -573,7 +598,17 @@ private static IDictionary Dict(IEnumerable values)
[Test]
public void CustomParameterAddedToViewSearchPath()
{
- _factory.DescriptorBuilder = new ExtendingDescriptorBuilderWithInheritance(_factory.Engine);
+ var settings = new SparkSettings();
+
+ var sp = SetupServiceProvider(settings,
+ s =>
+ {
+ s.AddSingleton(this._viewFolder);
+ s.AddSingleton();
+ });
+
+ var factory = sp.GetService();
+
_routeData.Values.Add("controller", "Home");
_routeData.Values.Add("language", "en-us");
_viewFolder.Add(@"Home\Index.en-us.spark", "");
@@ -584,7 +619,8 @@ public void CustomParameterAddedToViewSearchPath()
_viewFolder.Add(@"Layouts\Application.spark", "");
var searchedLocations = new List();
- var result = _factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+ var result = factory.CreateDescriptor(_controllerContext, "Index", null, true, searchedLocations);
+
AssertDescriptorTemplates(
result,
searchedLocations,
@@ -592,22 +628,18 @@ public void CustomParameterAddedToViewSearchPath()
@"Layouts\Application.en.spark");
}
- public class ExtendingDescriptorBuilderWithInheritance : DefaultDescriptorBuilder
+ public class ExtendingDescriptorBuilderWithInheritance : DescriptorBuilder
{
- public ExtendingDescriptorBuilderWithInheritance()
+ public ExtendingDescriptorBuilderWithInheritance(ISparkSettings settings, IViewFolder viewFolder)
+ : base(settings, viewFolder)
{
}
- public ExtendingDescriptorBuilderWithInheritance(ISparkViewEngine engine)
- : base(engine)
- {
- }
-
- public override IDictionary GetExtraParameters(ControllerContext controllerContext)
+ public override IDictionary GetExtraParameters(SparkRouteData routeData)
{
return new Dictionary
{
- { "language", Convert.ToString(controllerContext.RouteData.Values["language"]) }
+ { "language", Convert.ToString(routeData.Values["language"]) }
};
}
@@ -649,16 +681,33 @@ static IEnumerable Merge(IEnumerable locations, string region)
[Test]
public void CustomDescriptorBuildersCantUseDescriptorFilters()
{
- _factory.DescriptorBuilder = MockRepository.GenerateStub();
- Assert.That(() =>
- _factory.AddFilter(MockRepository.GenerateStub()),
- Throws.TypeOf());
+ var settings = new SparkSettings();
+
+ var descriptorBuilders = MockRepository.GenerateStub();
+
+ var factory = new SparkViewFactory(
+ settings,
+ null,
+ descriptorBuilders,
+ null,
+ null,
+ new SparkWebPrecompiler(null, descriptorBuilders));
+
+ Assert.That(
+ () =>
+ factory.AddFilter(MockRepository.GenerateStub()),
+ Throws.TypeOf());
}
[Test]
public void SimplifiedUseMasterGrammarDetectsElementCorrectly()
{
- var builder = new DefaultDescriptorBuilder();
+ var settings = new SparkSettings
+ {
+ Prefix = null
+ };
+
+ var builder = new DescriptorBuilder(settings, null);
var a = builder.ParseUseMaster(new Position(new SourceContext("")));
var b = builder.ParseUseMaster(new Position(new SourceContext("")));
@@ -678,7 +727,12 @@ public void SimplifiedUseMasterGrammarDetectsElementCorrectly()
[Test]
public void SimplifiedUseMasterGrammarWithPrefixDetectsElementCorrectly()
{
- var builder = new DefaultDescriptorBuilder("s");
+ var settings = new SparkSettings
+ {
+ Prefix = "s"
+ };
+
+ var builder = new DescriptorBuilder(settings, null);
var a = builder.ParseUseMaster(new Position(new SourceContext("")));
var b = builder.ParseUseMaster(new Position(new SourceContext("")));
diff --git a/src/Spark.Web.Mvc.Tests/DescriptorFilterTester.cs b/src/Spark.Web.Mvc.Tests/DescriptorFilterTester.cs
index ee11ab35..c6407f00 100644
--- a/src/Spark.Web.Mvc.Tests/DescriptorFilterTester.cs
+++ b/src/Spark.Web.Mvc.Tests/DescriptorFilterTester.cs
@@ -4,9 +4,8 @@
using System.Web.Mvc;
using System.Web.Routing;
using NUnit.Framework;
-
using Rhino.Mocks;
-using Spark.Web.Mvc.Descriptors;
+using Spark.Descriptors;
namespace Spark.Web.Mvc.Tests
{
@@ -32,8 +31,8 @@ public void AreaFilterUsesRouteDataTokensByDefault()
{
var filter = new AreaDescriptorFilter();
- _context.RouteData.DataTokens.Add("area", "foo");
- filter.ExtraParameters(_context, _extra);
+ _context.RouteData.Values.Add("area", "foo");
+ filter.ExtraParameters(new SparkRouteData(_context.RouteData.Values), _extra);
Assert.That(_extra["area"], Is.EqualTo("foo"));
}
@@ -44,7 +43,7 @@ public void AreaFilterUsesRouteValuesForBackCompat() {
var filter = new AreaDescriptorFilter();
_context.RouteData.Values.Add("area", "foo");
- filter.ExtraParameters(_context, _extra);
+ filter.ExtraParameters(new SparkRouteData(_context.RouteData.Values), _extra);
Assert.That(_extra["area"], Is.EqualTo("foo"));
}
@@ -76,7 +75,7 @@ public void AreaFilterAddsNameToStartOfPath()
public void ThemeFilterDelegateCanExtractParameter()
{
var filter = ThemeDescriptorFilter.For(context => "foo");
- filter.ExtraParameters(_context, _extra);
+ filter.ExtraParameters(new SparkRouteData(_context.RouteData.Values), _extra);
Assert.That(_extra["theme"], Is.EqualTo("foo"));
}
@@ -107,7 +106,7 @@ public void ThemeFilterAddsThemesAndNameToPath()
public void LanguageFilterDelegateCanExtractParameter()
{
var filter = LanguageDescriptorFilter.For(context => "foo");
- filter.ExtraParameters(_context, _extra);
+ filter.ExtraParameters(new SparkRouteData(_context.RouteData.Values), _extra);
Assert.That(_extra["language"], Is.EqualTo("foo"));
}
diff --git a/src/Spark.Web.Mvc.Tests/Spark.Web.Mvc.Tests.csproj b/src/Spark.Web.Mvc.Tests/Spark.Web.Mvc.Tests.csproj
index 5671e1c3..2b91d1c8 100644
--- a/src/Spark.Web.Mvc.Tests/Spark.Web.Mvc.Tests.csproj
+++ b/src/Spark.Web.Mvc.Tests/Spark.Web.Mvc.Tests.csproj
@@ -11,12 +11,14 @@
-
+
+
+
@@ -76,9 +78,6 @@
Always
-
- Always
- Always
diff --git a/src/Spark.Web.Mvc.Tests/SparkBatchCompilerTester.cs b/src/Spark.Web.Mvc.Tests/SparkBatchCompilerTester.cs
index 6052f04e..6981f5e1 100644
--- a/src/Spark.Web.Mvc.Tests/SparkBatchCompilerTester.cs
+++ b/src/Spark.Web.Mvc.Tests/SparkBatchCompilerTester.cs
@@ -17,28 +17,52 @@
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
+using Spark.Compiler;
using Spark.FileSystem;
+using Spark.Web.Mvc.Extensions;
using Spark.Web.Mvc.Tests.Controllers;
namespace Spark.Web.Mvc.Tests
{
[TestFixture]
- public class SparkBatchCompilerTester
+ public class SparkPrecompilerTester
{
#region Setup/Teardown
+ public static IServiceProvider SetupServiceProvider(Action serviceOverrides = null)
+ {
+ var services = new ServiceCollection();
+
+ services.AddSpark(new SparkSettings().SetBaseClassTypeName(typeof(SparkView).FullName));
+
+ if (serviceOverrides != null)
+ {
+ serviceOverrides.Invoke(services);
+ }
+
+ services.AddSingleton();
+
+ return services.BuildServiceProvider();
+ }
+
[SetUp]
public void Init()
{
- var settings = new SparkSettings();
+ var serviceProvider = SetupServiceProvider(
+ s =>
+ {
+ s.AddSingleton(new FileSystemViewFolder("AspNetMvc.Tests.Views"));
+ s.AddSingleton();
+ });
- _factory = new SparkViewFactory(settings) { ViewFolder = new FileSystemViewFolder("AspNetMvc.Tests.Views") };
+ this._precompiler = serviceProvider.GetService();
}
#endregion
- private SparkViewFactory _factory;
+ private SparkPrecompiler _precompiler;
[Test]
public void CompileBatchDescriptor()
@@ -49,10 +73,10 @@ public void CompileBatchDescriptor()
.For().Layout("layout").Include("Index").Include("List.spark")
.For().Layout("ajax").Include("_Widget");
- var assembly = _factory.Precompile(batch);
+ var assembly = this._precompiler.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(3, assembly.GetTypes().Length);
+ Assert.AreEqual(3, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
@@ -67,8 +91,11 @@ public void CanHandleCSharpV3SyntaxWhenLoadedInAppDomainWithoutConfig()
try
{
sandbox = AppDomain.CreateDomain("sandbox", null, appDomainSetup);
- var remoteRunner = (PrecompileRunner) sandbox.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName,
- typeof(PrecompileRunner).FullName);
+
+ var remoteRunner = (PrecompileRunner)sandbox.CreateInstanceAndUnwrap(
+ Assembly.GetExecutingAssembly().FullName,
+ typeof(PrecompileRunner).FullName);
+
remoteRunner.Precompile();
}
finally
@@ -84,9 +111,16 @@ public class PrecompileRunner : MarshalByRefObject
{
public void Precompile()
{
- var settings = new SparkSettings();
+ var serviceProvider = SetupServiceProvider(
+ s =>
+ {
+ // Don't know why but the roslin compiler complains
+ // in CanHandleCSharpV3SyntaxWhenLoadedInAppDomainWithoutConfig test
+ s.AddSingleton();
+ s.AddSingleton(new FileSystemViewFolder("AspNetMvc.Tests.Views"));
+ });
- var factory = new SparkViewFactory(settings) { ViewFolder = new FileSystemViewFolder("AspNetMvc.Tests.Views") };
+ var factory = serviceProvider.GetService();
var batch = new SparkBatchDescriptor();
@@ -103,7 +137,7 @@ public void DefaultMatchingRules()
batch.For();
- var descriptors = _factory.CreateDescriptors(batch);
+ var descriptors = this._precompiler.CreateDescriptors(batch);
Assert.AreEqual(2, descriptors.Count);
Assert.AreEqual(1, descriptors[0].Templates.Count);
@@ -119,7 +153,7 @@ public void ExcludeRules()
batch.For().Include("*").Include("_*").Exclude("In*");
- var descriptors = _factory.CreateDescriptors(batch);
+ var descriptors = this._precompiler.CreateDescriptors(batch);
Assert.AreEqual(2, descriptors.Count);
Assert.AreEqual(1, descriptors[0].Templates.Count);
@@ -140,10 +174,10 @@ public void MultipleLayoutFiles()
.Include("Index")
.Include("List.spark");
- var assembly = _factory.Precompile(batch);
+ var assembly = this._precompiler.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(4, assembly.GetTypes().Length);
+ Assert.AreEqual(4, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
@@ -155,7 +189,7 @@ public void WildcardIncludeRules()
.For().Layout("layout").Include("*")
.For().Layout("ajax").Include("_*");
- var descriptors = _factory.CreateDescriptors(batch);
+ var descriptors = this._precompiler.CreateDescriptors(batch);
Assert.AreEqual(3, descriptors.Count);
Assert.That(
descriptors.Any(
@@ -167,10 +201,10 @@ public void WildcardIncludeRules()
descriptors.Any(
d => d.Templates.Contains(string.Format("Stub{0}_Widget.spark", Path.DirectorySeparatorChar)) && d.Templates.Contains(string.Format("Shared{0}ajax.spark", Path.DirectorySeparatorChar))));
- var assembly = _factory.Precompile(batch);
+ var assembly = this._precompiler.Precompile(batch);
Assert.IsNotNull(assembly);
- Assert.AreEqual(3, assembly.GetTypes().Length);
+ Assert.AreEqual(3, assembly.GetTypes().Count(x => x.BaseType == typeof(SparkView)));
}
[Test]
@@ -182,10 +216,19 @@ public void FileWithoutSparkExtensionAreIgnored()
{ string.Format("Stub{0}Helper.cs", Path.DirectorySeparatorChar), "// this is a code file" },
{ string.Format("Layouts{0}Stub.spark", Path.DirectorySeparatorChar), "
layout
" },
};
+
+ var sp = SetupServiceProvider(
+ s =>
+ {
+ s.AddSingleton(viewFolder);
+ });
+
+ this._precompiler = sp.GetService();
+
var batch = new SparkBatchDescriptor();
batch.For();
- var descriptors = _factory.CreateDescriptors(batch);
+ var descriptors = this._precompiler.CreateDescriptors(batch);
Assert.AreEqual(1, descriptors.Count);
Assert.AreEqual(2, descriptors[0].Templates.Count);
diff --git a/src/Spark.Web.Mvc.Tests/SparkViewFactoryTester.cs b/src/Spark.Web.Mvc.Tests/SparkViewFactoryTester.cs
index 80e2e0af..efdc880d 100644
--- a/src/Spark.Web.Mvc.Tests/SparkViewFactoryTester.cs
+++ b/src/Spark.Web.Mvc.Tests/SparkViewFactoryTester.cs
@@ -21,11 +21,15 @@
using System.Web.Mvc.Html;
using System.Web.Routing;
using System.Web.SessionState;
+using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework;
using Rhino.Mocks;
+using Spark.Descriptors;
using Spark.FileSystem;
+using Spark.Web.Mvc.Extensions;
using Spark.Web.Mvc.Tests.Controllers;
using Spark.Web.Mvc.Tests.Models;
+using RouteData = System.Web.Routing.RouteData;
namespace Spark.Web.Mvc.Tests
{
@@ -34,6 +38,20 @@ public class SparkViewFactoryTester
{
#region Setup/Teardown
+ public static IServiceProvider SetupServiceProvider(ISparkSettings settings, Action serviceOverrides = null)
+ {
+ var services = new ServiceCollection();
+
+ services.AddSpark(settings);
+
+ if (serviceOverrides != null)
+ {
+ serviceOverrides.Invoke(services);
+ }
+
+ return services.BuildServiceProvider();
+ }
+
[SetUp]
public void Init()
{
@@ -78,8 +96,17 @@ public void Init()
controllerContext = new ControllerContext(httpContext, routeData, controller);
- var settings = new SparkSettings().AddNamespace("System.Web.Mvc.Html").SetAutomaticEncoding(true);
- factory = new SparkViewFactory(settings) { ViewFolder = new FileSystemViewFolder("AspNetMvc.Tests.Views") };
+ var settings = new SparkSettings().AddNamespace("System.Web.Mvc.Html")
+ .SetAutomaticEncoding(true);
+
+ var serviceProvider = SetupServiceProvider(
+ settings,
+ s =>
+ {
+ s.AddSingleton(new FileSystemViewFolder("AspNetMvc.Tests.Views"));
+ });
+
+ factory = serviceProvider.GetService();
ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory());
@@ -150,7 +177,8 @@ private static void ContainsInOrder(string content, params string[] values)
foreach (var value in values)
{
var nextIndex = content.IndexOf(value, index);
- Assert.GreaterOrEqual(nextIndex, 0, string.Format("Looking for {0}", value));
+
+ Assert.GreaterOrEqual(nextIndex, 0, $"Looking for {value}");
index = nextIndex + value.Length;
}
}
@@ -213,17 +241,6 @@ public void GlobalSetTest()
Assert.That(content.Contains("