Skip to content

Commit

Permalink
Support C# Async Constructs During Page Rendering (#3984)
Browse files Browse the repository at this point in the history
* Use IPortalSettings in Localization APIs

This is in preparation to move the Localization.SetThreadCultures call
to an HttpModule.

* Move Localization.SetThreadCultures to HttpModule

This is in support of turning on Async for Default.aspx. Per a
discussion with the ASP.NET team, setting the thread culture in OnInit
for a page does not persist in the context for the page (once Async is
turned on an there are multiple contexts to consider). Setting it from
an IHttpModule implementation, however, will persist throughout that
request.

This fixes the bug that plagued #2089, where, as an example, URLs would
be generated for the incorrect language once Async was on.

* Add Async support to Default.aspx

This is a second try for 0cf1b13 #2089.
This will allow for async calls from WebForms controls (preferably via
calling RegisterAsyncTask, see https://docs.microsoft.com/en-us/aspnet/web-forms/overview/performance-and-caching/using-asynchronous-methods-in-aspnet-45#registerasynctask-notes)
  • Loading branch information
bdukes authored Oct 6, 2020
1 parent c26a2ca commit a2f73ac
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 49 deletions.
1 change: 1 addition & 0 deletions DNN Platform/HttpModules/DotNetNuke.HttpModules.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<Link>SolutionInfo.cs</Link>
</Compile>
<Compile Include="DependencyInjection\ServiceRequestScopeModule.cs" />
<Compile Include="Localization\LocalizationModule.cs" />
<Compile Include="MobileRedirect\MobileRedirectModule.cs" />
<Compile Include="OutputCaching\OutputCacheModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
Expand Down
39 changes: 39 additions & 0 deletions DNN Platform/HttpModules/Localization/LocalizationModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
namespace DotNetNuke.HttpModules.Localization
{
using System;
using System.Web;

using DotNetNuke.Entities.Portals;
using DotNetNuke.Services.Localization;

/// <summary>Sets up localization for all requests.</summary>
public class LocalizationModule : IHttpModule
{
/// <inheritdoc />
public void Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
}

/// <inheritdoc />
public void Dispose()
{
// intentionally left empty
}

private static void Context_BeginRequest(object sender, EventArgs e)
{
var isInstallPage = HttpContext.Current.Request.Url.LocalPath.ToLowerInvariant().Contains("installwizard.aspx");
if (isInstallPage)
{
return;
}

var portalSettings = PortalController.Instance.GetCurrentSettings();
Localization.SetThreadCultures(Localization.GetPageLocale(portalSettings), portalSettings);
}
}
}
17 changes: 6 additions & 11 deletions DNN Platform/Library/Framework/PageBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
namespace DotNetNuke.Framework
{
using System;
Expand All @@ -13,7 +13,7 @@ namespace DotNetNuke.Framework
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;


using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Host;
Expand All @@ -25,8 +25,8 @@ namespace DotNetNuke.Framework
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using DotNetNuke.UI.Modules;
using DotNetNuke.Web.Client.ClientResourceManagement;

using DotNetNuke.Web.Client.ClientResourceManagement;

/// -----------------------------------------------------------------------------
/// Namespace: DotNetNuke.Framework
/// Project: DotNetNuke
Expand Down Expand Up @@ -426,11 +426,6 @@ protected override void OnError(EventArgs e)
protected override void OnInit(EventArgs e)
{
var isInstallPage = HttpContext.Current.Request.Url.LocalPath.ToLowerInvariant().Contains("installwizard.aspx");
if (!isInstallPage)
{
Localization.SetThreadCultures(this.PageCulture, this.PortalSettings);
}

if (ScriptManager.GetCurrent(this) == null)
{
AJAX.AddScriptManager(this, !isInstallPage);
Expand Down
81 changes: 53 additions & 28 deletions DNN Platform/Library/Services/Localization/Localization.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
namespace DotNetNuke.Services.Localization
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

using DotNetNuke.Abstractions.Portals;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Data;
using DotNetNuke.Entities.Host;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Entities.Users;
using DotNetNuke.Instrumentation;
using DotNetNuke.Security.Roles;
using DotNetNuke.Services.Cache;
using DotNetNuke.Services.Localization.Internal;
using DotNetNuke.Services.Log.EventLog;
using DotNetNuke.Services.Tokens;
Expand All @@ -41,8 +36,8 @@ namespace DotNetNuke.Services.Localization
/// good support for international users. Otherwise we are limiting our potential user base to
/// that using English as their base language.</para>
/// <para>
/// You can store the muti language content in resource files and use the api below to get localization content.
/// Resouces files named as: Control(Page)Name + Extension (.aspx/.ascx ) + Language + ".resx"
/// You can store the multi language content in resource files and use the api below to get localization content.
/// Resources files named as: Control(Page)Name + Extension (.aspx/.ascx ) + Language + ".resx"
/// e.g: Installwizard.aspx.de-DE.resx.
/// </para>
/// </remarks>
Expand Down Expand Up @@ -576,7 +571,26 @@ public static string GetLocaleName(string code, CultureDropDownTypes displayType
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo.</returns>
[Obsolete("Deprecated in Platform 9.8.0. Scheduled removal in v11.0.0. Use overload taking IPortalSettings instead.")]
public static CultureInfo GetPageLocale(PortalSettings portalSettings)
{
return GetPageLocale((IPortalSettings)portalSettings);
}

/// <summary>
/// Detects the current language for the request.
/// The order in which the language is being detect is:
/// 1. QueryString
/// 2. Cookie
/// 3. User profile (if request is authenticated)
/// 4. Browser preference (if portal has this option enabled)
/// 5. Portal default
/// 6. System default (en-US)
/// At any point, if a valid language is detected nothing else should be done.
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo.</returns>
public static CultureInfo GetPageLocale(IPortalSettings portalSettings)
{
CultureInfo pageCulture = null;

Expand Down Expand Up @@ -1583,20 +1597,31 @@ public static void SetLanguage(string value)
}
}

/// <summary>
/// Sets the culture codes on the current Thread.
/// </summary>
/// <param name = "cultureInfo">Culture Info for the current page.</param>
/// <param name = "portalSettings">The current portalSettings.</param>
/// <summary>Sets the culture codes on the current Thread.</summary>
/// <param name="cultureInfo">Culture Info for the current page.</param>
/// <param name="portalSettings">The current portal settings.</param>
/// <remarks>
/// This method will configure the Thread culture codes. Any page which does not derive from PageBase should
/// be sure to call this method in OnInit to ensure localiztion works correctly. See the TelerikDialogHandler for an example.
/// This method will configure the Thread culture codes. Any page which does not derive from <see cref="PageBase" /> should
/// be sure to call this method in <see cref="Control.OnInit" /> to ensure localization works correctly. See the <see cref="TelerikDialogHandler" /> for an example.
/// </remarks>
[Obsolete("Deprecated in Platform 9.8.0. Scheduled removal in v11.0.0. Use overload taking IPortalSettings instead.")]
public static void SetThreadCultures(CultureInfo cultureInfo, PortalSettings portalSettings)
{
SetThreadCultures(cultureInfo, (IPortalSettings)portalSettings);
}

/// <summary>Sets the culture codes on the current Thread.</summary>
/// <param name="cultureInfo">Culture Info for the current page.</param>
/// <param name="portalSettings">The current portal settings.</param>
/// <remarks>
/// This method will configure the Thread culture codes. Any page which does not derive from <see cref="PageBase" /> should
/// be sure to call this method in <see cref="Control.OnInit" /> to ensure localization works correctly. See the <see cref="TelerikDialogHandler" /> for an example.
/// </remarks>
public static void SetThreadCultures(CultureInfo cultureInfo, IPortalSettings portalSettings)
{
if (cultureInfo == null)
{
throw new ArgumentNullException("cultureInfo");
throw new ArgumentNullException(nameof(cultureInfo));
}

if (cultureInfo.Name == "fa-IR")
Expand Down Expand Up @@ -1895,7 +1920,7 @@ private static string GetValidLanguageURL(int portalId, string httpAlias, string
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo if any is found.</returns>
private static CultureInfo GetCultureFromQs(PortalSettings portalSettings)
private static CultureInfo GetCultureFromQs(IPortalSettings portalSettings)
{
if (HttpContext.Current == null || HttpContext.Current.Request["language"] == null)
{
Expand All @@ -1912,7 +1937,7 @@ private static CultureInfo GetCultureFromQs(PortalSettings portalSettings)
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo if any is found.</returns>
private static CultureInfo GetCultureFromCookie(PortalSettings portalSettings)
private static CultureInfo GetCultureFromCookie(IPortalSettings portalSettings)
{
CultureInfo culture;
if (HttpContext.Current == null || HttpContext.Current.Request.Cookies["language"] == null)
Expand All @@ -1930,7 +1955,7 @@ private static CultureInfo GetCultureFromCookie(PortalSettings portalSettings)
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo if any is found.</returns>
private static CultureInfo GetCultureFromProfile(PortalSettings portalSettings)
private static CultureInfo GetCultureFromProfile(IPortalSettings portalSettings)
{
UserInfo objUserInfo = UserController.Instance.GetCurrentUserInfo();

Expand All @@ -1950,7 +1975,7 @@ private static CultureInfo GetCultureFromProfile(PortalSettings portalSettings)
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo if any is found.</returns>
private static CultureInfo GetCultureFromBrowser(PortalSettings portalSettings)
private static CultureInfo GetCultureFromBrowser(IPortalSettings portalSettings)
{
if (!portalSettings.EnableBrowserLanguage)
{
Expand All @@ -1967,7 +1992,7 @@ private static CultureInfo GetCultureFromBrowser(PortalSettings portalSettings)
/// </summary>
/// <param name="portalSettings">Current PortalSettings.</param>
/// <returns>A valid CultureInfo if any is found.</returns>
private static CultureInfo GetCultureFromPortal(PortalSettings portalSettings)
private static CultureInfo GetCultureFromPortal(IPortalSettings portalSettings)
{
CultureInfo culture = null;
if (!string.IsNullOrEmpty(portalSettings.DefaultLanguage))
Expand Down Expand Up @@ -2004,13 +2029,13 @@ private static IList<object> GetPortalLocalizations(int portalID)

/// <summary>
/// When portal allows users to select their preferred UI language, this method
/// will return the user ui preferred language if defined. Otherwise defaults
/// will return the user UI preferred language if defined. Otherwise defaults
/// to the current culture.
/// </summary>
/// <param name="currentCulture">Current culture.</param>
/// <param name="portalSettings">PortalSettings for the current request.</param>
/// <returns></returns>
private static CultureInfo GetUserUICulture(CultureInfo currentCulture, PortalSettings portalSettings)
/// <param name="portalSettings">Portal settings for the current request.</param>
/// <returns>A <see cref="CultureInfo"/> instance representing the user's UI culture.</returns>
private static CultureInfo GetUserUICulture(CultureInfo currentCulture, IPortalSettings portalSettings)
{
CultureInfo uiCulture = currentCulture;
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@
<Content Include="App_LocalResources\SharedResources.resx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\DotNetNuke.Abstractions\DotNetNuke.Abstractions.csproj">
<Project>{6928a9b1-f88a-4581-a132-d3eb38669bb0}</Project>
<Name>DotNetNuke.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\..\DotNetNuke.Web\DotNetNuke.Web.csproj">
<Project>{ee1329fe-fd88-4e1a-968c-345e394ef080}</Project>
<Name>DotNetNuke.Web</Name>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
namespace DotNetNuke.Modules.CoreMessaging.Services
{
using System;
Expand All @@ -13,7 +12,8 @@ namespace DotNetNuke.Modules.CoreMessaging.Services
using System.Net.Http;
using System.Web.Http;
using System.Xml;


using DotNetNuke.Abstractions.Portals;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Modules.CoreMessaging.ViewModels;
using DotNetNuke.Services.Exceptions;
Expand All @@ -22,7 +22,7 @@ namespace DotNetNuke.Modules.CoreMessaging.Services
using DotNetNuke.Services.Social.Subscriptions;
using DotNetNuke.Services.Social.Subscriptions.Entities;
using DotNetNuke.Web.Api;


[DnnAuthorize]
public class SubscriptionsController : DnnApiController
{
Expand Down Expand Up @@ -154,7 +154,7 @@ public HttpResponseMessage GetLocalizationTable(string culture)
{
if (!string.IsNullOrEmpty(culture))
{
Localization.SetThreadCultures(new CultureInfo(culture), this.PortalSettings);
Localization.SetThreadCultures(new CultureInfo(culture), (IPortalSettings)this.PortalSettings);
}

var dictionary = new Dictionary<string, string>();
Expand Down
6 changes: 3 additions & 3 deletions DNN Platform/Website/Default.aspx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%@ Page Language="C#" AutoEventWireup="True" Inherits="DotNetNuke.Framework.DefaultPage" CodeBehind="Default.aspx.cs" %>
<%@ Page Language="C#" AutoEventWireup="True" Inherits="DotNetNuke.Framework.DefaultPage" CodeBehind="Default.aspx.cs" Async="true" %>
<%@ Register TagPrefix="dnncrm" Namespace="DotNetNuke.Web.Client.ClientResourceManagement" Assembly="DotNetNuke.Web.Client" %>
<%@ Register TagPrefix="dnn" Namespace="DotNetNuke.Common.Controls" Assembly="DotNetNuke" %>
<asp:literal id="skinDocType" runat="server" ViewStateMode="Disabled"/>
Expand All @@ -12,14 +12,14 @@
<meta id="MetaCopyright" runat="Server" name="COPYRIGHT" Visible="False"/>
<meta id="MetaGenerator" runat="Server" name="GENERATOR" Visible="False"/>
<meta id="MetaAuthor" runat="Server" name="AUTHOR" Visible="False"/>
<meta id="MetaRobots" runat="server" name="ROBOTS" Visible="False" />
<meta id="MetaRobots" runat="server" name="ROBOTS" Visible="False" />
<asp:PlaceHolder runat="server" ID="ClientDependencyHeadCss"></asp:PlaceHolder>
<asp:PlaceHolder runat="server" ID="ClientDependencyHeadJs"></asp:PlaceHolder>
<asp:placeholder id="CSS" runat="server" />
<asp:placeholder id="SCRIPTS" runat="server" />
</head>
<body id="Body" runat="server">

<dnn:Form ID="Form" runat="server" ENCTYPE="multipart/form-data">
<asp:PlaceHolder ID="BodySCRIPTS" runat="server" />
<asp:Label ID="SkinError" runat="server" CssClass="NormalRed" Visible="False"></asp:Label>
Expand Down
7 changes: 7 additions & 0 deletions DNN Platform/Website/Install/Config/09.08.00.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<configuration>
<nodes configfile="web.config">
<node path="/configuration/system.webServer/modules" action="update" key="name" collision="overwrite">
<add name="Localization" type="DotNetNuke.HttpModules.Localization.LocalizationModule, DotNetNuke.HttpModules" preCondition="managedHandler" />
</node>
</nodes>
</configuration>
1 change: 1 addition & 0 deletions DNN Platform/Website/development.config
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<modules>
<add name="RequestFilter" type="DotNetNuke.HttpModules.RequestFilter.RequestFilterModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="Localization" type="DotNetNuke.HttpModules.Localization.LocalizationModule, DotNetNuke.HttpModules" preCondition="managedHandler" />
<add name="MobileRedirect" type="DotNetNuke.HttpModules.MobileRedirectModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="Exception" type="DotNetNuke.HttpModules.Exceptions.ExceptionModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="DNNMembership" type="DotNetNuke.HttpModules.Membership.MembershipModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
Expand Down
1 change: 1 addition & 0 deletions DNN Platform/Website/release.config
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<modules>
<add name="RequestFilter" type="DotNetNuke.HttpModules.RequestFilter.RequestFilterModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="Localization" type="DotNetNuke.HttpModules.Localization.LocalizationModule, DotNetNuke.HttpModules" preCondition="managedHandler" />
<add name="MobileRedirect" type="DotNetNuke.HttpModules.MobileRedirectModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="Exception" type="DotNetNuke.HttpModules.Exceptions.ExceptionModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
<add name="DNNMembership" type="DotNetNuke.HttpModules.Membership.MembershipModule, DotNetNuke.HttpModules" preCondition="managedHandler"/>
Expand Down

0 comments on commit a2f73ac

Please sign in to comment.