Adding support for disk based views with code generation and compilation
This commit is contained in:
parent
b918cb8170
commit
0699e7aa40
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class CompilationFailedException : Exception
|
||||||
|
{
|
||||||
|
public CompilationFailedException(IEnumerable<CompilationMessage> messages, string generatedCode)
|
||||||
|
: base(FormatMessage(messages))
|
||||||
|
{
|
||||||
|
Messages = messages.ToList();
|
||||||
|
GeneratedCode = generatedCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GeneratedCode { get; private set; }
|
||||||
|
|
||||||
|
public IEnumerable<CompilationMessage> Messages { get; private set; }
|
||||||
|
|
||||||
|
public string CompilationSource
|
||||||
|
{
|
||||||
|
get { return GeneratedCode; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Message
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "Compilation Failed:" + FormatMessage(Messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatMessage(IEnumerable<CompilationMessage> messages)
|
||||||
|
{
|
||||||
|
return String.Join(Environment.NewLine, messages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class CompilationMessage
|
||||||
|
{
|
||||||
|
public CompilationMessage(string message)
|
||||||
|
{
|
||||||
|
Message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Message {get; private set;}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class CompilationResult
|
||||||
|
{
|
||||||
|
private readonly Type _type;
|
||||||
|
|
||||||
|
private CompilationResult(string generatedCode, Type type, IEnumerable<CompilationMessage> messages)
|
||||||
|
{
|
||||||
|
_type = type;
|
||||||
|
GeneratedCode = generatedCode;
|
||||||
|
Messages = messages.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CompilationMessage> Messages { get; private set; }
|
||||||
|
|
||||||
|
public string GeneratedCode { get; private set; }
|
||||||
|
|
||||||
|
public Type CompiledType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_type == null)
|
||||||
|
{
|
||||||
|
throw new CompilationFailedException(Messages, GeneratedCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompilationResult Failed(string generatedCode, IEnumerable<CompilationMessage> messages)
|
||||||
|
{
|
||||||
|
return new CompilationResult(generatedCode, type: null, messages: messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CompilationResult Successful(string generatedCode, Type type)
|
||||||
|
{
|
||||||
|
return new CompilationResult(generatedCode, type, Enumerable.Empty<CompilationMessage>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Caching;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class CompilerCache
|
||||||
|
{
|
||||||
|
private readonly MemoryCache _cache;
|
||||||
|
|
||||||
|
public CompilerCache()
|
||||||
|
{
|
||||||
|
_cache = MemoryCache.Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<CompilationResult> GetOrAdd(IFileInfo file, Func<Task<CompilationResult>> compile)
|
||||||
|
{
|
||||||
|
// Generate a content id
|
||||||
|
string contentId = file.PhysicalPath + '|' + file.LastModified.Ticks;
|
||||||
|
|
||||||
|
var cachedType = _cache[contentId] as Type;
|
||||||
|
if (cachedType == null)
|
||||||
|
{
|
||||||
|
return CompileWith(contentId, file, compile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(CompilationResult.Successful(generatedCode: null, type: cachedType));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<CompilationResult> CompileWith(string contentId, IFileInfo file, Func<Task<CompilationResult>> compile)
|
||||||
|
{
|
||||||
|
CompilationResult result = await compile();
|
||||||
|
Type compiledType = result.CompiledType;
|
||||||
|
|
||||||
|
var filePaths = new [] { file.PhysicalPath };
|
||||||
|
var policy = new CacheItemPolicy();
|
||||||
|
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
|
||||||
|
|
||||||
|
_cache.Set(contentId, result.CompiledType, policy);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class CscBasedCompilationService : ICompilationService
|
||||||
|
{
|
||||||
|
private static readonly string _tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||||
|
private readonly string _path;
|
||||||
|
|
||||||
|
public CscBasedCompilationService()
|
||||||
|
{
|
||||||
|
_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows),
|
||||||
|
@"Microsoft.NET\Framework\v4.0.30319\csc.exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CompilationResult> Compile(IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(_tempDir);
|
||||||
|
string outFile = Path.Combine(_tempDir, Path.GetRandomFileName() + ".dll");
|
||||||
|
StringBuilder args = new StringBuilder("/target:library ");
|
||||||
|
args.AppendFormat("/out:\"{0}\" ", outFile);
|
||||||
|
foreach (var file in Directory.EnumerateFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "*.dll"))
|
||||||
|
{
|
||||||
|
args.AppendFormat("/R:\"{0}\" ", file);
|
||||||
|
}
|
||||||
|
args.AppendFormat("\"{0}\"", fileInfo.PhysicalPath);
|
||||||
|
var outputStream = new MemoryStream();
|
||||||
|
var errorStream = new MemoryStream();
|
||||||
|
|
||||||
|
// common execute
|
||||||
|
var process = CreateProcess(args.ToString());
|
||||||
|
int exitCode = await Start(process, outputStream, errorStream);
|
||||||
|
|
||||||
|
string output = GetString(outputStream);
|
||||||
|
string error = GetString(errorStream);
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
return CompilationResult.Failed(String.Empty, error.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(e => new CompilationMessage(e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = Assembly.LoadFrom(outFile)
|
||||||
|
.GetExportedTypes()
|
||||||
|
.First();
|
||||||
|
return CompilationResult.Successful(String.Empty, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private string GetString(MemoryStream stream)
|
||||||
|
{
|
||||||
|
if (stream.Length > 0)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetString(stream.GetBuffer(), 0, (int)stream.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<int> Start(Process process, Stream output, Stream error)
|
||||||
|
{
|
||||||
|
var tcs = new TaskCompletionSource<int>();
|
||||||
|
process.EnableRaisingEvents = true;
|
||||||
|
process.Exited += (sender, eventArgs) =>
|
||||||
|
{
|
||||||
|
tcs.SetResult(process.ExitCode);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
var tasks = new[]
|
||||||
|
{
|
||||||
|
process.StandardOutput.BaseStream.CopyToAsync(output),
|
||||||
|
process.StandardError.BaseStream.CopyToAsync(error)
|
||||||
|
};
|
||||||
|
|
||||||
|
int result = await tcs.Task;
|
||||||
|
|
||||||
|
// Process has exited, draining the stdout and stderr
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Process CreateProcess(string arguments)
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = _path,
|
||||||
|
RedirectStandardInput = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
|
UseShellExecute = false,
|
||||||
|
ErrorDialog = false,
|
||||||
|
Arguments = arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
psi.StandardOutputEncoding = Encoding.UTF8;
|
||||||
|
psi.StandardErrorEncoding = Encoding.UTF8;
|
||||||
|
|
||||||
|
var process = new Process()
|
||||||
|
{
|
||||||
|
StartInfo = psi
|
||||||
|
};
|
||||||
|
|
||||||
|
return process;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public class DefaultCompilationService : ICompilationService
|
||||||
|
{
|
||||||
|
public Task<CompilationResult> Compile(IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.CoreServices
|
||||||
|
{
|
||||||
|
public interface ICompilationService
|
||||||
|
{
|
||||||
|
Task<CompilationResult> Compile(IFileInfo fileInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,11 +30,22 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.Owin.FileSystems">
|
||||||
|
<HintPath>..\packages\Microsoft.Owin.FileSystems.2.1.0-rc1\lib\net40\Microsoft.Owin.FileSystems.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Runtime.Caching" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ActivatorUtilities.cs" />
|
<Compile Include="ActivatorUtilities.cs" />
|
||||||
|
<Compile Include="Compilation\CompilationFailedException.cs" />
|
||||||
|
<Compile Include="Compilation\CompilationMessage.cs" />
|
||||||
|
<Compile Include="Compilation\CompilationResult.cs" />
|
||||||
|
<Compile Include="Compilation\CompilerCache.cs" />
|
||||||
|
<Compile Include="Compilation\CscBasedCompilationService.cs" />
|
||||||
|
<Compile Include="Compilation\DefaultCompilationService.cs" />
|
||||||
|
<Compile Include="Compilation\ICompilationService.cs" />
|
||||||
<Compile Include="ServiceProvider.cs" />
|
<Compile Include="ServiceProvider.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ServiceProviderExtensions.cs" />
|
<Compile Include="ServiceProviderExtensions.cs" />
|
||||||
|
|
@ -42,6 +53,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="project.json" />
|
<Content Include="project.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Owin.FileSystems" version="2.1.0-rc1" targetFramework="net45" />
|
||||||
|
</packages>
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor
|
|
||||||
{
|
|
||||||
public interface IVirtualPathFactory
|
|
||||||
{
|
|
||||||
Task<object> CreateInstance(string virtualPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -34,12 +34,19 @@
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Owin.FileSystems">
|
||||||
|
<HintPath>..\packages\Microsoft.Owin.FileSystems.2.1.0-rc1\lib\net40\Microsoft.Owin.FileSystems.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Microsoft.AspNet.Razor.3.0.0\lib\net45\System.Web.Razor.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
|
@ -48,12 +55,20 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="HtmlString.cs" />
|
<Compile Include="HtmlString.cs" />
|
||||||
<Compile Include="IVirtualPathFactory.cs" />
|
<Compile Include="RazorViewOfT.cs" />
|
||||||
<Compile Include="MetadataVirtualPathProvider.cs" />
|
<Compile Include="Razor\MvcCSharpRazorCodeGenerator.cs" />
|
||||||
|
<Compile Include="Razor\MvcCSharpRazorCodeParser.cs" />
|
||||||
|
<Compile Include="Razor\MvcRazorHost.cs" />
|
||||||
|
<Compile Include="Razor\RazorCompilationService.cs" />
|
||||||
|
<Compile Include="Razor\SetModelTypeCodeGenerator.cs" />
|
||||||
|
<Compile Include="ViewEngine\IVirtualPathViewFactory.cs" />
|
||||||
|
<Compile Include="ViewEngine\MetadataVirtualPathViewFactory.cs" />
|
||||||
<Compile Include="RazorView.cs" />
|
<Compile Include="RazorView.cs" />
|
||||||
<Compile Include="RazorViewEngine.cs" />
|
<Compile Include="ViewEngine\RazorViewEngine.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="VirtualPathAttribute.cs" />
|
<Compile Include="ViewEngine\VirtualFileSystem.cs" />
|
||||||
|
<Compile Include="ViewEngine\VirtualPathAttribute.cs" />
|
||||||
|
<Compile Include="ViewEngine\VirtualPathViewFactory.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Microsoft.AspNet.CoreServices\Microsoft.AspNet.CoreServices.csproj">
|
<ProjectReference Include="..\Microsoft.AspNet.CoreServices\Microsoft.AspNet.CoreServices.csproj">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System.Web.Razor;
|
||||||
|
using System.Web.Razor.Generator;
|
||||||
|
using System.Web.Razor.Parser;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public class MvcRazorHost : RazorEngineHost
|
||||||
|
{
|
||||||
|
private static readonly string[] _namespaces = new[]
|
||||||
|
{
|
||||||
|
"System",
|
||||||
|
"System.Linq",
|
||||||
|
"System.Collections.Generic",
|
||||||
|
"Microsoft.AspNet.Mvc",
|
||||||
|
"Microsoft.AspNet.Mvc.Razor"
|
||||||
|
};
|
||||||
|
|
||||||
|
public MvcRazorHost()
|
||||||
|
: base(new CSharpRazorCodeLanguage())
|
||||||
|
{
|
||||||
|
DefaultBaseClass = typeof(RazorView).FullName;
|
||||||
|
GeneratedClassContext = new GeneratedClassContext(
|
||||||
|
executeMethodName: "Execute",
|
||||||
|
writeMethodName: "Write",
|
||||||
|
writeLiteralMethodName: "WriteLiteral",
|
||||||
|
writeToMethodName: "WriteTo",
|
||||||
|
writeLiteralToMethodName: "WriteLiteralTo",
|
||||||
|
templateTypeName: "Template",
|
||||||
|
defineSectionMethodName: "DefineSection")
|
||||||
|
{
|
||||||
|
ResolveUrlMethodName = "Href"
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var ns in _namespaces)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.CodeDom;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web.Razor;
|
||||||
|
using System.Web.Razor.Generator;
|
||||||
|
using Microsoft.AspNet.CoreServices;
|
||||||
|
using Microsoft.CSharp;
|
||||||
|
using Microsoft.Owin;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public class RazorCompilationService : ICompilationService
|
||||||
|
{
|
||||||
|
private static readonly string _tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
|
||||||
|
private readonly IFileSystem _tempFileSystem = new PhysicalFileSystem(Path.GetTempPath());
|
||||||
|
private readonly ICompilationService _baseCompilationService;
|
||||||
|
private readonly CompilerCache _cache = new CompilerCache();
|
||||||
|
|
||||||
|
public RazorCompilationService(ICompilationService compilationService)
|
||||||
|
{
|
||||||
|
_baseCompilationService = compilationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<CompilationResult> Compile(IFileInfo file)
|
||||||
|
{
|
||||||
|
return _cache.GetOrAdd(file, () => CompileCore(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<CompilationResult> CompileCore(IFileInfo file)
|
||||||
|
{
|
||||||
|
var host = new MvcRazorHost();
|
||||||
|
var engine = new RazorTemplateEngine(host);
|
||||||
|
GeneratorResults results;
|
||||||
|
using (TextReader rdr = new StreamReader(file.CreateReadStream()))
|
||||||
|
{
|
||||||
|
results = engine.GenerateCode(rdr, '_' + Path.GetFileNameWithoutExtension(file.Name), "Asp", file.PhysicalPath ?? file.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
string generatedCode;
|
||||||
|
|
||||||
|
using (var writer = new StringWriter())
|
||||||
|
using (var codeProvider = new CSharpCodeProvider())
|
||||||
|
{
|
||||||
|
codeProvider.GenerateCodeFromCompileUnit(results.GeneratedCode, writer, new CodeGeneratorOptions());
|
||||||
|
generatedCode = writer.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!results.Success)
|
||||||
|
{
|
||||||
|
return CompilationResult.Failed(generatedCode, results.ParserErrors.Select(e => new CompilationMessage(e.Message)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_tempPath);
|
||||||
|
string tempFile = Path.Combine(_tempPath, Path.GetRandomFileName() + ".cs");
|
||||||
|
|
||||||
|
File.WriteAllText(tempFile, generatedCode);
|
||||||
|
|
||||||
|
_tempFileSystem.TryGetFileInfo(tempFile, out file);
|
||||||
|
return await _baseCompilationService.Compile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,18 +13,14 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
public IOwinContext Context { get; set; }
|
public IOwinContext Context { get; set; }
|
||||||
|
|
||||||
public object Model { get; set; }
|
|
||||||
|
|
||||||
public string Layout { get; set; }
|
public string Layout { get; set; }
|
||||||
|
|
||||||
protected TextWriter Output { get; set; }
|
protected TextWriter Output { get; set; }
|
||||||
|
|
||||||
private string BodyContent { get; set; }
|
private string BodyContent { get; set; }
|
||||||
|
|
||||||
public async Task RenderAsync(ViewContext context, TextWriter writer)
|
public virtual async Task RenderAsync(ViewContext context, TextWriter writer)
|
||||||
{
|
{
|
||||||
Model = context.Model;
|
|
||||||
|
|
||||||
var contentBuilder = new StringBuilder(1024);
|
var contentBuilder = new StringBuilder(1024);
|
||||||
using (var bodyWriter = new StringWriter(contentBuilder))
|
using (var bodyWriter = new StringWriter(contentBuilder))
|
||||||
{
|
{
|
||||||
|
|
@ -45,7 +41,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
|
||||||
private async Task RenderLayoutAsync(ViewContext context, TextWriter writer, string bodyContent)
|
private async Task RenderLayoutAsync(ViewContext context, TextWriter writer, string bodyContent)
|
||||||
{
|
{
|
||||||
var virtualPathFactory = context.ServiceProvider.GetService<IVirtualPathFactory>();
|
var virtualPathFactory = context.ServiceProvider.GetService<IVirtualPathViewFactory>();
|
||||||
RazorView razorView = (RazorView)(await virtualPathFactory.CreateInstance(Layout));
|
RazorView razorView = (RazorView)(await virtualPathFactory.CreateInstance(Layout));
|
||||||
if (razorView == null)
|
if (razorView == null)
|
||||||
{
|
{
|
||||||
|
|
@ -57,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
await razorView.RenderAsync(context, writer);
|
await razorView.RenderAsync(context, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void Execute();
|
public abstract void Execute();
|
||||||
|
|
||||||
public virtual void Write(object value)
|
public virtual void Write(object value)
|
||||||
{
|
{
|
||||||
|
|
@ -93,12 +89,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RenderBody()
|
protected virtual string RenderBody()
|
||||||
{
|
{
|
||||||
if (BodyContent != null)
|
if (BodyContent == null)
|
||||||
{
|
{
|
||||||
WriteLiteral(BodyContent);
|
throw new InvalidOperationException("RenderBody cannot be called at this point because you're not executing a layout");
|
||||||
}
|
}
|
||||||
|
return BodyContent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public abstract class RazorView<TModel> : RazorView
|
||||||
|
{
|
||||||
|
public TModel Model { get; set; }
|
||||||
|
|
||||||
|
public override Task RenderAsync(ViewContext context, TextWriter writer)
|
||||||
|
{
|
||||||
|
Model = (TModel)context.Model;
|
||||||
|
return base.RenderAsync(context, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public interface IVirtualPathViewFactory
|
||||||
|
{
|
||||||
|
Task<IView> CreateInstance(string virtualPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,11 +6,11 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.Razor
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
{
|
{
|
||||||
public class MetadataVirtualPathProvider : IVirtualPathFactory
|
public class MetadataVirtualPathViewFactory : IVirtualPathViewFactory
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, Type> _viewMetadata;
|
private readonly Dictionary<string, Type> _viewMetadata;
|
||||||
|
|
||||||
public MetadataVirtualPathProvider(Assembly assembly)
|
public MetadataVirtualPathViewFactory(Assembly assembly)
|
||||||
{
|
{
|
||||||
var metadataType = assembly.GetType("ViewMetadata");
|
var metadataType = assembly.GetType("ViewMetadata");
|
||||||
if (metadataType != null)
|
if (metadataType != null)
|
||||||
|
|
@ -29,13 +29,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<object> CreateInstance(string virtualPath)
|
public Task<IView> CreateInstance(string virtualPath)
|
||||||
{
|
{
|
||||||
Type type;
|
Type type;
|
||||||
object view = null;
|
IView view = null;
|
||||||
if (_viewMetadata.TryGetValue(virtualPath, out type))
|
if (_viewMetadata.TryGetValue(virtualPath, out type))
|
||||||
{
|
{
|
||||||
view = (RazorView)Activator.CreateInstance(type);
|
view = (IView)Activator.CreateInstance(type);
|
||||||
}
|
}
|
||||||
return Task.FromResult(view);
|
return Task.FromResult(view);
|
||||||
}
|
}
|
||||||
|
|
@ -13,10 +13,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
"~/Views/Shared/{0}.cshtml",
|
"~/Views/Shared/{0}.cshtml",
|
||||||
};
|
};
|
||||||
private readonly IActionDescriptorProvider _actionDescriptorProvider;
|
private readonly IActionDescriptorProvider _actionDescriptorProvider;
|
||||||
private readonly IVirtualPathFactory _virtualPathFactory;
|
private readonly IVirtualPathViewFactory _virtualPathFactory;
|
||||||
|
|
||||||
public RazorViewEngine(IActionDescriptorProvider actionDescriptorProvider,
|
public RazorViewEngine(IActionDescriptorProvider actionDescriptorProvider,
|
||||||
IVirtualPathFactory virtualPathFactory)
|
IVirtualPathViewFactory virtualPathFactory)
|
||||||
{
|
{
|
||||||
_actionDescriptorProvider = actionDescriptorProvider;
|
_actionDescriptorProvider = actionDescriptorProvider;
|
||||||
_virtualPathFactory = virtualPathFactory;
|
_virtualPathFactory = virtualPathFactory;
|
||||||
|
|
@ -46,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
||||||
for (int i = 0; i < _viewLocationFormats.Length; i++)
|
for (int i = 0; i < _viewLocationFormats.Length; i++)
|
||||||
{
|
{
|
||||||
string path = String.Format(CultureInfo.InvariantCulture, _viewLocationFormats[i], viewName, controllerName);
|
string path = String.Format(CultureInfo.InvariantCulture, _viewLocationFormats[i], viewName, controllerName);
|
||||||
RazorView view = (RazorView)(await _virtualPathFactory.CreateInstance(path));
|
IView view = await _virtualPathFactory.CreateInstance(path);
|
||||||
if (view != null)
|
if (view != null)
|
||||||
{
|
{
|
||||||
return ViewEngineResult.Found(view);
|
return ViewEngineResult.Found(view);
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public class VirtualFileSystem : IFileSystem
|
||||||
|
{
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
public VirtualFileSystem(IFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo)
|
||||||
|
{
|
||||||
|
string translated = TranslatePath(subpath);
|
||||||
|
return _fileSystem.TryGetFileInfo(translated, out fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents)
|
||||||
|
{
|
||||||
|
string translated = TranslatePath(subpath);
|
||||||
|
return _fileSystem.TryGetDirectoryContents(translated, out contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string TranslatePath(string path)
|
||||||
|
{
|
||||||
|
if (path.StartsWith("~/", StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
path = path.Substring(2);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.CoreServices;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Razor
|
||||||
|
{
|
||||||
|
public class VirtualPathViewFactory : IVirtualPathViewFactory
|
||||||
|
{
|
||||||
|
private readonly IFileSystem _fileSystem;
|
||||||
|
private readonly ICompilationService _compilationService;
|
||||||
|
|
||||||
|
public VirtualPathViewFactory(IFileSystem fileSystem, ICompilationService compilationService)
|
||||||
|
{
|
||||||
|
_fileSystem = fileSystem;
|
||||||
|
_compilationService = compilationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IView> CreateInstance(string virtualPath)
|
||||||
|
{
|
||||||
|
IFileInfo fileInfo;
|
||||||
|
if (_fileSystem.TryGetFileInfo(virtualPath, out fileInfo))
|
||||||
|
{
|
||||||
|
CompilationResult result = await _compilationService.Compile(fileInfo);
|
||||||
|
return (IView)Activator.CreateInstance(result.CompiledType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
|
<package id="Microsoft.AspNet.Razor" version="3.0.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
|
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
|
||||||
|
<package id="Microsoft.Owin.FileSystems" version="2.1.0-rc1" targetFramework="net45" />
|
||||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
||||||
|
|
@ -36,12 +36,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult View()
|
public IActionResult View(string view, object model)
|
||||||
{
|
{
|
||||||
return new ViewResult(_serviceProvider, _viewEngine)
|
return new ViewResult(_serviceProvider, _viewEngine)
|
||||||
{
|
{
|
||||||
ViewName = null,
|
ViewName = view,
|
||||||
Model = null
|
Model = model
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
public static class ActionResultHelperExtensions
|
||||||
|
{
|
||||||
|
public static IActionResult View(this IActionResultHelper actionResultHelper)
|
||||||
|
{
|
||||||
|
return actionResultHelper.View(view: null, model: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IActionResult View(this IActionResultHelper actionResultHelper, string view)
|
||||||
|
{
|
||||||
|
return actionResultHelper.View(view, model: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IActionResult View(this IActionResultHelper actionResultHelper, object model)
|
||||||
|
{
|
||||||
|
return actionResultHelper.View(view: null, model: model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
IActionResult Content(string value);
|
IActionResult Content(string value);
|
||||||
IActionResult Content(string value, string contentType);
|
IActionResult Content(string value, string contentType);
|
||||||
IActionResult Json(object value);
|
IActionResult Json(object value);
|
||||||
IActionResult View();
|
IActionResult View(string view, object model);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@
|
||||||
<Compile Include="ActionInvokerProvider.cs" />
|
<Compile Include="ActionInvokerProvider.cs" />
|
||||||
<Compile Include="ActionResultFactory.cs" />
|
<Compile Include="ActionResultFactory.cs" />
|
||||||
<Compile Include="ActionResultHelper.cs" />
|
<Compile Include="ActionResultHelper.cs" />
|
||||||
|
<Compile Include="ActionResultHelperExtensions.cs" />
|
||||||
<Compile Include="ActionResults\NoContentResult.cs" />
|
<Compile Include="ActionResults\NoContentResult.cs" />
|
||||||
<Compile Include="ActionResults\NegotiatedContentResult.cs" />
|
<Compile Include="ActionResults\NegotiatedContentResult.cs" />
|
||||||
<Compile Include="ActionResults\ContentResult.cs" />
|
<Compile Include="ActionResults\ContentResult.cs" />
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
Model = model;
|
Model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Model { get; private set; }
|
|
||||||
|
|
||||||
public IServiceProvider ServiceProvider { get; set; }
|
public IServiceProvider ServiceProvider { get; set; }
|
||||||
|
|
||||||
|
public object Model { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var viewContext = new ViewContext(context.HttpContext, context.RouteData, Model)
|
var viewContext = new ViewContext(context.HttpContext, context.RouteData, Model)
|
||||||
{
|
{
|
||||||
ServiceProvider = _serviceProvider
|
ServiceProvider = _serviceProvider
|
||||||
|
|
||||||
};
|
};
|
||||||
await view.RenderAsync(viewContext, writer);
|
await view.RenderAsync(viewContext, writer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ namespace MvcSample
|
||||||
|
|
||||||
public IActionResult MyView()
|
public IActionResult MyView()
|
||||||
{
|
{
|
||||||
return Result.View();
|
return Result.View(User());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -46,6 +46,10 @@
|
||||||
<Reference Include="Microsoft.Owin.Diagnostics">
|
<Reference Include="Microsoft.Owin.Diagnostics">
|
||||||
<HintPath>..\packages\Microsoft.Owin.Diagnostics.2.0.2\lib\net40\Microsoft.Owin.Diagnostics.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Owin.Diagnostics.2.0.2\lib\net40\Microsoft.Owin.Diagnostics.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Microsoft.Owin.FileSystems, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Microsoft.Owin.FileSystems.2.1.0-rc1\lib\net40\Microsoft.Owin.FileSystems.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.4.5.11\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||||
|
|
@ -90,6 +94,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="web.config" />
|
<Content Include="web.config" />
|
||||||
<Content Include="project.json" />
|
<Content Include="project.json" />
|
||||||
|
<Content Include="Views\Home\MyView.cshtml" />
|
||||||
|
<Content Include="Views\Shared\_Layout.cshtml" />
|
||||||
<None Include="web.Debug.config">
|
<None Include="web.Debug.config">
|
||||||
<DependentUpon>web.config</DependentUpon>
|
<DependentUpon>web.config</DependentUpon>
|
||||||
</None>
|
</None>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.Razor;
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
using Microsoft.AspNet.Mvc.Routing;
|
using Microsoft.AspNet.Mvc.Routing;
|
||||||
using Microsoft.Owin;
|
using Microsoft.Owin;
|
||||||
|
using Microsoft.Owin.FileSystems;
|
||||||
using Owin;
|
using Owin;
|
||||||
|
|
||||||
[assembly: OwinStartup(typeof(MvcSample.Startup))]
|
[assembly: OwinStartup(typeof(MvcSample.Startup))]
|
||||||
|
|
@ -17,12 +18,17 @@ namespace MvcSample
|
||||||
{
|
{
|
||||||
app.UseErrorPage();
|
app.UseErrorPage();
|
||||||
|
|
||||||
|
string appRoot = Environment.GetEnvironmentVariable("WEB_ROOT") ??
|
||||||
|
AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
|
||||||
var serviceProvider = MvcServices.Create();
|
var serviceProvider = MvcServices.Create();
|
||||||
serviceProvider.AddInstance<IVirtualPathFactory>(new MetadataVirtualPathProvider(GetType().Assembly));
|
var fileSystem = new PhysicalFileSystem(appRoot);
|
||||||
|
serviceProvider.AddInstance<IFileSystem>(new VirtualFileSystem(fileSystem));
|
||||||
|
serviceProvider.AddInstance<ICompilationService>(new RazorCompilationService(new CscBasedCompilationService()));
|
||||||
|
serviceProvider.Add<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||||
serviceProvider.Add<IViewEngine, RazorViewEngine>();
|
serviceProvider.Add<IViewEngine, RazorViewEngine>();
|
||||||
|
|
||||||
var handler = new MvcHandler(serviceProvider);
|
var handler = new MvcHandler(serviceProvider);
|
||||||
|
|
||||||
app.Run(async context =>
|
app.Run(async context =>
|
||||||
{
|
{
|
||||||
// Pretending to be routing
|
// Pretending to be routing
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
@{ Layout = "~/Views/Shared/_Layout.cshtml"; }
|
||||||
|
@DateTime.UtcNow
|
||||||
|
|
@ -6,7 +6,7 @@ namespace MvcSample.Views
|
||||||
[VirtualPath("~/Views/Shared/_Layout.cshtml")]
|
[VirtualPath("~/Views/Shared/_Layout.cshtml")]
|
||||||
public class Layout : RazorView
|
public class Layout : RazorView
|
||||||
{
|
{
|
||||||
protected override void Execute()
|
public override void Execute()
|
||||||
{
|
{
|
||||||
WriteLiteral("<html>");
|
WriteLiteral("<html>");
|
||||||
WriteLiteral("<body>");
|
WriteLiteral("<body>");
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,16 @@ using Microsoft.AspNet.Mvc.Razor;
|
||||||
namespace MvcSample.Views
|
namespace MvcSample.Views
|
||||||
{
|
{
|
||||||
[VirtualPath("~/Views/Home/MyView.cshtml")]
|
[VirtualPath("~/Views/Home/MyView.cshtml")]
|
||||||
public class MyView : RazorView
|
public class MyView : RazorView<User>
|
||||||
{
|
{
|
||||||
protected override void Execute()
|
public override void Execute()
|
||||||
{
|
{
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
WriteLiteral("<div style=\"border: 1px solid black\">The time is now");
|
WriteLiteral("<div style=\"border: 1px solid black\">The time is now");
|
||||||
Write(new HtmlString(DateTime.UtcNow.ToString()));
|
Write(new HtmlString(DateTime.UtcNow.ToString()));
|
||||||
|
WriteLiteral("<em>");
|
||||||
|
Write(Model.Name);
|
||||||
|
Write("</em>");
|
||||||
WriteLiteral("</div>");
|
WriteLiteral("</div>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>No title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="margin: auto; width: 900px">
|
||||||
|
<h2>Hello world</h2>
|
||||||
|
@RenderBody()
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.0.0" targetFramework="net45" />
|
<package id="Microsoft.AspNet.WebApi.Client" version="5.0.0" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
|
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
|
||||||
<package id="Microsoft.Owin.Diagnostics" version="2.0.2" targetFramework="net45" />
|
<package id="Microsoft.Owin.Diagnostics" version="2.0.2" targetFramework="net45" />
|
||||||
|
<package id="Microsoft.Owin.FileSystems" version="2.1.0-rc1" targetFramework="net45" />
|
||||||
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
|
||||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||||
<package id="OwinHost" version="2.0.2" targetFramework="net45" />
|
<package id="OwinHost" version="2.0.2" targetFramework="net45" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue