Skip to content

Commit

Permalink
Merge branch 'release/3.6.5' into releases
Browse files Browse the repository at this point in the history
  • Loading branch information
matthid committed Apr 10, 2015
2 parents af84fb2 + 67eb30d commit d700f9c
Show file tree
Hide file tree
Showing 13 changed files with 297 additions and 36 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Join the chat at https://gitter.im/Antaris/RazorEngine](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Antaris/RazorEngine?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

*latest* documentation available on http://antaris.github.io/RazorEngine/.
*latest* documentation available on https://antaris.github.io/RazorEngine/.

## Build status

Expand All @@ -28,6 +28,7 @@ You can find an introduction [here](http://www.asp.net/web-pages/overview/gettin
All you need to do is use the static `Engine` class (the `Engine.Razor` instance):

```csharp
// using RazorEngine.Templating; // Dont forget to include this.
string template = "Hello @Model.Name, welcome to RazorEngine!";
var result =
Engine.Razor.RunCompile(template, "templateKey", null, new { Name = "World" });
Expand All @@ -38,6 +39,7 @@ var result =
The `"templateKey"` must be unique and after running the above example you can re-run the cached template with this key.

```csharp
// using RazorEngine.Templating; // Dont forget to include this.
var result =
Engine.Razor.Run("templateKey", null, new { Name = "Max" });
```
Expand All @@ -46,6 +48,7 @@ The null parameter is the `modelType` and `null` in this case means we use `dyna
You can use a static model as well by providing a type object.

```csharp
// using RazorEngine.Templating; // Dont forget to include this.
var result =
Engine.Razor.RunCompile("templateKey", typeof(Person), new Person { Name = "Max" });
```
Expand Down Expand Up @@ -102,6 +105,7 @@ As as you might see in the above code there is no file to debug into.
To provide RazorEngine with the necessary information you need to tell where the file can be found:

```csharp
// using RazorEngine.Templating; // Dont forget to include this.
string template = "Hello @Model.Name, welcome to RazorEngine!";
string templateFile = "C:/mytemplate.cshtml"
var result =
Expand Down
2 changes: 1 addition & 1 deletion buildConfig.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ let projectDescription_roslyn = "RazorEngine.Roslyn - Roslyn support for RazorEn
// !!!!!!!!!!!!!!!!!!!
// UPDATE RELEASE NOTES AS WELL!
// !!!!!!!!!!!!!!!!!!!
let version_razor4 = "4.1.4-beta1"
let version_razor4 = "4.1.5-beta1"
let version_roslyn = "3.5.2-beta1"
let version_roslyn_razor4 = "4.0.2-beta1"

Expand Down
21 changes: 12 additions & 9 deletions doc/ReferenceResolver.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ config.ReferenceResolver = new MyIReferenceResolver();

class MyIReferenceResolver : IReferenceResolver {
public string FindLoaded(IEnumerable<string> refs, string find) {
return refs.First(r => r == find);
return refs.First(r => r.EndsWith(System.IO.Path.DirectorySeparatorChar + find));
}
public IEnumerable<CompilerReference> GetReferences(TypeContext context, IEnumerable<CompilerReference> includeAssemblies) {
// TypeContext gives you some context for the compilation (which templates, which namespaces and types)
// You must make sure to include all libraries that are required!
// Mono compiler does add more standard references by default
// Mono compiler does add more standard references than csc!
// If you want mono compatibility include ALL references here, including mscorlib!
// If you include a mscorlib here the compiler is called with /nostdlib.
// If you include mscorlib here the compiler is called with /nostdlib.
IEnumerable<string> loadedAssemblies = (new UseCurrentAssembliesReferenceResolver())
.GetReferences(context, includeAssemblies)
.Select(r => r.GetFile())
Expand All @@ -28,13 +30,14 @@ class MyIReferenceResolver : IReferenceResolver {
yield return CompilerReference.From(FindLoaded(loadedAssemblies, "mscorlib.dll"));
yield return CompilerReference.From(FindLoaded(loadedAssemblies, "System.dll"));
yield return CompilerReference.From(FindLoaded(loadedAssemblies, "System.Core.dll"));
// TypeContext gives you some context for the compilation (which templates, which namespaces and types)
yield return CompilerReference.From("Path-to-my-custom-assembly"); // file path (string)
yield return CompilerReference.From(typeof(MyIReferenceResolver).Assembly); // Assembly
byte[] assemblyInByteArray = null;
yield return CompilerReference.From(assemblyInByteArray); // byte array (roslyn only)
string assemblyFile = null;
yield return CompilerReference.From(File.OpenRead(assemblyFile)); // stream (roslyn only)
// There are several ways to load an assembly:
//yield return CompilerReference.From("Path-to-my-custom-assembly"); // file path (string)
//byte[] assemblyInByteArray = --- Load your assembly ---;
//yield return CompilerReference.From(assemblyInByteArray); // byte array (roslyn only)
//string assemblyFile = --- Get the path to the assembly ---;
//yield return CompilerReference.From(File.OpenRead(assemblyFile)); // stream (roslyn only)
}
}

Expand Down
5 changes: 4 additions & 1 deletion doc/ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
### 3.6.4 / 4.1.4-beta1
### 3.6.5 / 4.1.5-beta1
* Fix https://github.com/Antaris/RazorEngine/issues/267

### 3.6.4 / 4.1.4-beta1
* Use /nostdlib when we find a mscorlib (improves mono support)
* Added `DisableTempFileLocking` to load assemblies in memory (to prevent temp file locking),
this is only recommended in a very limited amount of scenarios.
Expand Down
8 changes: 4 additions & 4 deletions src/SharedAssemblyInfo-Razor4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
[assembly: AssemblyCompanyAttribute("RazorEngine")]
[assembly: AssemblyProductAttribute("RazorEngine")]
[assembly: AssemblyCopyrightAttribute("RazorEngine Copyright © RazorEngine Project 2011-2015")]
[assembly: AssemblyVersionAttribute("4.1.4")]
[assembly: AssemblyFileVersionAttribute("4.1.4")]
[assembly: AssemblyInformationalVersionAttribute("4.1.4-beta1")]
[assembly: AssemblyVersionAttribute("4.1.5")]
[assembly: AssemblyFileVersionAttribute("4.1.5")]
[assembly: AssemblyInformationalVersionAttribute("4.1.5-beta1")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "4.1.4";
internal const string Version = "4.1.5";
}
}
8 changes: 4 additions & 4 deletions src/SharedAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
[assembly: AssemblyCompanyAttribute("RazorEngine")]
[assembly: AssemblyProductAttribute("RazorEngine")]
[assembly: AssemblyCopyrightAttribute("RazorEngine Copyright © RazorEngine Project 2011-2015")]
[assembly: AssemblyVersionAttribute("3.6.4")]
[assembly: AssemblyFileVersionAttribute("3.6.4")]
[assembly: AssemblyInformationalVersionAttribute("3.6.4")]
[assembly: AssemblyVersionAttribute("3.6.5")]
[assembly: AssemblyFileVersionAttribute("3.6.5")]
[assembly: AssemblyInformationalVersionAttribute("3.6.5")]
namespace System {
internal static class AssemblyVersionInformation {
internal const string Version = "3.6.4";
internal const string Version = "3.6.5";
}
}
86 changes: 76 additions & 10 deletions src/source/RazorEngine.Core/Compilation/CrossAppDomainCleanUp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,39 @@ public static void RegisterCleanup(string item, bool throwOnDefault = true)
CurrentCleanup.RegisterCleanupPath(item);
}

/// <summary>
/// Helper method to stop the Execution flow and run the delegate in a new Task.
/// See https://github.com/Antaris/RazorEngine/issues/267 for details.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <returns></returns>
[SecurityCritical]
private static T CallHelperSafe<T>(Func<T> a)
{
using (var flow = System.Threading.ExecutionContext.SuppressFlow())
{
// in the new task we got rid of any executioncontext, see https://github.com/Antaris/RazorEngine/issues/267
return TaskRunner.Run(a).Result;
}
}

/// <summary>
/// Helper method to stop the Execution flow and run the delegate in a new Task.
/// See https://github.com/Antaris/RazorEngine/issues/267 for details.
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
[SecurityCritical]
private static void CallHelperSafe(Action a)
{
using (var flow = System.Threading.ExecutionContext.SuppressFlow())
{
// in the new task we got rid of any executioncontext, see https://github.com/Antaris/RazorEngine/issues/267
TaskRunner.Run(a).Wait();
}
}

private readonly AppDomain _domain;
private readonly CleanupHelper _helper;
/*
Expand Down Expand Up @@ -528,16 +561,48 @@ public CrossAppDomainCleanUp(AppDomain toWatch, IPrinter printer)
current.SetupInformation, new PermissionSet(PermissionState.Unrestricted),
strongNames);

ObjectHandle handle =
Activator.CreateInstanceFrom(
_domain, typeof(CleanupHelper).Assembly.ManifestModule.FullyQualifiedName,
typeof(CleanupHelper).FullName
);
_helper = (CleanupHelper)handle.Unwrap();
_helper.SetupDomain();
_helper.Init(current, CrossAppDomainCleanUp.CurrentPrinter);
var initHelper = new InitHelper() { Domain = _domain, Current = current };
_helper = CallHelperSafe(new Func<CleanupHelper>(initHelper.CreateHelper));
}

/// <summary>
/// This class only exists because we can't use a simple lambda.
/// </summary>
[SecuritySafeCritical]
private class InitHelper
{
internal AppDomain Domain { get; set; }
internal AppDomain Current { get; set; }
[SecuritySafeCritical]
internal CleanupHelper CreateHelper()
{
(new PermissionSet(PermissionState.Unrestricted)).Assert();
ObjectHandle handle =
Activator.CreateInstanceFrom(
Domain, typeof(CleanupHelper).Assembly.ManifestModule.FullyQualifiedName,
typeof(CleanupHelper).FullName
);
var helper = (CleanupHelper)handle.Unwrap();
helper.SetupDomain();
helper.Init(Current, CrossAppDomainCleanUp.CurrentPrinter);
return helper;
}

}

/// <summary>
/// This class only exists because we can't use a simple lambda.
/// </summary>
[SecuritySafeCritical]
private class RegisterCleanupHelper
{
internal string Path { get; set; }
internal CleanupHelper Helper { get; set; }
[SecuritySafeCritical]
internal void RegisterCleanupPath (){
Helper.RegisterCleanupPath(Path);
}
}
/// <summary>
/// Register the given path for cleanup.
/// </summary>
Expand All @@ -546,7 +611,8 @@ public CrossAppDomainCleanUp(AppDomain toWatch, IPrinter printer)
[SecuritySafeCritical]
public void RegisterCleanupPath(string path)
{
_helper.RegisterCleanupPath(path);
var caller = new RegisterCleanupHelper() { Helper = _helper, Path = path };
CallHelperSafe(caller.RegisterCleanupPath);
}

/// <summary>
Expand All @@ -556,7 +622,7 @@ public void RegisterCleanupPath(string path)
[SecuritySafeCritical]
public void Dispose()
{
_helper.Dispose();
CallHelperSafe(_helper.Dispose);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace RazorEngine.Configuration
using Templating;
using Text;
using RazorEngine.Compilation.ReferenceResolver;
using System.Security;

/// <summary>
/// Provides a default implementation of a template service configuration.
Expand All @@ -22,14 +23,22 @@ public class TemplateServiceConfiguration : ITemplateServiceConfiguration
#pragma warning restore 0618 // Backwards Compat.

#region Constructor

/// <summary>
/// Initialises a new instance of <see cref="TemplateServiceConfiguration"/>.
/// </summary>
[SecuritySafeCritical]
public TemplateServiceConfiguration()

{
// Read configuration values from App.config / Web.config
// and fallback to appropriate defaults.
var xmlConfig = new XmlTemplateServiceConfiguration();
XmlTemplateServiceConfiguration xmlConfig = null;
// Fix for Release_3_6_TestFixture.RazorEngineService_Issue267Ext.
using (var flow = System.Threading.ExecutionContext.SuppressFlow())
{
xmlConfig = TaskRunner.Run(() => new XmlTemplateServiceConfiguration()).Result;
}

Activator = xmlConfig.Activator ?? new DefaultActivator();
CompilerServiceFactory = xmlConfig.CompilerServiceFactory ?? new DefaultCompilerServiceFactory();
Expand Down
1 change: 1 addition & 0 deletions src/source/RazorEngine.Core/RazorEngine.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
<Compile Include="Configuration\Xml\TemplateServiceConfigurationElement.cs" />
<Compile Include="Configuration\Xml\TemplateServiceConfigurationElementCollection.cs" />
<Compile Include="Engine.cs" />
<Compile Include="TaskRunner.cs" />
<Compile Include="Templating\DynamicWrapperService.cs" />
<Compile Include="Templating\IsolatedRazorEngineService.cs" />
<Compile Include="Templating\TemplateLoadingException.cs" />
Expand Down
48 changes: 48 additions & 0 deletions src/source/RazorEngine.Core/TaskRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;

namespace RazorEngine
{
/// <summary>
/// Helper for missing net40 methods, REMOVE me when we are net45 only.
/// </summary>
internal class TaskRunner
{
/// <summary>
/// Runs the given delegate in a new task (like Task.Run but works on net40).
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="t"></param>
/// <returns></returns>
public static Task<T> Run<T>(Func<T> t)
{
#if NET40
var task = new Task<T>(t);
task.Start();
return task;
#else
return Task.Run(t);
#endif
}

/// <summary>
/// Runs the given delegate in a new task (like Task.Run but works on net40).
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public static Task Run(Action t)
{
#if NET40
var task = new Task(t);
task.Start();
return task;
#else
return Task.Run(t);
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,27 @@ internal static string GetMessage(IEnumerable<RazorEngineCompilerError> errors,
sourceCodeMessage = string.Format(rawSourceCode, Separate(files.SourceCode));
}

string loadedAssemblies =
"\nList of loaded Assemblies:\n" +
string.Join("\n\tLoaded Assembly: ",
(new Compilation.ReferenceResolver.UseCurrentAssembliesReferenceResolver())
.GetReferences().Select(r => r.GetFile()));

var rawMessage = @"Errors while compiling a Template.
Please try the following to solve the situation:
* If the problem is about missing references either try to load the missing references manually (in the compiling appdomain!) or
* If the problem is about missing/invalid references or multiple defines either try to load
the missing references manually (in the compiling appdomain!) or
Specify your references manually by providing your own IReferenceResolver implementation.
See https://antaris.github.io/RazorEngine/ReferenceResolver.html for details.
Currently all references have to be available as files!
* If you get 'class' does not contain a definition for 'member':
try another modelType (for example 'null' or 'typeof(DynamicObject)' to make the model dynamic).
NOTE: You CANNOT use typeof(dynamic)!
try another modelType (for example 'null' to make the model dynamic).
NOTE: You CANNOT use typeof(dynamic) to make the model dynamic!
Or try to use static instead of anonymous/dynamic types.
More details about the error:
{0}
{1}{2}{3}";
return string.Format(rawMessage, errorMsgs, tempFilesMsg, templateFileMsg, sourceCodeMessage);
{1}{2}{3}{4}";
return string.Format(rawMessage, errorMsgs, tempFilesMsg, templateFileMsg, sourceCodeMessage, loadedAssemblies);
}

#region Constructors
Expand Down

0 comments on commit d700f9c

Please sign in to comment.