Adding view engines
This commit is contained in:
parent
1ba47fa480
commit
b918cb8170
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class HtmlString
|
||||
{
|
||||
private readonly string _input;
|
||||
|
||||
public HtmlString(string input)
|
||||
{
|
||||
_input = input;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public interface IVirtualPathFactory
|
||||
{
|
||||
Task<object> CreateInstance(string virtualPath);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class MetadataVirtualPathProvider : IVirtualPathFactory
|
||||
{
|
||||
private readonly Dictionary<string, Type> _viewMetadata;
|
||||
|
||||
public MetadataVirtualPathProvider(Assembly assembly)
|
||||
{
|
||||
var metadataType = assembly.GetType("ViewMetadata");
|
||||
if (metadataType != null)
|
||||
{
|
||||
object metadata = metadataType.GetProperty("Metadata", BindingFlags.Static | BindingFlags.Public)
|
||||
.GetValue(obj: null);
|
||||
|
||||
_viewMetadata = new Dictionary<string, Type>((Dictionary<string, Type>)metadata, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Code to support precompiled views generated via RazorGenerator
|
||||
_viewMetadata = assembly.GetExportedTypes()
|
||||
.Where(type => typeof(RazorView).IsAssignableFrom(type))
|
||||
.ToDictionary(type => GetVirtualPath(type), StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<object> CreateInstance(string virtualPath)
|
||||
{
|
||||
Type type;
|
||||
object view = null;
|
||||
if (_viewMetadata.TryGetValue(virtualPath, out type))
|
||||
{
|
||||
view = (RazorView)Activator.CreateInstance(type);
|
||||
}
|
||||
return Task.FromResult(view);
|
||||
}
|
||||
|
||||
private static string GetVirtualPath(Type type)
|
||||
{
|
||||
VirtualPathAttribute attribute = type.GetCustomAttribute<VirtualPathAttribute>();
|
||||
return attribute.VirtualPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Microsoft.AspNet.Mvc.Razor</RootNamespace>
|
||||
<AssemblyName>Microsoft.AspNet.Mvc.Razor</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Owin, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Microsoft.Owin.2.0.2\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="HtmlString.cs" />
|
||||
<Compile Include="IVirtualPathFactory.cs" />
|
||||
<Compile Include="MetadataVirtualPathProvider.cs" />
|
||||
<Compile Include="RazorView.cs" />
|
||||
<Compile Include="RazorViewEngine.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="VirtualPathAttribute.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.CoreServices\Microsoft.AspNet.CoreServices.csproj">
|
||||
<Project>{ec38534c-a2d1-413f-97d1-55eef5d2fb71}</Project>
|
||||
<Name>Microsoft.AspNet.CoreServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.Mvc\Microsoft.AspNet.Mvc.csproj">
|
||||
<Project>{2a0c26f1-0240-4ae1-ae00-4691c291b122}</Project>
|
||||
<Name>Microsoft.AspNet.Mvc</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- 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.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Microsoft.AspNet.Mvc.Razor")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Microsoft.AspNet.Mvc.Razor")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("af993404-738b-4c26-94af-38bec7c4e487")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.CoreServices;
|
||||
using Microsoft.Owin;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public abstract class RazorView : IView
|
||||
{
|
||||
public IOwinContext Context { get; set; }
|
||||
|
||||
public object Model { get; set; }
|
||||
|
||||
public string Layout { get; set; }
|
||||
|
||||
protected TextWriter Output { get; set; }
|
||||
|
||||
private string BodyContent { get; set; }
|
||||
|
||||
public async Task RenderAsync(ViewContext context, TextWriter writer)
|
||||
{
|
||||
Model = context.Model;
|
||||
|
||||
var contentBuilder = new StringBuilder(1024);
|
||||
using (var bodyWriter = new StringWriter(contentBuilder))
|
||||
{
|
||||
Output = bodyWriter;
|
||||
Execute();
|
||||
}
|
||||
|
||||
string bodyContent = contentBuilder.ToString();
|
||||
if (!String.IsNullOrEmpty(Layout))
|
||||
{
|
||||
await RenderLayoutAsync(context, writer, bodyContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
await writer.WriteAsync(bodyContent);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RenderLayoutAsync(ViewContext context, TextWriter writer, string bodyContent)
|
||||
{
|
||||
var virtualPathFactory = context.ServiceProvider.GetService<IVirtualPathFactory>();
|
||||
RazorView razorView = (RazorView)(await virtualPathFactory.CreateInstance(Layout));
|
||||
if (razorView == null)
|
||||
{
|
||||
string message = String.Format(CultureInfo.CurrentCulture, "The layout view '{0}' could not be located.", Layout);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
razorView.BodyContent = bodyContent;
|
||||
await razorView.RenderAsync(context, writer);
|
||||
}
|
||||
|
||||
protected abstract void Execute();
|
||||
|
||||
public virtual void Write(object value)
|
||||
{
|
||||
WriteTo(Output, value);
|
||||
}
|
||||
|
||||
public virtual void WriteTo(TextWriter writer, object content)
|
||||
{
|
||||
if (content != null)
|
||||
{
|
||||
var htmlString = content as HtmlString;
|
||||
if (htmlString != null)
|
||||
{
|
||||
writer.Write(content.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
WebUtility.HtmlEncode(content.ToString(), writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteLiteral(object value)
|
||||
{
|
||||
WriteLiteralTo(Output, value);
|
||||
}
|
||||
|
||||
public virtual void WriteLiteralTo(TextWriter writer, object text)
|
||||
{
|
||||
if (text != null)
|
||||
{
|
||||
writer.Write(text.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void RenderBody()
|
||||
{
|
||||
if (BodyContent != null)
|
||||
{
|
||||
WriteLiteral(BodyContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
public class RazorViewEngine : IViewEngine
|
||||
{
|
||||
private static readonly string[] _viewLocationFormats = new[]
|
||||
{
|
||||
"~/Views/{1}/{0}.cshtml",
|
||||
"~/Views/Shared/{0}.cshtml",
|
||||
};
|
||||
private readonly IActionDescriptorProvider _actionDescriptorProvider;
|
||||
private readonly IVirtualPathFactory _virtualPathFactory;
|
||||
|
||||
public RazorViewEngine(IActionDescriptorProvider actionDescriptorProvider,
|
||||
IVirtualPathFactory virtualPathFactory)
|
||||
{
|
||||
_actionDescriptorProvider = actionDescriptorProvider;
|
||||
_virtualPathFactory = virtualPathFactory;
|
||||
}
|
||||
|
||||
public IEnumerable<string> ViewLocationFormats
|
||||
{
|
||||
get { return _viewLocationFormats; }
|
||||
}
|
||||
|
||||
public async Task<ViewEngineResult> FindView(RequestContext requestContext, string viewName)
|
||||
{
|
||||
var actionDescriptor = _actionDescriptorProvider.CreateDescriptor(requestContext) as ControllerBasedActionDescriptor;
|
||||
|
||||
if (actionDescriptor == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(viewName))
|
||||
{
|
||||
viewName = actionDescriptor.ActionName;
|
||||
}
|
||||
|
||||
string controllerName = actionDescriptor.ControllerName;
|
||||
var searchedLocations = new List<string>(_viewLocationFormats.Length);
|
||||
for (int i = 0; i < _viewLocationFormats.Length; i++)
|
||||
{
|
||||
string path = String.Format(CultureInfo.InvariantCulture, _viewLocationFormats[i], viewName, controllerName);
|
||||
RazorView view = (RazorView)(await _virtualPathFactory.CreateInstance(path));
|
||||
if (view != null)
|
||||
{
|
||||
return ViewEngineResult.Found(view);
|
||||
}
|
||||
searchedLocations.Add(path);
|
||||
}
|
||||
return ViewEngineResult.NotFound(searchedLocations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
|
||||
public class VirtualPathAttribute : Attribute
|
||||
{
|
||||
public VirtualPathAttribute(string virtualPath)
|
||||
{
|
||||
VirtualPath = virtualPath;
|
||||
}
|
||||
|
||||
public string VirtualPath { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net45" />
|
||||
<package id="Owin" version="1.0" targetFramework="net45" />
|
||||
</packages>
|
||||
|
|
@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MvcSample", "MvcSample\MvcS
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.CoreServices", "Microsoft.AspNet.CoreServices\Microsoft.AspNet.CoreServices.csproj", "{EC38534C-A2D1-413F-97D1-55EEF5D2FB71}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNet.Mvc.Razor", "Microsoft.AspNet.Mvc.Razor\Microsoft.AspNet.Mvc.Razor.csproj", "{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -27,6 +29,10 @@ Global
|
|||
{EC38534C-A2D1-413F-97D1-55EEF5D2FB71}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC38534C-A2D1-413F-97D1-55EEF5D2FB71}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC38534C-A2D1-413F-97D1-55EEF5D2FB71}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{224A14D0-ECA7-441C-AE89-B6E66A57EF9B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.CoreServices;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ActionResultHelper : IActionResultHelper
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IViewEngine _viewEngine;
|
||||
|
||||
public ActionResultHelper(IServiceProvider serviceProvider, IViewEngine viewEngine)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_viewEngine = viewEngine;
|
||||
}
|
||||
|
||||
public IActionResult Content(string value)
|
||||
{
|
||||
return new ContentResult
|
||||
|
|
@ -28,7 +38,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
public IActionResult View()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return new ViewResult(_serviceProvider, _viewEngine)
|
||||
{
|
||||
ViewName = null,
|
||||
Model = null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,9 @@
|
|||
<Compile Include="DefaultContentNegotiator.cs" />
|
||||
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
||||
<Compile Include="Formatters\JQeryMvcForUrlEncodedFormatter.cs" />
|
||||
<Compile Include="View\CompositeViewEngine.cs" />
|
||||
<Compile Include="View\IView.cs" />
|
||||
<Compile Include="View\IViewEngine.cs" />
|
||||
<Compile Include="FormattingUtilities.cs" />
|
||||
<Compile Include="Extensions\TypeExtensions.cs" />
|
||||
<Compile Include="IOwinContentNegotiator.cs" />
|
||||
|
|
@ -84,6 +87,9 @@
|
|||
<Compile Include="MvcServices.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Routing\IRouteData.cs" />
|
||||
<Compile Include="View\ViewContext.cs" />
|
||||
<Compile Include="View\ViewEngineResult.cs" />
|
||||
<Compile Include="View\ViewResult.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
_serviceProvider = serviceProvider ?? MvcServices.Create();
|
||||
}
|
||||
|
||||
//public ServiceProvider ServiceProvider
|
||||
//{
|
||||
// get { return (ServiceProvider)_serviceProvider; }
|
||||
//}
|
||||
|
||||
public Task ExecuteAsync(IOwinContext context, IRouteData routeData)
|
||||
{
|
||||
var requestContext = new RequestContext(context, routeData);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
public static class MvcServices
|
||||
{
|
||||
public static IServiceProvider Create()
|
||||
public static ServiceProvider Create()
|
||||
{
|
||||
var services = new ServiceProvider();
|
||||
DoCallback((service, implementation) => services.Add(service, implementation));
|
||||
|
|
@ -21,6 +21,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
callback(typeof(IActionResultFactory), typeof(ActionResultFactory));
|
||||
callback(typeof(IContentNegotiator), typeof(DefaultContentNegotiator));
|
||||
|
||||
|
||||
// TODO: Should be many
|
||||
callback(typeof(IActionDescriptorProvider), typeof(ActionDescriptorProvider));
|
||||
callback(typeof(IActionInvokerProvider), typeof(ActionInvokerProvider));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.View
|
||||
{
|
||||
public class CompositeViewEngine : IViewEngine
|
||||
{
|
||||
private readonly List<IViewEngine> _viewEngines;
|
||||
|
||||
public CompositeViewEngine()
|
||||
: this(Enumerable.Empty<IViewEngine>())
|
||||
{
|
||||
}
|
||||
|
||||
public CompositeViewEngine(IEnumerable<IViewEngine> viewEngines)
|
||||
{
|
||||
_viewEngines = viewEngines.ToList();
|
||||
}
|
||||
|
||||
public void Insert(int index, IViewEngine viewEngine)
|
||||
{
|
||||
_viewEngines.Insert(index, viewEngine);
|
||||
}
|
||||
|
||||
public void Add(IViewEngine viewEngine)
|
||||
{
|
||||
_viewEngines.Add(viewEngine);
|
||||
}
|
||||
|
||||
public async Task<ViewEngineResult> FindView(RequestContext controllerContext, string viewName)
|
||||
{
|
||||
if (_viewEngines.Count == 0)
|
||||
{
|
||||
return ViewEngineResult.NotFound(Enumerable.Empty<string>());
|
||||
}
|
||||
|
||||
var searchedPaths = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
for (int i = 0; i < _viewEngines.Count; i++)
|
||||
{
|
||||
ViewEngineResult result = await _viewEngines[i].FindView(controllerContext, viewName);
|
||||
if (result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
foreach (string location in result.SearchedLocations)
|
||||
{
|
||||
searchedPaths.Add(location);
|
||||
}
|
||||
}
|
||||
|
||||
return ViewEngineResult.NotFound(searchedPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IView
|
||||
{
|
||||
Task RenderAsync(ViewContext context, TextWriter writer);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IViewEngine
|
||||
{
|
||||
Task<ViewEngineResult> FindView(RequestContext requestContext, string viewName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Owin;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ViewContext : RequestContext
|
||||
{
|
||||
public ViewContext(IOwinContext context, IRouteData routeData, object model) :
|
||||
base(context, routeData)
|
||||
{
|
||||
Model = model;
|
||||
}
|
||||
|
||||
public object Model { get; private set; }
|
||||
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ViewEngineResult
|
||||
{
|
||||
private ViewEngineResult()
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<string> SearchedLocations { get; private set; }
|
||||
|
||||
public IView View { get; private set; }
|
||||
|
||||
public bool Success
|
||||
{
|
||||
get { return View != null; }
|
||||
}
|
||||
|
||||
public static ViewEngineResult NotFound(IEnumerable<string> searchedLocations)
|
||||
{
|
||||
if (searchedLocations == null)
|
||||
{
|
||||
throw new ArgumentNullException("searchedLocations");
|
||||
}
|
||||
|
||||
return new ViewEngineResult
|
||||
{
|
||||
SearchedLocations = searchedLocations
|
||||
};
|
||||
}
|
||||
|
||||
public static ViewEngineResult Found(IView view)
|
||||
{
|
||||
if (view == null)
|
||||
{
|
||||
throw new ArgumentNullException("view");
|
||||
}
|
||||
|
||||
return new ViewEngineResult
|
||||
{
|
||||
View = view
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.CoreServices;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ViewResult : IActionResult
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IViewEngine _viewEngine;
|
||||
|
||||
public ViewResult(IServiceProvider serviceProvider, IViewEngine viewEngine)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_viewEngine = viewEngine;
|
||||
}
|
||||
|
||||
public string ViewName {get; set; }
|
||||
|
||||
public object Model { get; set; }
|
||||
|
||||
public async Task ExecuteResultAsync(RequestContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException("context");
|
||||
}
|
||||
|
||||
IView view = await FindView(context, ViewName);
|
||||
using (view as IDisposable)
|
||||
{
|
||||
context.HttpContext.Response.ContentType = "text/html";
|
||||
using (var writer = new StreamWriter(context.HttpContext.Response.Body, Encoding.UTF8, 1024, leaveOpen: true))
|
||||
{
|
||||
var viewContext = new ViewContext(context.HttpContext, context.RouteData, Model)
|
||||
{
|
||||
ServiceProvider = _serviceProvider
|
||||
|
||||
};
|
||||
await view.RenderAsync(viewContext, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IView> FindView(RequestContext requestContext, string viewName)
|
||||
{
|
||||
ViewEngineResult result = await _viewEngine.FindView(requestContext, viewName);
|
||||
if (!result.Success)
|
||||
{
|
||||
string locationsText = String.Join(Environment.NewLine, result.SearchedLocations);
|
||||
const string message = @"The view '{0}' was not found. The following locations were searched:{1}.";
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, message, viewName, locationsText));
|
||||
}
|
||||
|
||||
return result.View;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,5 +47,10 @@ namespace MvcSample
|
|||
|
||||
return user;
|
||||
}
|
||||
|
||||
public IActionResult MyView()
|
||||
{
|
||||
return Result.View();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,8 +70,18 @@
|
|||
<Compile Include="Models\Class1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Startup.cs" />
|
||||
<Compile Include="Views\Layout.cs" />
|
||||
<Compile Include="Views\MyView.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.CoreServices\Microsoft.AspNet.CoreServices.csproj">
|
||||
<Project>{ec38534c-a2d1-413f-97d1-55eef5d2fb71}</Project>
|
||||
<Name>Microsoft.AspNet.CoreServices</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.Mvc.Razor\Microsoft.AspNet.Mvc.Razor.csproj">
|
||||
<Project>{224a14d0-eca7-441c-ae89-b6e66a57ef9b}</Project>
|
||||
<Name>Microsoft.AspNet.Mvc.Razor</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Microsoft.AspNet.Mvc\Microsoft.AspNet.Mvc.csproj">
|
||||
<Project>{2a0c26f1-0240-4ae1-ae00-4691c291b122}</Project>
|
||||
<Name>Microsoft.AspNet.Mvc</Name>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.CoreServices;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Owin;
|
||||
using Owin;
|
||||
|
|
@ -15,8 +17,12 @@ namespace MvcSample
|
|||
{
|
||||
app.UseErrorPage();
|
||||
|
||||
var handler = new MvcHandler();
|
||||
|
||||
var serviceProvider = MvcServices.Create();
|
||||
serviceProvider.AddInstance<IVirtualPathFactory>(new MetadataVirtualPathProvider(GetType().Assembly));
|
||||
serviceProvider.Add<IViewEngine, RazorViewEngine>();
|
||||
|
||||
var handler = new MvcHandler(serviceProvider);
|
||||
|
||||
app.Run(async context =>
|
||||
{
|
||||
// Pretending to be routing
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ViewMetadata
|
||||
{
|
||||
public static Dictionary<string, Type> Metadata
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, Type>
|
||||
{
|
||||
{
|
||||
"~/Views/Home/MyView.cshtml",
|
||||
typeof(MvcSample.Views.MyView)
|
||||
},
|
||||
{
|
||||
"~/Views/Shared/_Layout.cshtml",
|
||||
typeof(MvcSample.Views.Layout)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
|
||||
namespace MvcSample.Views
|
||||
{
|
||||
[VirtualPath("~/Views/Shared/_Layout.cshtml")]
|
||||
public class Layout : RazorView
|
||||
{
|
||||
protected override void Execute()
|
||||
{
|
||||
WriteLiteral("<html>");
|
||||
WriteLiteral("<body>");
|
||||
WriteLiteral("<h1>Hello world</h1>");
|
||||
WriteLiteral("<div id=\"main\"");
|
||||
RenderBody();
|
||||
WriteLiteral("</div>");
|
||||
WriteLiteral("</body></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
|
||||
namespace MvcSample.Views
|
||||
{
|
||||
[VirtualPath("~/Views/Home/MyView.cshtml")]
|
||||
public class MyView : RazorView
|
||||
{
|
||||
protected override void Execute()
|
||||
{
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
WriteLiteral("<div style=\"border: 1px solid black\">The time is now");
|
||||
Write(new HtmlString(DateTime.UtcNow.ToString()));
|
||||
WriteLiteral("</div>");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue