From bac68ba3c225b116d5be5ac1a1383d6bad053bf6 Mon Sep 17 00:00:00 2001 From: Pranav K Date: Thu, 31 Aug 2017 11:24:58 -0700 Subject: [PATCH] Injecting IViewLocalizer into Razor Page causing IndexOutOfRangeException Fixes #6694 --- .../Internal/PageActionInvoker.cs | 2 ++ .../RazorPagesTest.cs | 24 +++++++++++++++++ .../Internal/PageActionInvokerTest.cs | 26 +++++++++++++++++++ .../Pages/Localized/Page.cshtml | 3 +++ .../Pages/Localized/Page.fr-FR.resx | 18 +++++++++++++ .../Pages/Localized/PageWithModel.cs | 13 ++++++++++ .../Pages/Localized/PageWithModel.cshtml | 4 +++ .../Pages/Localized/PageWithModel.fr-FR.resx | 18 +++++++++++++ test/WebSites/RazorPagesWebSite/Startup.cs | 15 ++++++++++- 9 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Localized/Page.cshtml create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Localized/Page.fr-FR.resx create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cs create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cshtml create mode 100644 test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.fr-FR.resx diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvoker.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvoker.cs index 53fc6b1fe0..8f282e7f37 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvoker.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/PageActionInvoker.cs @@ -122,6 +122,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal _tempDataFactory.GetTempData(_pageContext.HttpContext), TextWriter.Null, _htmlHelperOptions); + _viewContext.ExecutingFilePath = _pageContext.ActionDescriptor.RelativePath; _page = (Page)CacheEntry.PageFactory(_pageContext, _viewContext); @@ -265,6 +266,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal _tempDataFactory.GetTempData(_pageContext.HttpContext), TextWriter.Null, _htmlHelperOptions); + _viewContext.ExecutingFilePath = _pageContext.ActionDescriptor.RelativePath; } if (_page == null) diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs index 6c74d876de..f94fb8dc99 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs @@ -1115,6 +1115,30 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore._InjectedP Assert.Equal(expected, (await response.Content.ReadAsStringAsync()).Trim()); } + [Fact] + public async Task ViewLocalizer_WorksForPagesWithoutModel() + { + // Arrange + var expected = "Bon Jour from Page"; + + // Act + var response = await Client.GetStringAsync("/Pages/Localized/Page?culture=fr-FR"); + + Assert.Equal(expected, response.Trim()); + } + + [Fact] + public async Task ViewLocalizer_WorksForPagesWithModel() + { + // Arrange + var expected = "Bon Jour from PageWithModel"; + + // Act + var response = await Client.GetStringAsync("/Pages/Localized/PageWithModel?culture=fr-FR"); + + Assert.Equal(expected, response.Trim()); + } + private async Task AddAntiforgeryHeaders(HttpRequestMessage request) { var getResponse = await Client.GetAsync(request.RequestUri); diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs index 7ca7972864..677d3c8416 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/PageActionInvokerTest.cs @@ -356,6 +356,32 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Same(pageModel.PageContext.ViewData, pageResult.ViewData); } + [Fact] + public async Task InvokeAction_WithPage_SetsExecutingFilePath() + { + // Arrange + var relativePath = "/Pages/Users/Show.cshtml"; + var descriptor = CreateDescriptorForSimplePage(); + descriptor.RelativePath = relativePath; + + object instance = null; + var pageFilter = new Mock(); + AllowSelector(pageFilter); + pageFilter + .Setup(f => f.OnPageHandlerExecuting(It.IsAny())) + .Callback(c => + { + instance = c.HandlerInstance; + }); + var invoker = CreateInvoker(new[] { pageFilter.Object }, descriptor); + + // Act + await invoker.InvokeAsync(); + + // Assert + var page = Assert.IsType(instance); + Assert.Equal(relativePath, page.ViewContext.ExecutingFilePath); + } #endregion #region Handler Selection diff --git a/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.cshtml b/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.cshtml new file mode 100644 index 0000000000..91c87f0d1a --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.cshtml @@ -0,0 +1,3 @@ +@page +@inject Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer Localizer +@Localizer["Hello"] diff --git a/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.fr-FR.resx b/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.fr-FR.resx new file mode 100644 index 0000000000..5fa59b72a7 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Localized/Page.fr-FR.resx @@ -0,0 +1,18 @@ + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bon Jour from Page + + diff --git a/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cs b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cs new file mode 100644 index 0000000000..c06f62ae13 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cs @@ -0,0 +1,13 @@ +// 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 Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace RazorPagesWebSite.Pages.Localized +{ + public class PageWithModel : PageModel + { + public IActionResult OnGet() => Page(); + } +} diff --git a/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cshtml b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cshtml new file mode 100644 index 0000000000..fe46ea0520 --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.cshtml @@ -0,0 +1,4 @@ +@page +@model PageWithModel +@inject Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer Localizer +@Localizer["Hello"] diff --git a/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.fr-FR.resx b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.fr-FR.resx new file mode 100644 index 0000000000..1204c9ae7e --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/Pages/Localized/PageWithModel.fr-FR.resx @@ -0,0 +1,18 @@ + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bon Jour from PageWithModel + + diff --git a/test/WebSites/RazorPagesWebSite/Startup.cs b/test/WebSites/RazorPagesWebSite/Startup.cs index adcb48b6d0..9ea2793f1c 100644 --- a/test/WebSites/RazorPagesWebSite/Startup.cs +++ b/test/WebSites/RazorPagesWebSite/Startup.cs @@ -1,6 +1,7 @@ // 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.Globalization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.Extensions.DependencyInjection; @@ -13,7 +14,7 @@ namespace RazorPagesWebSite { services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => options.LoginPath = "/Login"); services.AddMvc() - .AddCookieTempDataProvider() + .AddViewLocalization() .AddRazorPagesOptions(options => { options.Conventions.AuthorizePage("/HelloWorldWithAuth"); @@ -31,6 +32,18 @@ namespace RazorPagesWebSite app.UseStaticFiles(); + var supportedCultures = new[] + { + new CultureInfo("en-US"), + new CultureInfo("fr-FR"), + }; + + app.UseRequestLocalization(new RequestLocalizationOptions + { + SupportedCultures = supportedCultures, + SupportedUICultures = supportedCultures + }); + app.UseMvc(); } }