diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj b/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj index b3994bb8d..04c364831 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj +++ b/src/Orchard.Web/Modules/Orchard.Templates/Orchard.Templates.csproj @@ -169,7 +169,6 @@ - diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/DefaultTemplateService.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/DefaultTemplateService.cs index f28399503..80799d1fb 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/DefaultTemplateService.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/DefaultTemplateService.cs @@ -6,7 +6,6 @@ using System.Web.Mvc; using Orchard.ContentManagement; using Orchard.DisplayManagement; using Orchard.DisplayManagement.Implementation; -using Orchard.Mvc; using Orchard.Templates.Models; namespace Orchard.Templates.Services { @@ -17,7 +16,7 @@ namespace Orchard.Templates.Services { private readonly IWorkContextAccessor _workContextAccessor; private readonly IContentManager _contentManager; private readonly IEnumerable _processors; - private readonly IHttpContextAccessor _httpContextAccessor; + private readonly HttpContextBase _httpContextBase; public DefaultTemplateService( IShapeFactory shapeFactory, @@ -25,13 +24,13 @@ namespace Orchard.Templates.Services { IWorkContextAccessor workContextAccessor, IContentManager contentManager, IEnumerable processors, - IHttpContextAccessor httpContextAccessor) { + HttpContextBase httpContextBase) { _shapeFactory = shapeFactory; _displayHelperFactory = displayHelperFactory; _workContextAccessor = workContextAccessor; _contentManager = contentManager; _processors = processors; - _httpContextAccessor = httpContextAccessor; + _httpContextBase = httpContextBase; } public string ExecuteShape(string shapeType) { @@ -40,16 +39,12 @@ namespace Orchard.Templates.Services { public string ExecuteShape(string shapeType, INamedEnumerable parameters) { var shape = _shapeFactory.Create(shapeType, parameters); - var result = ""; - ExecuteInHttpContext(httpContext => { - var viewContext = new ViewContext { HttpContext = httpContext }; - viewContext.RouteData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; - var display = _displayHelperFactory.CreateHelper(viewContext, new ViewDataContainer()); - result = ((DisplayHelper)display).ShapeExecute(shape).ToString(); - }); + var viewContext = new ViewContext { HttpContext = _httpContextBase }; + viewContext.RouteData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; + var display = _displayHelperFactory.CreateHelper(viewContext, new ViewDataContainer()); - return result; + return ((DisplayHelper)display).ShapeExecute(shape).ToString(); } public string Execute(string template, string name, string language, TModel model = default(TModel)) { @@ -65,26 +60,6 @@ namespace Orchard.Templates.Services { return _contentManager.Query(versionOptions ?? VersionOptions.Published).List(); } - /// - /// Executes the action in an HttpContext, regardless of whether or not we're in a ThreadStaticScope or HttpContextScope. - /// - private void ExecuteInHttpContext(Action action) { - var httpContext = _httpContextAccessor.Current(); - - if (httpContext != null) { - action(httpContext); - return; - } - - // We're not using the ViewContext.HttpContext because that will be an EmptyHttpContext when we're on a background thread. - // EmptyHttpContext does not implement Items, which is necessary for Orchard when storing and accessing certain services such as IWorkContextAccessor. - httpContext = new StubHttpContext(); - using (var scope = _workContextAccessor.CreateWorkContextScope(httpContext)) { - _httpContextAccessor.Set(httpContext); - action(httpContext); - } - } - private class ViewDataContainer : IViewDataContainer { public ViewDataDictionary ViewData { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs index d8d5d85fb..a63c0b5f9 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/RazorTemplateProcessor.cs @@ -2,31 +2,26 @@ using System.Collections.Generic; using System.IO; using System.Text; +using System.Web; using System.Web.Mvc; using System.Web.UI; using System.Web.WebPages; using Orchard.Compilation.Razor; -using Orchard.ContentManagement; using Orchard.DisplayManagement.Implementation; -using Orchard.Logging; -using Orchard.Mvc; -using Orchard.Settings; -using Orchard.Themes.Models; - -namespace Orchard.Templates.Services { +using Orchard.Logging;namespace Orchard.Templates.Services { public class RazorTemplateProcessor : TemplateProcessorImpl { private readonly IRazorCompiler _compiler; - private readonly ISiteService _siteService; - private readonly IHttpContextAccessor _hca; + private readonly HttpContextBase _httpContextBase; public override string Type { get { return "Razor"; } } - public RazorTemplateProcessor(IRazorCompiler compiler, ISiteService siteService, IHttpContextAccessor hca) { + public RazorTemplateProcessor( + IRazorCompiler compiler, + HttpContextBase httpContextBase) { _compiler = compiler; - _siteService = siteService; - _hca = hca; + _httpContextBase = httpContextBase; Logger = NullLogger.Instance; } @@ -48,24 +43,32 @@ namespace Orchard.Templates.Services { private string ActivateAndRenderTemplate(IRazorTemplateBase obj, DisplayContext displayContext, string templateVirtualPath, object model) { var buffer = new StringBuilder(1024); using (var writer = new StringWriter(buffer)) { - var htmlWriter = new HtmlTextWriter(writer); - var httpContext = _hca.Current(); + using (var htmlWriter = new HtmlTextWriter(writer)) { - // this should be done better - if no display context is provided we should fallback to current controller context somehow, if possible - if (displayContext != null) { - var shapeViewContext = new ViewContext(displayContext.ViewContext.Controller.ControllerContext, displayContext.ViewContext.View, displayContext.ViewContext.ViewData, displayContext.ViewContext.TempData, htmlWriter); - obj.WebPageContext = new WebPageContext(displayContext.ViewContext.HttpContext, obj as WebPageRenderingBase, model); - obj.ViewContext = shapeViewContext; - obj.ViewData = new ViewDataDictionary(displayContext.ViewDataContainer.ViewData) { Model = model }; - } - else { - obj.ViewData = new ViewDataDictionary(model); - obj.WebPageContext = new WebPageContext(httpContext, obj as WebPageRenderingBase, model); - } + if (displayContext != null && displayContext.ViewContext.Controller != null) { + var shapeViewContext = new ViewContext( + displayContext.ViewContext.Controller.ControllerContext, + displayContext.ViewContext.View, + displayContext.ViewContext.ViewData, + displayContext.ViewContext.TempData, + htmlWriter + ); - obj.VirtualPath = templateVirtualPath ?? "~/Themes/" + _siteService.GetSiteSettings().As().CurrentThemeName; - obj.InitHelpers(); - obj.Render(htmlWriter); + obj.WebPageContext = new WebPageContext(displayContext.ViewContext.HttpContext, obj as WebPageRenderingBase, model); + obj.ViewContext = shapeViewContext; + + obj.ViewData = new ViewDataDictionary(displayContext.ViewDataContainer.ViewData) {Model = model}; + obj.InitHelpers(); + } + else { + + obj.ViewData = new ViewDataDictionary(model); + obj.WebPageContext = new WebPageContext(_httpContextBase, obj as WebPageRenderingBase, model); + } + + obj.VirtualPath = templateVirtualPath ?? "~/Themes/Orchard.Templates"; + obj.Render(htmlWriter); + } } return buffer.ToString(); diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/StubHttpContext.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/StubHttpContext.cs deleted file mode 100644 index bee75d6e0..000000000 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/StubHttpContext.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System.Collections; -using System.Collections.Specialized; -using System.Security.Principal; -using System.Web; -using System.Web.ClientServices; -using System.Web.Routing; -using System.Web.Security; - -namespace Orchard.Templates.Services { - internal class StubHttpContext : HttpContextBase { - private IDictionary _items; - private HttpRequestBase _request; - private HttpSessionStateBase _session; - private IPrincipal _user; - - public override IDictionary Items { - get { return _items ?? (_items = new Hashtable()); } - } - - public override HttpRequestBase Request { - get { return _request ?? (_request = new StubHttpRequest(this)); } - } - - public override HttpSessionStateBase Session { - get { return _session ?? (_session = new StubHttpSessionState()); } - } - - public override IPrincipal User { - get { return _user ?? (_user = new ClientRolePrincipal(new FormsIdentity(new FormsAuthenticationTicket(FormsAuthentication.FormsCookieName, true, int.MaxValue)))); } - set { _user = value; } - } - - public override IHttpHandler Handler { get; set; } - - private class StubHttpRequest : HttpRequestBase { - private readonly HttpContextBase _httpContext; - private RequestContext _requestContext; - private NameValueCollection _queryString; - private NameValueCollection _headers; - - public StubHttpRequest(HttpContextBase httpContext) { - _httpContext = httpContext; - } - - public override RequestContext RequestContext { - get { return _requestContext ?? (_requestContext = new StubRequestContext(_httpContext)); } - set { _requestContext = value; } - } - - public override NameValueCollection QueryString { - get { return _queryString ?? (_queryString = new NameValueCollection()); } - } - - public override NameValueCollection Headers { - get { return _headers ?? (_headers = new NameValueCollection()); } - } - - public override bool IsAuthenticated { - get { return true; } - } - - public override string AppRelativeCurrentExecutionFilePath { - get { return "/"; } - } - } - - private class StubRequestContext : RequestContext { - private HttpContextBase _httpContext; - - public StubRequestContext(HttpContextBase httpContext) { - _httpContext = httpContext; - } - - public override HttpContextBase HttpContext { - get { return _httpContext; } - set { _httpContext = value; } - } - } - - private class StubHttpSessionState : HttpSessionStateBase { - private readonly Hashtable _stub = new Hashtable(); - public override object this[int index] { - get { return _stub[index]; } - set { _stub[index] = value; } - } - - public override object this[string index] { - get { return _stub[index]; } - set { _stub[index] = value; } - } - - public override int Count { - get { return _stub.Count; } - } - - public override void Clear() { - _stub.Clear(); - } - } - } -} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateBindingStrategy.cs b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateBindingStrategy.cs index 6b3cb2bc2..71dceff60 100644 --- a/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateBindingStrategy.cs +++ b/src/Orchard.Web/Modules/Orchard.Templates/Services/TemplateBindingStrategy.cs @@ -1,54 +1,33 @@ using System; using System.Linq; using System.Web; -using Orchard.Caching; using Orchard.Compilation.Razor; -using Orchard.ContentManagement; using Orchard.DisplayManagement.Descriptors; using Orchard.DisplayManagement.Implementation; -using Orchard.Environment.Extensions; using Orchard.Environment.Extensions.Models; using Orchard.Mvc.Spooling; -using Orchard.Settings; -using Orchard.Themes.Models; namespace Orchard.Templates.Services { public class TemplateBindingStrategy : IShapeTableProvider { - private readonly IWorkContextAccessor _wca; + private readonly ITemplateService _templateService; private readonly IRazorTemplateHolder _templateProvider; public TemplateBindingStrategy( - IWorkContextAccessor wca, + ITemplateService templateService, IRazorTemplateHolder templateProvider) { - _wca = wca; + _templateService = templateService; _templateProvider = templateProvider; } + public virtual Feature Feature { get; set; } + public void Discover(ShapeTableBuilder builder) { - EnsureWorkContext(() => BuildShapes(builder)); + BuildShapes(builder); } private void BuildShapes(ShapeTableBuilder builder) { - - var templateService = _wca.GetContext().Resolve(); - var siteService = _wca.GetContext().Resolve(); - var extensionManager = _wca.GetContext().Resolve(); - var currentTheme = extensionManager.GetExtension(siteService.GetSiteSettings().As().CurrentThemeName); - var themeFeature = currentTheme.Features.FirstOrDefault(); - - var hackedDescriptor = new FeatureDescriptor - { - Category = themeFeature.Category, - Dependencies = themeFeature.Dependencies, - Description = themeFeature.Description, - Extension = themeFeature.Extension, - Id = themeFeature.Id, - Name = themeFeature.Name, - Priority = int.MaxValue - }; - - var shapes = templateService.GetTemplates().Select(r => + var shapes = _templateService.GetTemplates().Select(r => new { r.Name, r.Language, @@ -61,7 +40,7 @@ namespace Orchard.Templates.Services { var shapeType = AdjustName(record.Name); builder.Describe(shapeType) - .From(new Feature { Descriptor = hackedDescriptor }) + .From(new Feature { Descriptor = Feature.Descriptor }) .BoundAs("Template::" + shapeType, descriptor => context => { var template = _templateProvider.Get(record.Name); @@ -72,13 +51,12 @@ namespace Orchard.Templates.Services { private IHtmlString PerformInvoke(DisplayContext displayContext, string name, string type, string template) { - var service = _wca.GetContext().Resolve(); - var output = new HtmlStringWriter(); - - if (String.IsNullOrEmpty(template)) + if (String.IsNullOrEmpty(template)) { return null; + } - output.Write(CoerceHtmlString(service.Execute(template, name, type, displayContext, displayContext.Value))); + var output = new HtmlStringWriter(); + output.Write(CoerceHtmlString(_templateService.Execute(template, name, type, displayContext, displayContext.Value))); return output; } @@ -115,16 +93,5 @@ namespace Orchard.Templates.Services { return invoke as IHtmlString ?? (invoke != null ? new HtmlString(invoke.ToString()) : null); } - private void EnsureWorkContext(Action action) { - var workContext = _wca.GetContext(); - if (workContext != null) { - action(); - } - else { - using (_wca.CreateWorkContextScope()) { - action(); - } - } - } } } \ No newline at end of file diff --git a/src/Orchard/Compilation/Razor/RazorTemplateBase.cs b/src/Orchard/Compilation/Razor/RazorTemplateBase.cs index 46f509137..372abd73f 100644 --- a/src/Orchard/Compilation/Razor/RazorTemplateBase.cs +++ b/src/Orchard/Compilation/Razor/RazorTemplateBase.cs @@ -1,11 +1,6 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Text; +using System.IO; using System.Web.Mvc; -using System.Web.UI; using System.Web.WebPages; -using System.Web.WebPages.Instrumentation; namespace Orchard.Compilation.Razor { public interface IRazorTemplateBase @@ -22,13 +17,13 @@ namespace Orchard.Compilation.Razor { public interface IRazorTemplateBase : IRazorTemplateBase { - TModel Model { get; } - ViewDataDictionary ViewData { get; set; } + new TModel Model { get; } + new ViewDataDictionary ViewData { get; set; } } public abstract class RazorTemplateBase : Mvc.ViewEngines.Razor.WebViewPage, IRazorTemplateBase { public WebPageContext WebPageContext { get; set; } - public void Render(TextWriter writer) { + public virtual void Render(TextWriter writer) { PushContext(WebPageContext, writer); OutputStack.Push(writer); Execute();