parent
b8ab5c5063
commit
e28adbfb3d
|
|
@ -39,6 +39,7 @@
|
|||
<Content Include="Views\Shared\HelloWorldPartial.cshtml" />
|
||||
<Content Include="Views\Shared\MyView.cshtml" />
|
||||
<Content Include="Views\Shared\_Layout.cshtml" />
|
||||
<Content Include="Views\_ViewStart.cshtml" />
|
||||
<Content Include="web.config" />
|
||||
<Content Include="web.Debug.config" />
|
||||
<Content Include="web.Release.config" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@using MvcSample.Web.Models
|
||||
@model User
|
||||
@{
|
||||
Layout = "/Views/Shared/_Layout.cshtml";
|
||||
ViewBag.Title = "Home Page";
|
||||
string nullValue = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,12 +27,6 @@
|
|||
<div class="container body-content">
|
||||
@RenderBody()
|
||||
<hr />
|
||||
<address>
|
||||
@if (@Model != null)
|
||||
{
|
||||
@Model.Address
|
||||
}
|
||||
</address>
|
||||
<footer>
|
||||
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
@{
|
||||
Layout = "/Views/Shared/_Layout.cshtml";
|
||||
}
|
||||
|
|
@ -16,6 +16,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
/// </summary>
|
||||
ViewContext ViewContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the page.
|
||||
/// </summary>
|
||||
string Path { get; set; }
|
||||
|
||||
string BodyContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
/// <summary>
|
||||
/// Creates a <see cref="IRazorPage"/> for the specified path.
|
||||
/// </summary>
|
||||
/// <param name="viewPath">The path to locate the RazorPage.</param>
|
||||
/// <param name="path">The path to locate the page.</param>
|
||||
/// <returns>The IRazorPage instance if it exists, null otherwise.</returns>
|
||||
IRazorPage CreateInstance(string viewPath);
|
||||
IRazorPage CreateInstance(string path);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines methods for locating ViewStart pages that are applicable to a page.
|
||||
/// </summary>
|
||||
public interface IViewStartProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Given a view path, returns a sequence of ViewStart instances
|
||||
/// that are applicable to the specified view.
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the page to locate ViewStart files for.</param>
|
||||
/// <returns>A sequence of <see cref="IRazorPage"/> that represent ViewStart.</returns>
|
||||
IEnumerable<IRazorPage> GetViewStartPages(string path);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,9 @@
|
|||
<Compile Include="Compilation\RoslynCompilationService.cs" />
|
||||
<Compile Include="Extensions\DictionaryExtensions.cs" />
|
||||
<Compile Include="IRazorPage.cs" />
|
||||
<Compile Include="IViewStartProvider.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ViewStartProvider.cs" />
|
||||
<Compile Include="VirtualPathRazorPageFactory.cs" />
|
||||
<Compile Include="HelperResult.cs" />
|
||||
<Compile Include="IRazorPageActivator.cs" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNet.Mvc.Razor.Test")]
|
||||
|
|
@ -42,6 +42,9 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ViewContext ViewContext { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
|
|
@ -17,6 +18,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
private readonly IRazorPageFactory _pageFactory;
|
||||
private readonly IRazorPageActivator _pageActivator;
|
||||
private readonly IViewStartProvider _viewStartProvider;
|
||||
private readonly IRazorPage _page;
|
||||
private readonly bool _executeViewHierarchy;
|
||||
|
||||
|
|
@ -30,11 +32,13 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
/// view start and layout pages are executed as part of the executing the page.</param>
|
||||
public RazorView([NotNull] IRazorPageFactory pageFactory,
|
||||
[NotNull] IRazorPageActivator pageActivator,
|
||||
[NotNull] IViewStartProvider viewStartProvider,
|
||||
[NotNull] IRazorPage page,
|
||||
bool executeViewHierarchy)
|
||||
{
|
||||
_pageFactory = pageFactory;
|
||||
_pageActivator = pageActivator;
|
||||
_viewStartProvider = viewStartProvider;
|
||||
_page = page;
|
||||
_executeViewHierarchy = executeViewHierarchy;
|
||||
}
|
||||
|
|
@ -44,7 +48,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
if (_executeViewHierarchy)
|
||||
{
|
||||
var bodyContent = await RenderPageAsync(_page, context);
|
||||
var bodyContent = await RenderPageAsync(_page, context, executeViewStart: true);
|
||||
await RenderLayoutAsync(context, bodyContent);
|
||||
}
|
||||
else
|
||||
|
|
@ -53,7 +57,9 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<string> RenderPageAsync(IRazorPage page, ViewContext context)
|
||||
private async Task<string> RenderPageAsync(IRazorPage page,
|
||||
ViewContext context,
|
||||
bool executeViewStart)
|
||||
{
|
||||
var contentBuilder = new StringBuilder(1024);
|
||||
using (var bodyWriter = new StringWriter(contentBuilder))
|
||||
|
|
@ -64,6 +70,11 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
context.Writer = bodyWriter;
|
||||
try
|
||||
{
|
||||
if (executeViewStart)
|
||||
{
|
||||
// Execute view starts using the same context + writer as the page to render.
|
||||
await RenderViewStartAsync(context);
|
||||
}
|
||||
await RenderPageCoreAsync(page, context);
|
||||
}
|
||||
finally
|
||||
|
|
@ -86,6 +97,19 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
await page.ExecuteAsync();
|
||||
}
|
||||
|
||||
private async Task RenderViewStartAsync(ViewContext context)
|
||||
{
|
||||
var viewStarts = _viewStartProvider.GetViewStartPages(_page.Path);
|
||||
|
||||
foreach (var viewStart in viewStarts)
|
||||
{
|
||||
await RenderPageCoreAsync(viewStart, context);
|
||||
|
||||
// Copy over interesting properties from the ViewStart page to the entry page.
|
||||
_page.Layout = viewStart.Layout;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RenderLayoutAsync(ViewContext context,
|
||||
string bodyContent)
|
||||
{
|
||||
|
|
@ -104,7 +128,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
layoutPage.PreviousSectionWriters = previousPage.SectionWriters;
|
||||
layoutPage.BodyContent = bodyContent;
|
||||
|
||||
bodyContent = await RenderPageAsync(layoutPage, context);
|
||||
bodyContent = await RenderPageAsync(layoutPage, context, executeViewStart: false);
|
||||
|
||||
// Verify that RenderBody is called, or that RenderSection is called for all sections
|
||||
layoutPage.EnsureBodyAndSectionsWereRendered();
|
||||
|
|
|
|||
|
|
@ -28,12 +28,15 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
private readonly IRazorPageFactory _pageFactory;
|
||||
private readonly IRazorPageActivator _viewActivator;
|
||||
private readonly IViewStartProvider _viewStartProvider;
|
||||
|
||||
public RazorViewEngine(IRazorPageFactory pageFactory,
|
||||
IRazorPageActivator viewActivator)
|
||||
IRazorPageActivator viewActivator,
|
||||
IViewStartProvider viewStartProvider)
|
||||
{
|
||||
_pageFactory = pageFactory;
|
||||
_viewActivator = viewActivator;
|
||||
_viewStartProvider = viewStartProvider;
|
||||
}
|
||||
|
||||
public IEnumerable<string> ViewLocationFormats
|
||||
|
|
@ -96,6 +99,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
{
|
||||
var view = new RazorView(_pageFactory,
|
||||
_viewActivator,
|
||||
_viewStartProvider,
|
||||
page,
|
||||
executeViewHierarchy: !partial);
|
||||
return ViewEngineResult.Found(viewName, view);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Runtime;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class ViewStartProvider : IViewStartProvider
|
||||
{
|
||||
private const string ViewStartFileName = "_ViewStart.cshtml";
|
||||
private readonly string _appRoot;
|
||||
private readonly IRazorPageFactory _pageFactory;
|
||||
|
||||
public ViewStartProvider(IApplicationEnvironment appEnv,
|
||||
IRazorPageFactory pageFactory)
|
||||
{
|
||||
_appRoot = TrimTrailingSlash(appEnv.ApplicationBasePath);
|
||||
_pageFactory = pageFactory;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<IRazorPage> GetViewStartPages([NotNull] string path)
|
||||
{
|
||||
var viewStartLocations = GetViewStartLocations(path);
|
||||
var viewStarts = viewStartLocations.Select(_pageFactory.CreateInstance)
|
||||
.Where(p => p != null)
|
||||
.ToArray();
|
||||
|
||||
// GetViewStartLocations return ViewStarts inside-out that is the _ViewStart closest to the page
|
||||
// is the first: e.g. [ /Views/Home/_ViewStart, /Views/_ViewStart, /_ViewStart ]
|
||||
// However they need to be executed outside in, so we'll reverse the sequence.
|
||||
Array.Reverse(viewStarts);
|
||||
|
||||
return viewStarts;
|
||||
}
|
||||
|
||||
internal IEnumerable<string> GetViewStartLocations(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
var viewStartLocations = new List<string>();
|
||||
var currentDir = GetViewDirectory(_appRoot, path);
|
||||
while (IsSubDirectory(_appRoot, currentDir))
|
||||
{
|
||||
viewStartLocations.Add(Path.Combine(currentDir, ViewStartFileName));
|
||||
currentDir = Path.GetDirectoryName(currentDir);
|
||||
}
|
||||
|
||||
return viewStartLocations;
|
||||
}
|
||||
|
||||
private static bool IsSubDirectory(string appRoot, string currentDir)
|
||||
{
|
||||
return currentDir.StartsWith(appRoot, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static string GetViewDirectory(string appRoot, string viewPath)
|
||||
{
|
||||
if (viewPath.StartsWith("~/"))
|
||||
{
|
||||
viewPath = viewPath.Substring(2);
|
||||
}
|
||||
else if (viewPath[0] == Path.DirectorySeparatorChar ||
|
||||
viewPath[0] == Path.AltDirectorySeparatorChar)
|
||||
{
|
||||
viewPath = viewPath.Substring(1);
|
||||
}
|
||||
|
||||
var viewDir = Path.GetDirectoryName(viewPath);
|
||||
return Path.GetFullPath(Path.Combine(appRoot, viewDir));
|
||||
}
|
||||
|
||||
private static string TrimTrailingSlash(string path)
|
||||
{
|
||||
if (path.Length > 0 &&
|
||||
path[path.Length - 1] == Path.DirectorySeparatorChar)
|
||||
{
|
||||
return path.Substring(0, path.Length - 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,14 +30,15 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRazorPage CreateInstance([NotNull] string viewPath)
|
||||
public IRazorPage CreateInstance([NotNull] string path)
|
||||
{
|
||||
var fileInfo = _fileInfoCache.GetFileInfo(viewPath);
|
||||
var fileInfo = _fileInfoCache.GetFileInfo(path);
|
||||
|
||||
if (fileInfo != null)
|
||||
{
|
||||
var result = _compilationService.Compile(fileInfo);
|
||||
var page = (IRazorPage)_activator.CreateInstance(_serviceProvider, result.CompiledType);
|
||||
page.Path = path;
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
yield return describe.Singleton<IViewEngineProvider, DefaultViewEngineProvider>();
|
||||
yield return describe.Scoped<ICompositeViewEngine, CompositeViewEngine>();
|
||||
yield return describe.Singleton<IRazorCompilationService, RazorCompilationService>();
|
||||
yield return describe.Singleton<IViewStartProvider, ViewStartProvider>();
|
||||
|
||||
yield return describe.Singleton<IRazorPageActivator, RazorPageActivator>();
|
||||
// Virtual path view factory needs to stay scoped so views can get get scoped services.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
<Compile Include="RazorPageTest.cs" />
|
||||
<Compile Include="RazorViewTest.cs" />
|
||||
<Compile Include="SpanFactory.cs" />
|
||||
<Compile Include="ViewStartProviderTest.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -160,15 +160,35 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
|
|||
}, result.SearchedLocations);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindView_ReturnsRazorView_IfLookupWasSuccessful()
|
||||
{
|
||||
// Arrange
|
||||
var pageFactory = new Mock<IRazorPageFactory>();
|
||||
pageFactory.Setup(p => p.CreateInstance(It.IsAny<string>()))
|
||||
.Returns(Mock.Of<IRazorPage>());
|
||||
var viewEngine = new RazorViewEngine(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
Mock.Of<IViewStartProvider>());
|
||||
|
||||
// Act
|
||||
var result = viewEngine.FindView(_controllerTestContext, "test-view");
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Success);
|
||||
Assert.IsType<RazorView>(result.View);
|
||||
Assert.Equal("/Views/bar/test-view.cshtml", result.ViewName);
|
||||
}
|
||||
|
||||
private IViewEngine CreateSearchLocationViewEngineTester()
|
||||
{
|
||||
var pageFactory = new Mock<IRazorPageFactory>();
|
||||
pageFactory.Setup(vpf => vpf.CreateInstance(It.IsAny<string>()))
|
||||
.Returns<RazorPage>(null);
|
||||
|
||||
var pageActivator = Mock.Of<IRazorPageActivator>();
|
||||
|
||||
var viewEngine = new RazorViewEngine(pageFactory.Object, pageActivator);
|
||||
var viewEngine = new RazorViewEngine(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
Mock.Of<IViewStartProvider>());
|
||||
|
||||
return viewEngine;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -27,6 +27,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
});
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: false);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -51,9 +52,10 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
Assert.Same(viewData, v.ViewContext.ViewData);
|
||||
});
|
||||
var activator = new Mock<IRazorPageActivator>();
|
||||
|
||||
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
activator.Object,
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: false);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -86,6 +88,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Verifiable();
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
activator.Object,
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: false);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -98,15 +101,17 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderAsync_WithoutHierarchy_DoesNotExecuteLayoutPages()
|
||||
public async Task RenderAsync_WithoutHierarchy_DoesNotExecuteLayoutOrViewStartPages()
|
||||
{
|
||||
var page = new TestableRazorPage(v =>
|
||||
{
|
||||
v.Layout = LayoutPath;
|
||||
});
|
||||
var pageFactory = new Mock<IRazorPageFactory>();
|
||||
var viewStartProvider = CreateViewStartProvider();
|
||||
var view = new RazorView(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
viewStartProvider,
|
||||
page,
|
||||
executeViewHierarchy: false);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -116,6 +121,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
|
||||
// Assert
|
||||
pageFactory.Verify(v => v.CreateInstance(It.IsAny<string>()), Times.Never());
|
||||
Mock.Get(viewStartProvider).Verify(v => v.GetViewStartPages(It.IsAny<string>()), Times.Never());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -129,6 +135,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
});
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -152,6 +159,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
});
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -177,6 +185,49 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Verifiable();
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
activator.Object,
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
||||
// Act
|
||||
await view.RenderAsync(viewContext);
|
||||
|
||||
// Assert
|
||||
activator.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderAsync_WithHierarchy_ExecutesViewStart()
|
||||
{
|
||||
// Arrange
|
||||
var actualLayoutPath = "";
|
||||
var layoutPath = "/Views/_Shared/_Layout.cshtml";
|
||||
var viewStart1 = new TestableRazorPage(v =>
|
||||
{
|
||||
v.Layout = "/fake-layout-path";
|
||||
});
|
||||
var viewStart2 = new TestableRazorPage(v =>
|
||||
{
|
||||
v.Layout = layoutPath;
|
||||
});
|
||||
var page = new TestableRazorPage(v =>
|
||||
{
|
||||
// This path must have been set as a consequence of running viewStart
|
||||
actualLayoutPath = v.Layout;
|
||||
// Clear out layout so we don't render it
|
||||
v.Layout = null;
|
||||
});
|
||||
var activator = new Mock<IRazorPageActivator>();
|
||||
activator.Setup(a => a.Activate(viewStart1, It.IsAny<ViewContext>()))
|
||||
.Verifiable();
|
||||
activator.Setup(a => a.Activate(viewStart2, It.IsAny<ViewContext>()))
|
||||
.Verifiable();
|
||||
activator.Setup(a => a.Activate(page, It.IsAny<ViewContext>()))
|
||||
.Verifiable();
|
||||
var view = new RazorView(Mock.Of<IRazorPageFactory>(),
|
||||
activator.Object,
|
||||
CreateViewStartProvider(viewStart1, viewStart2),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -231,6 +282,7 @@ foot-content";
|
|||
|
||||
var view = new RazorView(pageFactory.Object,
|
||||
activator.Object,
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -264,6 +316,7 @@ foot-content";
|
|||
|
||||
var view = new RazorView(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -290,6 +343,7 @@ foot-content";
|
|||
|
||||
var view = new RazorView(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -344,6 +398,7 @@ body-content";
|
|||
|
||||
var view = new RazorView(pageFactory.Object,
|
||||
Mock.Of<IRazorPageActivator>(),
|
||||
CreateViewStartProvider(),
|
||||
page,
|
||||
executeViewHierarchy: true);
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
|
@ -357,8 +412,8 @@ body-content";
|
|||
|
||||
private static ViewContext CreateViewContext(RazorView view)
|
||||
{
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var actionContext = new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var actionContext = new ActionContext(httpContext, routeData: null, actionDescriptor: null);
|
||||
return new ViewContext(
|
||||
actionContext,
|
||||
view,
|
||||
|
|
@ -366,6 +421,16 @@ body-content";
|
|||
new StringWriter());
|
||||
}
|
||||
|
||||
private static IViewStartProvider CreateViewStartProvider(params IRazorPage[] viewStartPages)
|
||||
{
|
||||
viewStartPages = viewStartPages ?? new IRazorPage[0];
|
||||
var viewStartProvider = new Mock<IViewStartProvider>();
|
||||
viewStartProvider.Setup(v => v.GetViewStartPages(It.IsAny<string>()))
|
||||
.Returns(viewStartPages);
|
||||
|
||||
return viewStartProvider.Object;
|
||||
}
|
||||
|
||||
private class TestableRazorPage : RazorPage
|
||||
{
|
||||
private readonly Action<TestableRazorPage> _executeAction;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Framework.Runtime;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor.Test
|
||||
{
|
||||
public class ViewStartProviderTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData("")]
|
||||
public void GetViewStartLocations_ReturnsEmptySequenceIfViewPathIsEmpty(string viewPath)
|
||||
{
|
||||
// Arrange
|
||||
var appPath = @"x:\test";
|
||||
var provider = new ViewStartProvider(GetAppEnv(appPath), Mock.Of<IRazorPageFactory>());
|
||||
|
||||
// Act
|
||||
var result = provider.GetViewStartLocations(viewPath);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> GetViewStartLocations_ReturnsPotentialViewStartLocationsData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
@"x:\test\myapp",
|
||||
"/Views/Home/View.cshtml",
|
||||
new[]
|
||||
{
|
||||
@"x:\test\myapp\Views\Home\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\Views\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\_ViewStart.cshtml",
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
@"x:\test\myapp",
|
||||
"Views/Home/View.cshtml",
|
||||
new[]
|
||||
{
|
||||
@"x:\test\myapp\Views\Home\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\Views\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\_ViewStart.cshtml",
|
||||
}
|
||||
};
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
@"x:\test\myapp\",
|
||||
"Views/Home/View.cshtml",
|
||||
new[]
|
||||
{
|
||||
@"x:\test\myapp\Views\Home\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\Views\_ViewStart.cshtml",
|
||||
@"x:\test\myapp\_ViewStart.cshtml",
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData("GetViewStartLocations_ReturnsPotentialViewStartLocationsData")]
|
||||
public void GetViewStartLocations_ReturnsPotentialViewStartLocations(string appPath,
|
||||
string viewPath,
|
||||
IEnumerable<string> expected)
|
||||
{
|
||||
// Arrange
|
||||
var provider = new ViewStartProvider(GetAppEnv(appPath), Mock.Of<IRazorPageFactory>());
|
||||
|
||||
// Act
|
||||
var result = provider.GetViewStartLocations(viewPath);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
private static IApplicationEnvironment GetAppEnv(string appPath)
|
||||
{
|
||||
var appEnv = new Mock<IApplicationEnvironment>();
|
||||
appEnv.Setup(p => p.ApplicationBasePath)
|
||||
.Returns(appPath);
|
||||
return appEnv.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue