parent
bc87c3e9cb
commit
7b2a4ff465
|
|
@ -240,7 +240,13 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
{
|
{
|
||||||
var controllerName = GetNormalizedRouteValue(actionContext, ControllerKey);
|
var controllerName = GetNormalizedRouteValue(actionContext, ControllerKey);
|
||||||
var areaName = GetNormalizedRouteValue(actionContext, AreaKey);
|
var areaName = GetNormalizedRouteValue(actionContext, AreaKey);
|
||||||
var razorPageName = GetNormalizedRouteValue(actionContext, PageKey);
|
string razorPageName = null;
|
||||||
|
if (actionContext.ActionDescriptor.RouteValues.ContainsKey(PageKey))
|
||||||
|
{
|
||||||
|
// Only calculate the Razor Page name if "page" is registered in RouteValues.
|
||||||
|
razorPageName = GetNormalizedRouteValue(actionContext, PageKey);
|
||||||
|
}
|
||||||
|
|
||||||
var expanderContext = new ViewLocationExpanderContext(
|
var expanderContext = new ViewLocationExpanderContext(
|
||||||
actionContext,
|
actionContext,
|
||||||
pageName,
|
pageName,
|
||||||
|
|
@ -270,8 +276,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
||||||
expanderContext.IsMainPage,
|
expanderContext.IsMainPage,
|
||||||
expanderValues);
|
expanderValues);
|
||||||
|
|
||||||
ViewLocationCacheResult cacheResult;
|
if (!ViewLookupCache.TryGetValue(cacheKey, out ViewLocationCacheResult cacheResult))
|
||||||
if (!ViewLookupCache.TryGetValue(cacheKey, out cacheResult))
|
|
||||||
{
|
{
|
||||||
_logger.ViewLookupCacheMiss(cacheKey.ViewName, cacheKey.ControllerName);
|
_logger.ViewLookupCacheMiss(cacheKey.ViewName, cacheKey.ControllerName);
|
||||||
cacheResult = OnCacheMiss(expanderContext, cacheKey);
|
cacheResult = OnCacheMiss(expanderContext, cacheKey);
|
||||||
|
|
|
||||||
|
|
@ -10,13 +10,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
{
|
{
|
||||||
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
|
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(context.PageName))
|
if ((context.ActionContext.ActionDescriptor is PageActionDescriptor) && !string.IsNullOrEmpty(context.PageName))
|
||||||
{
|
{
|
||||||
// Not a page - just act natural.
|
return ExpandPageHierarchy();
|
||||||
return viewLocations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpandPageHierarchy();
|
// Not a page - just act natural.
|
||||||
|
return viewLocations;
|
||||||
|
|
||||||
IEnumerable<string> ExpandPageHierarchy()
|
IEnumerable<string> ExpandPageHierarchy()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -376,5 +376,31 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UsingPageRouteParameterInConventionalRouteWorks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "ConventionalRoute - Hello from mypage";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.GetStringAsync("/PageRoute/ConventionalRoute/mypage");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, response.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task UsingPageRouteParameterInAttributeRouteWorks()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "AttributeRoute - Hello from test-page";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.GetStringAsync("/PageRoute/Attribute/test-page");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(expected, response.Trim());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1791,6 +1791,79 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
Assert.Equal(expected, actual);
|
Assert.Equal(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ViewEngine_DoesNotSetPageValue_IfItIsNotSpecifiedInRouteValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var routeValues = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "controller", "MyController" },
|
||||||
|
{ "action", "MyAction" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var expected = new[] { "some-seed" };
|
||||||
|
var expander = new Mock<IViewLocationExpander>();
|
||||||
|
expander
|
||||||
|
.Setup(e => e.PopulateValues(It.IsAny<ViewLocationExpanderContext>()))
|
||||||
|
.Callback((ViewLocationExpanderContext c) =>
|
||||||
|
{
|
||||||
|
Assert.Equal("MyController", c.ControllerName);
|
||||||
|
Assert.Null(c.PageName);
|
||||||
|
})
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
expander
|
||||||
|
.Setup(e => e.ExpandViewLocations(
|
||||||
|
It.IsAny<ViewLocationExpanderContext>(),
|
||||||
|
It.IsAny<IEnumerable<string>>()))
|
||||||
|
.Returns(expected);
|
||||||
|
|
||||||
|
var viewEngine = CreateViewEngine(expanders: new[] { expander.Object });
|
||||||
|
var context = GetActionContext(routeValues);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
viewEngine.FindView(context, viewName: "Test-view", isMainPage: true);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expander.Verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ViewEngine_SetsPageValue_IfItIsSpecifiedInRouteValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var routeValues = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "page", "MyPage" },
|
||||||
|
};
|
||||||
|
|
||||||
|
var expected = new[] { "some-seed" };
|
||||||
|
var expander = new Mock<IViewLocationExpander>();
|
||||||
|
expander
|
||||||
|
.Setup(e => e.PopulateValues(It.IsAny<ViewLocationExpanderContext>()))
|
||||||
|
.Callback((ViewLocationExpanderContext c) =>
|
||||||
|
{
|
||||||
|
Assert.Equal("MyPage", c.PageName);
|
||||||
|
})
|
||||||
|
.Verifiable();
|
||||||
|
|
||||||
|
expander
|
||||||
|
.Setup(e => e.ExpandViewLocations(
|
||||||
|
It.IsAny<ViewLocationExpanderContext>(),
|
||||||
|
It.IsAny<IEnumerable<string>>()))
|
||||||
|
.Returns(expected);
|
||||||
|
|
||||||
|
var viewEngine = CreateViewEngine(expanders: new[] { expander.Object });
|
||||||
|
var context = GetActionContext(routeValues);
|
||||||
|
context.ActionDescriptor.RouteValues["page"] = "MyPage";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
viewEngine.FindView(context, viewName: "MyView", isMainPage: true);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expander.Verify();
|
||||||
|
}
|
||||||
|
|
||||||
// Return RazorViewEngine with a page factory provider that is always successful.
|
// Return RazorViewEngine with a page factory provider that is always successful.
|
||||||
private RazorViewEngine CreateSuccessfulViewEngine()
|
private RazorViewEngine CreateSuccessfulViewEngine()
|
||||||
{
|
{
|
||||||
|
|
@ -1931,8 +2004,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Test
|
||||||
optionsAccessor,
|
optionsAccessor,
|
||||||
new FileProviderRazorProject(
|
new FileProviderRazorProject(
|
||||||
Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == new TestFileProvider())))
|
Mock.Of<IRazorViewEngineFileProviderAccessor>(a => a.FileProvider == new TestFileProvider())))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestableRazorViewEngine(
|
public TestableRazorViewEngine(
|
||||||
IRazorPageFactoryProvider pageFactory,
|
IRazorPageFactoryProvider pageFactory,
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// 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.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
using Microsoft.AspNetCore.Mvc.Razor;
|
using Microsoft.AspNetCore.Mvc.Razor;
|
||||||
using Microsoft.AspNetCore.Razor.Language;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
|
|
@ -48,6 +45,28 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
Assert.Equal(locations, actual);
|
Assert.Equal(locations, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ExpandLocations_NoOp_ForNonPageWithPageName()
|
||||||
|
{
|
||||||
|
// Verifies the fix for https://github.com/aspnet/Mvc/issues/6660. This ensures that when PageViewLocationExpander is called
|
||||||
|
// from a non-Razor Page with a route value for "
|
||||||
|
// Arrange
|
||||||
|
var context = CreateContext(pageName: "test");
|
||||||
|
context.ActionContext.ActionDescriptor = new ControllerActionDescriptor();
|
||||||
|
var locations = new string[]
|
||||||
|
{
|
||||||
|
"/ignore-me",
|
||||||
|
};
|
||||||
|
|
||||||
|
var expander = new PageViewLocationExpander();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var actual = expander.ExpandViewLocations(context, locations);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(locations, actual);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ExpandLocations_NoOp_WhenLocationDoesNotContainPageToken()
|
public void ExpandLocations_NoOp_WhenLocationDoesNotContainPageToken()
|
||||||
{
|
{
|
||||||
|
|
@ -125,8 +144,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
|
|
||||||
private ViewLocationExpanderContext CreateContext(string viewName = "_LoginPartial.cshtml", string pageName = null)
|
private ViewLocationExpanderContext CreateContext(string viewName = "_LoginPartial.cshtml", string pageName = null)
|
||||||
{
|
{
|
||||||
|
var actionContext = new ActionContext
|
||||||
|
{
|
||||||
|
ActionDescriptor = new PageActionDescriptor(),
|
||||||
|
};
|
||||||
|
|
||||||
return new ViewLocationExpanderContext(
|
return new ViewLocationExpanderContext(
|
||||||
new ActionContext(),
|
actionContext,
|
||||||
viewName,
|
viewName,
|
||||||
controllerName: null,
|
controllerName: null,
|
||||||
areaName: null,
|
areaName: null,
|
||||||
|
|
@ -134,6 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
isMainPage: true)
|
isMainPage: true)
|
||||||
{
|
{
|
||||||
Values = new Dictionary<string, string>(),
|
Values = new Dictionary<string, string>(),
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace BasicWebSite.Controllers
|
||||||
|
{
|
||||||
|
// Verifies that we can use the "page" token in routing in a controller only (no Razor Pages) application
|
||||||
|
// without affecting view lookups.
|
||||||
|
public class PageRouteController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult ConventionalRoute(string page)
|
||||||
|
{
|
||||||
|
ViewData["page"] = page;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("/PageRoute/Attribute/{page}")]
|
||||||
|
public IActionResult AttributeRoute(string page)
|
||||||
|
{
|
||||||
|
ViewData["page"] = page;
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,6 +44,7 @@ namespace BasicWebSite
|
||||||
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
|
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
|
||||||
defaults: new { controller = "Home", action = "Index" });
|
defaults: new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
|
routes.MapRoute("PageRoute", "{controller}/{action}/{page}");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
AttributeRoute - Hello from @ViewBag.Page
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
ConventionalRoute - Hello from @ViewBag.Page
|
||||||
Loading…
Reference in New Issue