Ensure ViewData is set on PageResult after a handler method executes
[Fixes #7665] Initializing PageResult.Page as part of result execution breaks Identity UI
This commit is contained in:
parent
4f7d53f4e7
commit
faca3da42f
|
|
@ -128,7 +128,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
{
|
{
|
||||||
_page = (PageBase)CacheEntry.PageFactory(_pageContext, _viewContext);
|
_page = (PageBase)CacheEntry.PageFactory(_pageContext, _viewContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
pageResult.Page = _page;
|
pageResult.Page = _page;
|
||||||
pageResult.ViewData = pageResult.ViewData ?? _pageContext.ViewData;
|
pageResult.ViewData = pageResult.ViewData ?? _pageContext.ViewData;
|
||||||
}
|
}
|
||||||
|
|
@ -278,6 +277,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
{
|
{
|
||||||
_result = new PageResult();
|
_result = new PageResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure ViewData is set on PageResult for backwards compatibility (For example, Identity UI accesses
|
||||||
|
// ViewData in a PageFilter's PageHandlerExecutedMethod)
|
||||||
|
if (_result is PageResult pageResult)
|
||||||
|
{
|
||||||
|
pageResult.ViewData = pageResult.ViewData ?? _pageContext.ViewData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
|
private Task Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
|
||||||
|
|
|
||||||
|
|
@ -1295,6 +1295,16 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore.InjectedPa
|
||||||
Assert.Equal("From ShortCircuitPageAtPageFilter.cshtml", content);
|
Assert.Equal("From ShortCircuitPageAtPageFilter.cshtml", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ViewDataAvaialableInPageFilter_AfterHandlerMethod_ReturnsPageResult()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var content = await Client.GetStringAsync("http://localhost/Pages/ViewDataAvailableAfterHandlerExecuted");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("ViewData: Bar", content);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
||||||
{
|
{
|
||||||
var getResponse = await Client.GetAsync(request.RequestUri);
|
var getResponse = await Client.GetAsync(request.RequestUri);
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,33 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
|
|
||||||
#region Page Filters
|
#region Page Filters
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ViewDataIsSet_AfterHandlerMethodIsExecuted()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var pageHandlerExecutedCalled = false;
|
||||||
|
var pageFilter = new Mock<IPageFilter>();
|
||||||
|
AllowSelector(pageFilter);
|
||||||
|
pageFilter
|
||||||
|
.Setup(f => f.OnPageHandlerExecuted(It.IsAny<PageHandlerExecutedContext>()))
|
||||||
|
.Callback<PageHandlerExecutedContext>(c =>
|
||||||
|
{
|
||||||
|
pageHandlerExecutedCalled = true;
|
||||||
|
var result = c.Result;
|
||||||
|
var pageResult = Assert.IsType<PageResult>(result);
|
||||||
|
Assert.IsType<ViewDataDictionary<TestPage>>(pageResult.ViewData);
|
||||||
|
Assert.IsType<TestPage>(pageResult.Model);
|
||||||
|
Assert.Null(pageResult.Page);
|
||||||
|
});
|
||||||
|
var invoker = CreateInvoker(new IFilterMetadata[] { pageFilter.Object }, result: new PageResult());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await invoker.InvokeAsync();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(pageHandlerExecutedCalled);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task InvokeAction_InvokesPageFilter()
|
public async Task InvokeAction_InvokesPageFilter()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
@page
|
||||||
|
@model ViewDataAvailableAfterHandlerExecutedModel
|
||||||
|
@{
|
||||||
|
}
|
||||||
|
ViewData: @ViewData["Foo"]
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 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 System;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
namespace RazorPagesWebSite.Pages
|
||||||
|
{
|
||||||
|
[TestPageFilter]
|
||||||
|
public class ViewDataAvailableAfterHandlerExecutedModel : PageModel
|
||||||
|
{
|
||||||
|
public IActionResult OnGet()
|
||||||
|
{
|
||||||
|
return Page();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestPageFilterAttribute : Attribute, IPageFilter
|
||||||
|
{
|
||||||
|
public void OnPageHandlerExecuted(PageHandlerExecutedContext context)
|
||||||
|
{
|
||||||
|
// This usage mimics Identity UI where it sets data into ViewData in a PageFilters's
|
||||||
|
// PageHandlerExecuted method.
|
||||||
|
if (context.Result is PageResult pageResult)
|
||||||
|
{
|
||||||
|
pageResult.ViewData["Foo"] = "Bar";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPageHandlerExecuting(PageHandlerExecutingContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnPageHandlerSelected(PageHandlerSelectedContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue