Updating the view engine to use Microsoft.AspNet.Razor package

This commit is contained in:
Pranav K 2014-01-29 09:20:59 -08:00
parent a1d5a02c70
commit cb8a32e5a6
16 changed files with 129 additions and 207 deletions

View File

@ -1,5 +1,4 @@
using System; 
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
public class CompilationMessage public class CompilationMessage
@ -9,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.Razor
Message = message; Message = message;
} }
public string Message {get; private set;} public string Message { get; private set; }
public override string ToString() public override string ToString()
{ {

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Mvc.Razor
public CompilerCache() public CompilerCache()
{ {
_cache = new ConcurrentDictionary<string,Type>(StringComparer.OrdinalIgnoreCase); _cache = new ConcurrentDictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
} }
public async Task<CompilationResult> GetOrAdd(IFileInfo file, Func<Task<CompilationResult>> compile) public async Task<CompilationResult> GetOrAdd(IFileInfo file, Func<Task<CompilationResult>> compile)

View File

@ -22,9 +22,10 @@ namespace Microsoft.AspNet.Mvc.Razor
@"Microsoft.NET\Framework\v4.0.30319\csc.exe"); @"Microsoft.NET\Framework\v4.0.30319\csc.exe");
} }
public async Task<CompilationResult> Compile(IFileInfo fileInfo) public async Task<CompilationResult> Compile(string contents)
{ {
Directory.CreateDirectory(_tempDir); Directory.CreateDirectory(_tempDir);
string inFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".cs");
string outFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".dll"); string outFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".dll");
StringBuilder args = new StringBuilder("/target:library "); StringBuilder args = new StringBuilder("/target:library ");
args.AppendFormat("/out:\"{0}\" ", outFile); args.AppendFormat("/out:\"{0}\" ", outFile);
@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
args.AppendFormat("/R:\"{0}\" ", file); args.AppendFormat("/R:\"{0}\" ", file);
} }
args.AppendFormat("\"{0}\"", fileInfo.PhysicalPath); args.AppendFormat("\"{0}\"", inFile);
var outputStream = new MemoryStream(); var outputStream = new MemoryStream();
// common execute // common execute

View File

@ -1,14 +0,0 @@
using System;
using System.Threading.Tasks;
using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor
{
public class DefaultCompilationService : ICompilationService
{
public Task<CompilationResult> Compile(IFileInfo fileInfo)
{
return null;
}
}
}

View File

@ -1,11 +1,10 @@
 
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
public interface ICompilationService public interface ICompilationService
{ {
Task<CompilationResult> Compile(IFileInfo fileInfo); Task<CompilationResult> Compile(string content);
} }
} }

View File

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor
{
public interface IRazorCompilationService
{
Task<CompilationResult> Compile(IFileInfo fileInfo);
}
}

View File

@ -1,31 +0,0 @@
#if NET45
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.CodeDom;
using System.Web.Razor;
using System.Web.Razor.Generator;
namespace Microsoft.AspNet.Mvc.Razor
{
internal class MvcCSharpRazorCodeGenerator : CSharpRazorCodeGenerator
{
private const string DefaultModelTypeName = "dynamic";
public MvcCSharpRazorCodeGenerator(string className, string rootNamespaceName, string sourceFileName, RazorEngineHost host)
: base(className, rootNamespaceName, sourceFileName, host)
{
// set the default model type to "dynamic" (Dev10 bug 935656)
// don't set it for "special" pages (such as "_viewStart.cshtml")
SetBaseType(DefaultModelTypeName);
}
private void SetBaseType(string modelTypeName)
{
var baseType = new CodeTypeReference(Context.Host.DefaultBaseClass + "<" + modelTypeName + ">");
Context.GeneratedClass.BaseTypes.Clear();
Context.GeneratedClass.BaseTypes.Add(baseType);
}
}
}
#endif

View File

@ -1,73 +0,0 @@
#if NET45
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Web.Razor.Generator;
using System.Web.Razor.Parser;
using System.Web.Razor.Text;
namespace Microsoft.AspNet.Mvc.Razor
{
public class MvcCSharpRazorCodeParser : CSharpCodeParser
{
private const string ModelKeyword = "model";
private SourceLocation? _endInheritsLocation;
private bool _modelStatementFound;
public MvcCSharpRazorCodeParser()
{
MapDirectives(ModelDirective, ModelKeyword);
}
protected override void InheritsDirective()
{
// Verify we're on the right keyword and accept
AssertDirective(SyntaxConstants.CSharp.InheritsKeyword);
AcceptAndMoveNext();
_endInheritsLocation = CurrentLocation;
InheritsDirectiveCore();
CheckForInheritsAndModelStatements();
}
protected virtual void ModelDirective()
{
// Verify we're on the right keyword and accept
AssertDirective(ModelKeyword);
AcceptAndMoveNext();
SourceLocation endModelLocation = CurrentLocation;
BaseTypeDirective(
String.Format(CultureInfo.CurrentCulture,
"The '{0}' keyword must be followed by a type name on the same line.", ModelKeyword),
CreateModelCodeGenerator);
if (_modelStatementFound)
{
Context.OnError(endModelLocation, String.Format(CultureInfo.CurrentCulture,
"Only one '{0}' statement is allowed in a file.", ModelKeyword));
}
_modelStatementFound = true;
CheckForInheritsAndModelStatements();
}
private void CheckForInheritsAndModelStatements()
{
if (_modelStatementFound && _endInheritsLocation.HasValue)
{
Context.OnError(_endInheritsLocation.Value, String.Format(CultureInfo.CurrentCulture,
"The 'inherits' keyword is not allowed when a '{0}' keyword is used.", ModelKeyword));
}
}
private SpanCodeGenerator CreateModelCodeGenerator(string model)
{
return new SetModelTypeCodeGenerator(model);
}
}
}
#endif

View File

@ -1,7 +1,6 @@
#if NET45 using Microsoft.AspNet.Razor;
using System.Web.Razor; using Microsoft.AspNet.Razor.Generator;
using System.Web.Razor.Generator; using Microsoft.AspNet.Razor.Parser;
using System.Web.Razor.Parser;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
@ -37,19 +36,5 @@ namespace Microsoft.AspNet.Mvc.Razor
NamespaceImports.Add(ns); NamespaceImports.Add(ns);
} }
} }
public override RazorCodeGenerator DecorateCodeGenerator(RazorCodeGenerator incomingCodeGenerator)
{
return new MvcCSharpRazorCodeGenerator(incomingCodeGenerator.ClassName,
incomingCodeGenerator.RootNamespaceName,
incomingCodeGenerator.SourceFileName,
incomingCodeGenerator.Host);
}
public override ParserBase DecorateCodeParser(ParserBase incomingCodeParser)
{
return new MvcCSharpRazorCodeParser();
}
} }
} }
#endif

View File

@ -1,20 +1,17 @@
#if NET45 using System;
using System.CodeDom.Compiler;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Razor; using Microsoft.AspNet.Razor;
using Microsoft.CSharp;
using Microsoft.Owin.FileSystems; using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
public class RazorCompilationService : ICompilationService public class RazorCompilationService : IRazorCompilationService
{ {
private static readonly string _tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); private static readonly CompilerCache _cache = new CompilerCache();
private readonly IFileSystem _tempFileSystem = new PhysicalFileSystem(Path.GetTempPath());
private readonly ICompilationService _baseCompilationService; private readonly ICompilationService _baseCompilationService;
private readonly CompilerCache _cache = new CompilerCache();
public RazorCompilationService(ICompilationService compilationService) public RazorCompilationService(ICompilationService compilationService)
{ {
@ -30,34 +27,49 @@ namespace Microsoft.AspNet.Mvc.Razor
{ {
var host = new MvcRazorHost(); var host = new MvcRazorHost();
var engine = new RazorTemplateEngine(host); var engine = new RazorTemplateEngine(host);
var namespaceBuilder = GenerateNamespace(file);
GeneratorResults results; GeneratorResults results;
using (TextReader rdr = new StreamReader(file.CreateReadStream())) using (TextReader rdr = new StreamReader(file.CreateReadStream()))
{ {
results = engine.GenerateCode(rdr, '_' + Path.GetFileNameWithoutExtension(file.Name), "Asp", file.PhysicalPath ?? file.Name); results = engine.GenerateCode(rdr, '_' + file.Name, namespaceBuilder.ToString(), file.PhysicalPath ?? file.Name);
} }
string generatedCode; if (!results.Success)
using (var writer = new StringWriter())
using (var codeProvider = new CSharpCodeProvider())
{ {
codeProvider.GenerateCodeFromCompileUnit(results.GeneratedCode, writer, new CodeGeneratorOptions()); return CompilationResult.Failed(results.GeneratedCode, results.ParserErrors.Select(e => new CompilationMessage(e.Message)));
generatedCode = writer.ToString();
} }
if (!results.Success) return await _baseCompilationService.Compile(results.GeneratedCode);
}
private static StringBuilder GenerateNamespace(IFileInfo file)
{
string virtualPath = file.PhysicalPath;
if (virtualPath.StartsWith("~/", StringComparison.Ordinal))
{ {
return CompilationResult.Failed(generatedCode, results.ParserErrors.Select(e => new CompilationMessage(e.Message))); virtualPath = virtualPath.Substring(2);
} }
Directory.CreateDirectory(_tempPath); var namespaceBuilder = new StringBuilder(virtualPath.Length);
string tempFile = Path.Combine(_tempPath, Path.GetRandomFileName() + ".cs");
File.WriteAllText(tempFile, generatedCode); foreach (char c in Path.GetDirectoryName(virtualPath))
{
_tempFileSystem.TryGetFileInfo(tempFile, out file); if (c == Path.DirectorySeparatorChar)
return await _baseCompilationService.Compile(file); {
namespaceBuilder.Append('.');
}
else if (!Char.IsLetterOrDigit(c))
{
namespaceBuilder.Append('_');
}
else
{
namespaceBuilder.Append(c);
}
}
return namespaceBuilder;
} }
} }
} }
#endif

View File

@ -1,29 +0,0 @@
#if NET45
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Web.Razor.Generator;
namespace Microsoft.AspNet.Mvc.Razor
{
internal class SetModelTypeCodeGenerator : SetBaseTypeCodeGenerator
{
private const string GenericTypeFormatString = "{0}<{1}>";
public SetModelTypeCodeGenerator(string modelType)
: base(modelType)
{
}
protected override string ResolveType(CodeGeneratorContext context, string baseType)
{
return String.Format(
CultureInfo.InvariantCulture,
GenericTypeFormatString,
context.Host.DefaultBaseClass,
baseType);
}
}
}
#endif

View File

@ -0,0 +1,8 @@
using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor
{
public interface IVirtualFileSystem : IFileSystem
{
}
}

View File

@ -0,0 +1,48 @@
using System;
using System.IO;
using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor
{
public class VirtualFile : IFileInfo
{
private readonly string _virtualPath;
private readonly IFileInfo _underlyingFileInfo;
public VirtualFile(string virtualPath, IFileInfo underlyingFileInfo)
{
_virtualPath = virtualPath;
_underlyingFileInfo = underlyingFileInfo;
}
public Stream CreateReadStream()
{
return _underlyingFileInfo.CreateReadStream();
}
public bool IsDirectory
{
get { return _underlyingFileInfo.IsDirectory; }
}
public DateTime LastModified
{
get { return _underlyingFileInfo.LastModified; }
}
public long Length
{
get { return _underlyingFileInfo.Length; }
}
public string Name
{
get { return _underlyingFileInfo.Name; }
}
public string PhysicalPath
{
get { return _virtualPath; }
}
}
}

View File

@ -1,10 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Owin.FileSystems; using Microsoft.Owin.FileSystems;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
public class VirtualFileSystem : IFileSystem public class VirtualFileSystem : IVirtualFileSystem
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
@ -16,13 +18,21 @@ namespace Microsoft.AspNet.Mvc.Razor
public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo) public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo)
{ {
string translated = TranslatePath(subpath); string translated = TranslatePath(subpath);
return _fileSystem.TryGetFileInfo(translated, out fileInfo); if (_fileSystem.TryGetFileInfo(translated, out fileInfo))
{
fileInfo = new VirtualFile(subpath, fileInfo);
}
return false;
} }
public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents) public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents)
{ {
string translated = TranslatePath(subpath); string translated = TranslatePath(subpath);
return _fileSystem.TryGetDirectoryContents(translated, out contents); if (_fileSystem.TryGetDirectoryContents(translated, out contents))
{
contents = contents.Select(c => new VirtualFile(subpath + '/' + c.Name, c));
}
return false;
} }
private static string TranslatePath(string path) private static string TranslatePath(string path)

View File

@ -8,9 +8,9 @@ namespace Microsoft.AspNet.Mvc.Razor
public class VirtualPathViewFactory : IVirtualPathViewFactory public class VirtualPathViewFactory : IVirtualPathViewFactory
{ {
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ICompilationService _compilationService; private readonly IRazorCompilationService _compilationService;
public VirtualPathViewFactory(IFileSystem fileSystem, ICompilationService compilationService) public VirtualPathViewFactory(IFileSystem fileSystem, IRazorCompilationService compilationService)
{ {
_fileSystem = fileSystem; _fileSystem = fileSystem;
_compilationService = compilationService; _compilationService = compilationService;

View File

@ -4,15 +4,12 @@
"Microsoft.AspNet.FileSystems": "0.1-alpha-*", "Microsoft.AspNet.FileSystems": "0.1-alpha-*",
"Microsoft.AspNet.Abstractions": "0.1-alpha-*", "Microsoft.AspNet.Abstractions": "0.1-alpha-*",
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*", "Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
"Microsoft.AspNet.Razor": "0.1-alpha-*",
"Microsoft.AspNet.Mvc" : "", "Microsoft.AspNet.Mvc" : "",
"Microsoft.AspNet.Mvc.Forms" : "" "Microsoft.AspNet.Mvc.Forms" : ""
}, },
"configurations": { "configurations": {
"net45": { "net45": {},
"dependencies": {
"Microsoft.AspNet.Razor" : "3.1.0"
}
},
"k10" : { } "k10" : { }
} }
} }