mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
#5306: Implemented a background HttpContext factory.
This change instantiates an actual HttpContext object during background sweeps so that Razor templates using Html Helpers (that require HttpContext.Current to be not-null) won't fai lwhen being rendered.
This commit is contained in:
38
src/Orchard/BackgroundHttpContext.cs
Normal file
38
src/Orchard/BackgroundHttpContext.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Orchard.Settings;
|
||||
|
||||
namespace Orchard {
|
||||
/// <summary>
|
||||
/// A factory class that creates an HttpContext instance and initializes the HttpContext.Current property with that instance.
|
||||
/// This is useful when rendering views from a background thread, as some Html Helpers access HttpContext.Current directly, thus preventing a NullReferenceException.
|
||||
/// </summary>
|
||||
public class BackgroundHttpContextFactory : IBackgroundHttpContextFactory {
|
||||
public const string IsBackgroundHttpContextKey = "IsBackgroundHttpContext";
|
||||
private readonly ISiteService _siteService;
|
||||
public BackgroundHttpContextFactory(ISiteService siteService) {
|
||||
_siteService = siteService;
|
||||
}
|
||||
|
||||
public HttpContext CreateHttpContext() {
|
||||
var url = _siteService.GetSiteSettings().BaseUrl;
|
||||
var httpContext = new HttpContext(new HttpRequest("", url, ""), new HttpResponse(new StringWriter()));
|
||||
|
||||
httpContext.Items[IsBackgroundHttpContextKey] = true;
|
||||
|
||||
return httpContext;
|
||||
}
|
||||
|
||||
public void InitializeHttpContext() {
|
||||
if (HttpContext.Current != null)
|
||||
return;
|
||||
|
||||
HttpContext.Current = CreateHttpContext();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IBackgroundHttpContextFactory : IDependency {
|
||||
HttpContext CreateHttpContext();
|
||||
void InitializeHttpContext();
|
||||
}
|
||||
}
|
39
src/Orchard/Mvc/HttpContextAccessor.cs
Normal file
39
src/Orchard/Mvc/HttpContextAccessor.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public class HttpContextAccessor : IHttpContextAccessor {
|
||||
private HttpContextBase _httpContext;
|
||||
|
||||
public HttpContextBase Current() {
|
||||
var httpContext = GetStaticProperty();
|
||||
return !IsBackgroundHttpContext(httpContext) ? new HttpContextWrapper(httpContext) : _httpContext;
|
||||
}
|
||||
|
||||
public void Set(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
private static bool IsBackgroundHttpContext(HttpContext httpContext) {
|
||||
return httpContext == null || httpContext.Items.Contains(BackgroundHttpContextFactory.IsBackgroundHttpContextKey);
|
||||
}
|
||||
|
||||
private static HttpContext GetStaticProperty() {
|
||||
var httpContext = HttpContext.Current;
|
||||
if (httpContext == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// The "Request" property throws at application startup on IIS integrated pipeline mode.
|
||||
if (httpContext.Request == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
return null;
|
||||
}
|
||||
return httpContext;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,39 +1,8 @@
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.Mvc {
|
||||
public interface IHttpContextAccessor {
|
||||
HttpContextBase Current();
|
||||
void Set(HttpContextBase httpContext);
|
||||
}
|
||||
|
||||
public class HttpContextAccessor : IHttpContextAccessor {
|
||||
private HttpContextBase _httpContext;
|
||||
|
||||
public HttpContextBase Current() {
|
||||
var httpContext = GetStaticProperty();
|
||||
return httpContext != null ? new HttpContextWrapper(httpContext) : _httpContext;
|
||||
}
|
||||
|
||||
public void Set(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
private HttpContext GetStaticProperty() {
|
||||
var httpContext = HttpContext.Current;
|
||||
if (httpContext == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (httpContext.Request == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception) {
|
||||
return null;
|
||||
}
|
||||
return httpContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ namespace Orchard.Mvc {
|
||||
return false;
|
||||
|
||||
try {
|
||||
// The "Request" property throws at application startup on IIS integrated pipeline mode
|
||||
// The "Request" property throws at application startup on IIS integrated pipeline mode.
|
||||
var req = HttpContext.Current.Request;
|
||||
}
|
||||
catch (Exception) {
|
||||
|
@@ -317,6 +317,7 @@
|
||||
<Compile Include="Mvc\DataAnnotations\LocalizedRequiredAttribute.cs" />
|
||||
<Compile Include="Mvc\Extensions\RouteExtension.cs" />
|
||||
<Compile Include="Mvc\FormValueRequiredAttribute.cs" />
|
||||
<Compile Include="Mvc\HttpContextAccessor.cs" />
|
||||
<Compile Include="Mvc\HttpContextWorkContext.cs" />
|
||||
<Compile Include="Mvc\Extensions\ControllerExtensions.cs" />
|
||||
<Compile Include="Mvc\IOrchardViewPage.cs" />
|
||||
@@ -644,6 +645,7 @@
|
||||
<Compile Include="WebApi\Filters\OrchardApiActionFilterDispatcher.cs" />
|
||||
<Compile Include="WebApi\Routes\IHttpRouteProvider.cs" />
|
||||
<Compile Include="WebApi\Routes\StandardExtensionHttpRouteProvider.cs" />
|
||||
<Compile Include="BackgroundHttpContext.cs" />
|
||||
<Compile Include="WorkContextExtensions.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\Razor\RazorCompilationEventsShim.cs" />
|
||||
<Compile Include="Mvc\ViewEngines\Razor\RazorViewEngineProvider.cs" />
|
||||
|
@@ -16,24 +16,28 @@ namespace Orchard.Tasks {
|
||||
public class BackgroundService : IBackgroundService {
|
||||
private readonly IEnumerable<IBackgroundTask> _tasks;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly IBackgroundHttpContextFactory _backgroundHttpContextFactory;
|
||||
private readonly string _shellName;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public BackgroundService(
|
||||
IEnumerable<IBackgroundTask> tasks,
|
||||
ITransactionManager transactionManager,
|
||||
ShellSettings shellSettings,
|
||||
IContentManager contentManager) {
|
||||
IContentManager contentManager,
|
||||
IBackgroundHttpContextFactory backgroundHttpContextFactory) {
|
||||
|
||||
_tasks = tasks;
|
||||
_transactionManager = transactionManager;
|
||||
_backgroundHttpContextFactory = backgroundHttpContextFactory;
|
||||
_shellName = shellSettings.Name;
|
||||
_contentManager = contentManager;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void Sweep() {
|
||||
_backgroundHttpContextFactory.InitializeHttpContext();
|
||||
|
||||
foreach(var task in _tasks) {
|
||||
var taskName = task.GetType().FullName;
|
||||
|
||||
|
Reference in New Issue
Block a user