From cb8a32e5a6e7fe6acf00514e94ae6555eabe20bf Mon Sep 17 00:00:00 2001 From: Pranav K Date: Wed, 29 Jan 2014 09:20:59 -0800 Subject: [PATCH] Updating the view engine to use Microsoft.AspNet.Razor package --- .../Compilation/CompilationMessage.cs | 5 +- .../Compilation/CompilerCache.cs | 2 +- .../Compilation/CscBasedCompilationService.cs | 5 +- .../Compilation/DefaultCompilationService.cs | 14 ---- .../Compilation/ICompilationService.cs | 3 +- .../Razor/IRazorCompilationService.cs | 10 +++ .../Razor/MvcCSharpRazorCodeGenerator.cs | 31 -------- .../Razor/MvcCSharpRazorCodeParser.cs | 73 ------------------- .../Razor/MvcRazorHost.cs | 21 +----- .../Razor/RazorCompilationService.cs | 60 +++++++++------ .../Razor/SetModelTypeCodeGenerator.cs | 29 -------- .../ViewEngine/IVirtualFileSystem.cs | 8 ++ .../ViewEngine/VirtualFile.cs | 48 ++++++++++++ .../ViewEngine/VirtualFileSystem.cs | 16 +++- .../ViewEngine/VirtualPathViewFactory.cs | 4 +- src/Microsoft.AspNet.Mvc.Razor/project.json | 7 +- 16 files changed, 129 insertions(+), 207 deletions(-) delete mode 100644 src/Microsoft.AspNet.Mvc.Razor/Compilation/DefaultCompilationService.cs create mode 100644 src/Microsoft.AspNet.Mvc.Razor/Razor/IRazorCompilationService.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeGenerator.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeParser.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Razor/Razor/SetModelTypeCodeGenerator.cs create mode 100644 src/Microsoft.AspNet.Mvc.Razor/ViewEngine/IVirtualFileSystem.cs create mode 100644 src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFile.cs diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationMessage.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationMessage.cs index ab5773a3c4..59aed9e696 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationMessage.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilationMessage.cs @@ -1,5 +1,4 @@ -using System; - + namespace Microsoft.AspNet.Mvc.Razor { public class CompilationMessage @@ -9,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.Razor Message = message; } - public string Message {get; private set;} + public string Message { get; private set; } public override string ToString() { diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilerCache.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilerCache.cs index bbcb18e554..c097de6b98 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilerCache.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CompilerCache.cs @@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Mvc.Razor public CompilerCache() { - _cache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + _cache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); } public async Task GetOrAdd(IFileInfo file, Func> compile) diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs index de94fea857..fe60dfba84 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/CscBasedCompilationService.cs @@ -22,9 +22,10 @@ namespace Microsoft.AspNet.Mvc.Razor @"Microsoft.NET\Framework\v4.0.30319\csc.exe"); } - public async Task Compile(IFileInfo fileInfo) + public async Task Compile(string contents) { Directory.CreateDirectory(_tempDir); + string inFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".cs"); string outFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".dll"); StringBuilder args = new StringBuilder("/target:library "); args.AppendFormat("/out:\"{0}\" ", outFile); @@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Razor { args.AppendFormat("/R:\"{0}\" ", file); } - args.AppendFormat("\"{0}\"", fileInfo.PhysicalPath); + args.AppendFormat("\"{0}\"", inFile); var outputStream = new MemoryStream(); // common execute diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/DefaultCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/DefaultCompilationService.cs deleted file mode 100644 index 2ea4ccca9d..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/DefaultCompilationService.cs +++ /dev/null @@ -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 Compile(IFileInfo fileInfo) - { - return null; - } - } -} diff --git a/src/Microsoft.AspNet.Mvc.Razor/Compilation/ICompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Compilation/ICompilationService.cs index fdca6e0794..a1f9064520 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Compilation/ICompilationService.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Compilation/ICompilationService.cs @@ -1,11 +1,10 @@  using System.Threading.Tasks; -using Microsoft.Owin.FileSystems; namespace Microsoft.AspNet.Mvc.Razor { public interface ICompilationService { - Task Compile(IFileInfo fileInfo); + Task Compile(string content); } } diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/IRazorCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/IRazorCompilationService.cs new file mode 100644 index 0000000000..f8d4e1c2de --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/Razor/IRazorCompilationService.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Microsoft.Owin.FileSystems; + +namespace Microsoft.AspNet.Mvc.Razor +{ + public interface IRazorCompilationService + { + Task Compile(IFileInfo fileInfo); + } +} diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeGenerator.cs deleted file mode 100644 index ca0af7aa0f..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeGenerator.cs +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeParser.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeParser.cs deleted file mode 100644 index 2974c7d921..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcCSharpRazorCodeParser.cs +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcRazorHost.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcRazorHost.cs index 25a5a347ec..a35a85a689 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcRazorHost.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Razor/MvcRazorHost.cs @@ -1,7 +1,6 @@ -#if NET45 -using System.Web.Razor; -using System.Web.Razor.Generator; -using System.Web.Razor.Parser; +using Microsoft.AspNet.Razor; +using Microsoft.AspNet.Razor.Generator; +using Microsoft.AspNet.Razor.Parser; namespace Microsoft.AspNet.Mvc.Razor { @@ -37,19 +36,5 @@ namespace Microsoft.AspNet.Mvc.Razor 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 \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/RazorCompilationService.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/RazorCompilationService.cs index 6b75b043f8..19bc590047 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/Razor/RazorCompilationService.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/Razor/RazorCompilationService.cs @@ -1,20 +1,17 @@ -#if NET45 -using System.CodeDom.Compiler; +using System; using System.IO; using System.Linq; +using System.Text; using System.Threading.Tasks; -using System.Web.Razor; -using Microsoft.CSharp; +using Microsoft.AspNet.Razor; using Microsoft.Owin.FileSystems; 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 readonly IFileSystem _tempFileSystem = new PhysicalFileSystem(Path.GetTempPath()); + private static readonly CompilerCache _cache = new CompilerCache(); private readonly ICompilationService _baseCompilationService; - private readonly CompilerCache _cache = new CompilerCache(); public RazorCompilationService(ICompilationService compilationService) { @@ -30,34 +27,49 @@ namespace Microsoft.AspNet.Mvc.Razor { var host = new MvcRazorHost(); var engine = new RazorTemplateEngine(host); + + var namespaceBuilder = GenerateNamespace(file); + GeneratorResults results; 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; - - using (var writer = new StringWriter()) - using (var codeProvider = new CSharpCodeProvider()) + if (!results.Success) { - codeProvider.GenerateCodeFromCompileUnit(results.GeneratedCode, writer, new CodeGeneratorOptions()); - generatedCode = writer.ToString(); + return CompilationResult.Failed(results.GeneratedCode, results.ParserErrors.Select(e => new CompilationMessage(e.Message))); } - 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); - string tempFile = Path.Combine(_tempPath, Path.GetRandomFileName() + ".cs"); + var namespaceBuilder = new StringBuilder(virtualPath.Length); - File.WriteAllText(tempFile, generatedCode); - - _tempFileSystem.TryGetFileInfo(tempFile, out file); - return await _baseCompilationService.Compile(file); + foreach (char c in Path.GetDirectoryName(virtualPath)) + { + if (c == Path.DirectorySeparatorChar) + { + namespaceBuilder.Append('.'); + } + else if (!Char.IsLetterOrDigit(c)) + { + namespaceBuilder.Append('_'); + } + else + { + namespaceBuilder.Append(c); + } + } + return namespaceBuilder; } } } -#endif \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/Razor/SetModelTypeCodeGenerator.cs b/src/Microsoft.AspNet.Mvc.Razor/Razor/SetModelTypeCodeGenerator.cs deleted file mode 100644 index 392e956fb1..0000000000 --- a/src/Microsoft.AspNet.Mvc.Razor/Razor/SetModelTypeCodeGenerator.cs +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/IVirtualFileSystem.cs b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/IVirtualFileSystem.cs new file mode 100644 index 0000000000..7cce40e47e --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/IVirtualFileSystem.cs @@ -0,0 +1,8 @@ +using Microsoft.Owin.FileSystems; + +namespace Microsoft.AspNet.Mvc.Razor +{ + public interface IVirtualFileSystem : IFileSystem + { + } +} diff --git a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFile.cs b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFile.cs new file mode 100644 index 0000000000..fe1790d09a --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFile.cs @@ -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; } + } + } +} diff --git a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFileSystem.cs b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFileSystem.cs index dc7af31365..15de54b42e 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFileSystem.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualFileSystem.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using Microsoft.Owin.FileSystems; namespace Microsoft.AspNet.Mvc.Razor { - public class VirtualFileSystem : IFileSystem + public class VirtualFileSystem : IVirtualFileSystem { private readonly IFileSystem _fileSystem; @@ -16,13 +18,21 @@ namespace Microsoft.AspNet.Mvc.Razor public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo) { 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 contents) { 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) diff --git a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualPathViewFactory.cs b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualPathViewFactory.cs index b50998296b..0a423d0065 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualPathViewFactory.cs +++ b/src/Microsoft.AspNet.Mvc.Razor/ViewEngine/VirtualPathViewFactory.cs @@ -8,9 +8,9 @@ namespace Microsoft.AspNet.Mvc.Razor public class VirtualPathViewFactory : IVirtualPathViewFactory { 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; _compilationService = compilationService; diff --git a/src/Microsoft.AspNet.Mvc.Razor/project.json b/src/Microsoft.AspNet.Mvc.Razor/project.json index db8b6959fb..ee58029dbd 100644 --- a/src/Microsoft.AspNet.Mvc.Razor/project.json +++ b/src/Microsoft.AspNet.Mvc.Razor/project.json @@ -4,15 +4,12 @@ "Microsoft.AspNet.FileSystems": "0.1-alpha-*", "Microsoft.AspNet.Abstractions": "0.1-alpha-*", "Microsoft.AspNet.DependencyInjection": "0.1-alpha-*", + "Microsoft.AspNet.Razor": "0.1-alpha-*", "Microsoft.AspNet.Mvc" : "", "Microsoft.AspNet.Mvc.Forms" : "" }, "configurations": { - "net45": { - "dependencies": { - "Microsoft.AspNet.Razor" : "3.1.0" - } - }, + "net45": {}, "k10" : { } } } \ No newline at end of file