mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge branch '1.9-int' into 1.x
This commit is contained in:
@@ -111,7 +111,9 @@
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<modules runAllManagedModulesForAllRequests="false"/>
|
||||
<modules runAllManagedModulesForAllRequests="false">
|
||||
<remove name="OutputCache"/>
|
||||
</modules>
|
||||
<handlers accessPolicy="Script">
|
||||
<!-- Clear all handlers, prevents executing code file extensions or returning any file contents. -->
|
||||
<clear/>
|
||||
|
@@ -273,7 +273,11 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("value", "null")),
|
||||
new JObject(
|
||||
new JProperty("name", "TypePartDefinition"),
|
||||
new JProperty("value", "ContentTypePartDefinition")),
|
||||
new JProperty("value", "ContentTypePartDefinition"),
|
||||
new JProperty("children", new JArray(
|
||||
new JObject(
|
||||
new JProperty("name", "ContentTypeDefinition"),
|
||||
new JProperty("value", "null"))))),
|
||||
new JObject(
|
||||
new JProperty("name", "PartDefinition"),
|
||||
new JProperty("value", "ContentPartDefinition"),
|
||||
@@ -349,7 +353,10 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("value", "SettingsDictionary"))))),
|
||||
new JObject(
|
||||
new JProperty("name", "Settings"),
|
||||
new JProperty("value", "SettingsDictionary"))))),
|
||||
new JProperty("value", "SettingsDictionary")),
|
||||
new JObject(
|
||||
new JProperty("name", "ContentTypeDefinition"),
|
||||
new JProperty("value", "null"))))),
|
||||
new JObject(
|
||||
new JProperty("name", "PartDefinition"),
|
||||
new JProperty("value", "ContentPartDefinition"),
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Autofac;
|
||||
using System;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Mvc;
|
||||
@@ -17,7 +18,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
_shellSettings = new ShellSettings {RequestUrlPrefix = string.Empty};
|
||||
_shellSettings = new ShellSettings { RequestUrlPrefix = String.Empty };
|
||||
builder.RegisterType<UrlRuleProvider>().As<IRuleProvider>();
|
||||
builder.RegisterInstance(_shellSettings);
|
||||
_stubContextAccessor = new StubHttpContextAccessor();
|
||||
@@ -28,15 +29,15 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForHomePageMatchesHomePagePath() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/");
|
||||
var context = new RuleContext {FunctionName = "url", Arguments = new[] {"~/"}};
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UrlForAboutPageMatchesAboutPagePath() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/about");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/about"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/about" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.True);
|
||||
@@ -44,7 +45,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForBlogWithEndingWildcardMatchesBlogPostPageInSaidBlog() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/my-blog/my-blog-post");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/my-blog/my-blog-post"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/my-blog/*" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.True);
|
||||
@@ -52,7 +53,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForHomePageDoesNotMatchAboutPagePath() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/about");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/about"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.False);
|
||||
@@ -60,7 +61,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForAboutPageMatchesDifferentCasedAboutPagePath() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/About");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/About"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/about" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.True);
|
||||
@@ -68,7 +69,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForAboutPageWithEndingSlashMatchesAboutPagePath() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/About/");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/About/"));
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/about" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
Assert.That(context.Result, Is.True);
|
||||
@@ -76,7 +77,7 @@ namespace Orchard.Tests.Modules.Widgets.RuleEngine {
|
||||
|
||||
[Test]
|
||||
public void UrlForHomePageMatchesHomePagePathWithUrlPrefix() {
|
||||
_stubContextAccessor.StubContext = new StubHttpContext("~/site1");
|
||||
_stubContextAccessor.Set(new StubHttpContext("~/site1"));
|
||||
_shellSettings.RequestUrlPrefix = "site1";
|
||||
var context = new RuleContext { FunctionName = "url", Arguments = new[] { "~/" } };
|
||||
_urlRuleProvider.Process(context);
|
||||
|
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NHibernate;
|
||||
@@ -17,7 +16,6 @@ using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Localization.Records;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Security;
|
||||
using Orchard.Tests.ContentManagement;
|
||||
using Orchard.Tests.Stubs;
|
||||
@@ -31,10 +29,11 @@ namespace Orchard.Tests.Localization {
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
private string _databaseFileName;
|
||||
private StubWorkContext _stubWorkContext;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
_databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_databaseFileName = Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
_databaseFileName,
|
||||
typeof(CultureRecord));
|
||||
@@ -43,6 +42,7 @@ namespace Orchard.Tests.Localization {
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
_stubWorkContext = new StubWorkContext();
|
||||
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
|
||||
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
|
||||
builder.RegisterInstance(new Mock<IContentDefinitionManager>().Object);
|
||||
@@ -50,12 +50,11 @@ namespace Orchard.Tests.Localization {
|
||||
builder.RegisterInstance(new Mock<IAuthorizer>().Object);
|
||||
builder.RegisterInstance(new Mock<INotifier>().Object);
|
||||
builder.RegisterInstance(new Mock<IContentDisplay>().Object);
|
||||
builder.RegisterType<StubHttpContextAccessor>().As<IHttpContextAccessor>();
|
||||
builder.RegisterType<WorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterInstance(_stubWorkContext);
|
||||
builder.RegisterInstance(new StubWorkContextAccessor(_stubWorkContext)).As<IWorkContextAccessor>();
|
||||
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
||||
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
|
||||
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
||||
builder.RegisterType<TestCultureSelector>().As<ICultureSelector>();
|
||||
builder.RegisterType<DefaultCultureManager>().As<ICultureManager>();
|
||||
builder.RegisterType<Signals>().As<ISignals>();
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
@@ -106,15 +105,9 @@ namespace Orchard.Tests.Localization {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CultureManagerReturnsCultureFromSelector() {
|
||||
Assert.That(_cultureManager.GetCurrentCulture(null), Is.EqualTo("en-US"));
|
||||
public void CultureManagerReturnsCultureFromWorkContext() {
|
||||
_stubWorkContext.CultureName = "nl-NL";
|
||||
Assert.That(_cultureManager.GetCurrentCulture(null), Is.EqualTo("nl-NL"));
|
||||
}
|
||||
}
|
||||
|
||||
public class TestCultureSelector : ICultureSelector {
|
||||
public CultureSelectorResult GetCulture(HttpContextBase context) {
|
||||
return new CultureSelectorResult { Priority = 1, CultureName = "en-US" };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Localization.Services;
|
||||
using Orchard.Mvc;
|
||||
using Orchard.Tests.Stubs;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
[TestFixture]
|
||||
public class CurrentCultureWorkContextTests {
|
||||
private IContainer _container;
|
||||
private IWorkContextStateProvider _currentCultureStateProvider;
|
||||
private WorkContext _workContext;
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
_workContext = new StubWorkContext();
|
||||
builder.RegisterInstance(new StubCultureSelector("or-CH")).As<ICultureSelector>();
|
||||
builder.RegisterInstance(new StubHttpContext("~/"));
|
||||
builder.RegisterInstance(_workContext);
|
||||
builder.RegisterType<StubHttpContextAccessor>().As<IHttpContextAccessor>();
|
||||
builder.RegisterType<CurrentCultureWorkContext>().As<IWorkContextStateProvider>();
|
||||
_container = builder.Build();
|
||||
_currentCultureStateProvider = _container.Resolve<IWorkContextStateProvider>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CultureManagerReturnsCultureFromSelectors() {
|
||||
var actualCulture = _currentCultureStateProvider.Get<string>("CurrentCulture")(_workContext);
|
||||
var expectedCulture = "or-CH";
|
||||
Assert.That(actualCulture, Is.EqualTo(expectedCulture));
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using Orchard.Localization.Services;
|
||||
@@ -28,16 +25,19 @@ namespace Orchard.Tests.Localization {
|
||||
|
||||
internal class StubWorkContext : WorkContext {
|
||||
|
||||
private string _cultureName;
|
||||
private string _calendarName;
|
||||
private TimeZoneInfo _timeZone;
|
||||
public StubWorkContext() {
|
||||
}
|
||||
|
||||
public StubWorkContext(string cultureName, string calendarName, TimeZoneInfo timeZone) {
|
||||
_cultureName = cultureName;
|
||||
_calendarName = calendarName;
|
||||
_timeZone = timeZone;
|
||||
CultureName = cultureName;
|
||||
CalendarName = calendarName;
|
||||
TimeZone = timeZone;
|
||||
}
|
||||
|
||||
public string CultureName { get; set; }
|
||||
public string CalendarName { get; set; }
|
||||
public TimeZoneInfo TimeZone { get; set; }
|
||||
|
||||
public override T Resolve<T>() {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@@ -47,9 +47,9 @@ namespace Orchard.Tests.Localization {
|
||||
}
|
||||
|
||||
public override T GetState<T>(string name) {
|
||||
if (name == "CurrentCulture") return (T)((object)_cultureName);
|
||||
if (name == "CurrentCalendar") return (T)((object)_calendarName);
|
||||
if (name == "CurrentTimeZone") return (T)((object)_timeZone);
|
||||
if (name == "CurrentCulture") return (T)((object)CultureName);
|
||||
if (name == "CurrentCalendar") return (T)((object)CalendarName);
|
||||
if (name == "CurrentTimeZone") return (T)((object)TimeZone);
|
||||
throw new NotImplementedException(String.Format("Property '{0}' is not implemented.", name));
|
||||
}
|
||||
|
||||
@@ -60,17 +60,17 @@ namespace Orchard.Tests.Localization {
|
||||
|
||||
internal class StubWorkContextAccessor : IWorkContextAccessor {
|
||||
|
||||
private WorkContext _workContext;
|
||||
private readonly WorkContext _workContext;
|
||||
|
||||
public StubWorkContextAccessor(WorkContext workContext) {
|
||||
_workContext = workContext;
|
||||
}
|
||||
|
||||
public WorkContext GetContext(System.Web.HttpContextBase httpContext) {
|
||||
public WorkContext GetContext(HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IWorkContextScope CreateWorkContextScope(System.Web.HttpContextBase httpContext) {
|
||||
public IWorkContextScope CreateWorkContextScope(HttpContextBase httpContext) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
@@ -259,10 +259,12 @@
|
||||
<Compile Include="FileSystems\Dependencies\AssemblyProbingFolderTests.cs" />
|
||||
<Compile Include="FileSystems\Dependencies\DependenciesFolderTests.cs" />
|
||||
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathProviderTests.cs" />
|
||||
<Compile Include="Localization\CurrentCultureWorkContextTests.cs" />
|
||||
<Compile Include="Localization\CultureManagerTests.cs" />
|
||||
<Compile Include="Localization\DateTimePartsTests.cs" />
|
||||
<Compile Include="Localization\DefaultDateLocalizationServicesTests.cs" />
|
||||
<Compile Include="Localization\DefaultDateFormatterTests.cs" />
|
||||
<Compile Include="Stubs\StubCultureSelector.cs" />
|
||||
<Compile Include="Localization\TestHelpers.cs" />
|
||||
<Compile Include="Logging\OrchardFileAppenderTests.cs" />
|
||||
<Compile Include="Messaging\MessagingChannelStub.cs" />
|
||||
|
16
src/Orchard.Tests/Stubs/StubCultureSelector.cs
Normal file
16
src/Orchard.Tests/Stubs/StubCultureSelector.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Web;
|
||||
using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Tests.Stubs {
|
||||
public class StubCultureSelector : ICultureSelector {
|
||||
private readonly string _cultureName;
|
||||
|
||||
public StubCultureSelector(string cultureName) {
|
||||
_cultureName = cultureName;
|
||||
}
|
||||
|
||||
public CultureSelectorResult GetCulture(HttpContextBase context) {
|
||||
return new CultureSelectorResult { Priority = 1, CultureName = _cultureName };
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,16 +5,19 @@ namespace Orchard.Tests.Stubs {
|
||||
public class StubHttpContextAccessor : IHttpContextAccessor {
|
||||
private HttpContextBase _httpContext;
|
||||
|
||||
public HttpContextBase StubContext {
|
||||
set { _httpContext = value; }
|
||||
public StubHttpContextAccessor() {
|
||||
}
|
||||
|
||||
public StubHttpContextAccessor(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
public HttpContextBase Current() {
|
||||
return _httpContext;
|
||||
}
|
||||
|
||||
public void Set(HttpContextBase stub) {
|
||||
_httpContext = stub;
|
||||
public void Set(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,34 +1,10 @@
|
||||
var LayoutEditor;
|
||||
(function ($, LayoutEditor) {
|
||||
|
||||
var decode = function(value) {
|
||||
var decode = function (value) {
|
||||
return !!value ? decodeURIComponent(value.replace(/\+/g, "%20")) : null;
|
||||
};
|
||||
|
||||
var decodeGraph = function (graph) {
|
||||
|
||||
if (!!graph.html) {
|
||||
graph.html = decode(graph.html);
|
||||
}
|
||||
|
||||
if (!!graph.data) {
|
||||
var items = $.deserialize(graph.data);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
items[i] = decode(items[i]);
|
||||
}
|
||||
|
||||
graph.data = $.param(items);
|
||||
}
|
||||
|
||||
if (!!graph.children) {
|
||||
for (var i = 0; i < graph.children.length; i++) {
|
||||
decodeGraph(graph.children[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
LayoutEditor.decode = decode;
|
||||
LayoutEditor.decodeLayoutGraph = decodeGraph;
|
||||
|
||||
})(jQuery, LayoutEditor || (LayoutEditor = {}));
|
@@ -13,14 +13,14 @@ namespace Orchard.Layouts.Services {
|
||||
// Consider combining this class with DefaultContentDisplay to reuse shared code, for example by inheriting from a common base class.
|
||||
public abstract class ContentDisplayBase : Component {
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly Lazy<IShapeTableLocator> _shapeTableLocator;
|
||||
private readonly Lazy<IShapeTableLocator> _shapeTableLocator;
|
||||
private readonly RequestContext _requestContext;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
|
||||
protected ContentDisplayBase(
|
||||
IShapeFactory shapeFactory,
|
||||
Lazy<IShapeTableLocator> shapeTableLocator,
|
||||
Lazy<IShapeTableLocator> shapeTableLocator,
|
||||
RequestContext requestContext,
|
||||
IVirtualPathProvider virtualPathProvider,
|
||||
IWorkContextAccessor workContextAccessor) {
|
||||
@@ -109,9 +109,9 @@ namespace Orchard.Layouts.Services {
|
||||
private void BindPlacement(BuildShapeContext context, string displayType, string stereotype) {
|
||||
context.FindPlacement = (partShapeType, differentiator, defaultLocation) => {
|
||||
var workContext = _workContextAccessor.GetContext(_requestContext.HttpContext);
|
||||
var theme = workContext.CurrentTheme;
|
||||
var shapeTable = _shapeTableLocator.Value.Lookup(theme.Id);
|
||||
var request = _requestContext.HttpContext.Request;
|
||||
var shapeTable = workContext.HttpContext != null
|
||||
? _shapeTableLocator.Value.Lookup(workContext.CurrentTheme.Id)
|
||||
: _shapeTableLocator.Value.Lookup(null);
|
||||
|
||||
ShapeDescriptor descriptor;
|
||||
if (shapeTable.Descriptors.TryGetValue(partShapeType, out descriptor)) {
|
||||
|
@@ -43,10 +43,9 @@
|
||||
}
|
||||
});
|
||||
(function() {
|
||||
var editorConfig = @Html.Raw(Model.ConfigurationData);
|
||||
var editorCanvasData = @Html.Raw(Model.Data);
|
||||
var editorConfig = JSON.parse(LayoutEditor.decode("@Html.Raw(Url.Encode(Model.ConfigurationData))"));
|
||||
var editorCanvasData = JSON.parse(LayoutEditor.decode("@Html.Raw(Url.Encode(Model.Data))"));
|
||||
|
||||
LayoutEditor.decodeLayoutGraph(editorCanvasData);
|
||||
window.layoutEditor = new LayoutEditor.Editor(editorConfig, editorCanvasData);
|
||||
})(jQuery);
|
||||
</script>
|
||||
|
@@ -43,11 +43,9 @@
|
||||
html: LayoutEditor.decode("@Url.Encode(Model.ElementHtml)"),
|
||||
isTemplated: false
|
||||
},
|
||||
elementEditorModel: @Html.Raw(Model.ElementEditorModel.ToJson())
|
||||
elementEditorModel: LayoutEditor.decode("@Html.Raw(Url.Encode(Model.ElementEditorModel.ToJson()))")
|
||||
};
|
||||
|
||||
LayoutEditor.decodeLayoutGraph(payload.element);
|
||||
LayoutEditor.decodeLayoutGraph(payload.elementEditorModel);
|
||||
window.parent.currentDialog.trigger("command", payload);
|
||||
});
|
||||
</script>
|
||||
|
@@ -16,7 +16,7 @@ namespace Contrib.Cache.Database {
|
||||
.Column<int>("GraceTime", c => c.Nullable())
|
||||
.Column<DateTime>("ValidUntilUtc")
|
||||
.Column<DateTime>("StoredUntilUtc")
|
||||
.Column<string>("Output", column => column.Unlimited())
|
||||
.Column<byte[]>("Output", column => column.Unlimited().WithType(DbType.Binary))
|
||||
.Column<string>("ContentType")
|
||||
.Column<string>("QueryString", column => column.WithLength(2048))
|
||||
.Column<string>("CacheKey", column => column.WithLength(2048))
|
||||
@@ -31,7 +31,7 @@ namespace Contrib.Cache.Database {
|
||||
.CreateIndex("IDX_CacheItemRecord_CacheKey", "CacheKey")
|
||||
);
|
||||
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
@@ -45,5 +45,14 @@ namespace Contrib.Cache.Database {
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int UpdateFrom2() {
|
||||
SchemaBuilder.AlterTable("CacheItemRecord",
|
||||
table => {
|
||||
table.AlterColumn("Output", c => c.Unlimited().WithType(DbType.Binary));
|
||||
});
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace Orchard.OutputCache.Filters {
|
||||
public class CaptureStream : Stream {
|
||||
public CaptureStream(Stream innerStream) {
|
||||
_innerStream = innerStream;
|
||||
_captureStream = new MemoryStream();
|
||||
}
|
||||
|
||||
private readonly Stream _innerStream;
|
||||
private readonly MemoryStream _captureStream;
|
||||
|
||||
public override bool CanRead {
|
||||
get { return _innerStream.CanRead; }
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get { return _innerStream.CanSeek; }
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get { return _innerStream.CanWrite; }
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get { return _innerStream.Length; }
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get { return _innerStream.Position; }
|
||||
set { _innerStream.Position = value; }
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin direction) {
|
||||
return _innerStream.Seek(offset, direction);
|
||||
}
|
||||
|
||||
public override void SetLength(long length) {
|
||||
_innerStream.SetLength(length);
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
_innerStream.Close();
|
||||
}
|
||||
|
||||
public override void Flush() {
|
||||
if (_captureStream.Length > 0) {
|
||||
OnCaptured();
|
||||
_captureStream.SetLength(0);
|
||||
}
|
||||
|
||||
_innerStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) {
|
||||
return _innerStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) {
|
||||
_captureStream.Write(buffer, offset, count);
|
||||
_innerStream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
public event Action<byte[]> Captured;
|
||||
|
||||
protected virtual void OnCaptured() {
|
||||
Captured(_captureStream.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,6 @@ using Orchard.Mvc.Extensions;
|
||||
using Orchard.Mvc.Filters;
|
||||
using Orchard.OutputCache.Models;
|
||||
using Orchard.OutputCache.Services;
|
||||
using Orchard.OutputCache.ViewModels;
|
||||
using Orchard.Services;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Admin;
|
||||
@@ -78,12 +77,19 @@ namespace Orchard.OutputCache.Filters {
|
||||
private string _cacheKey;
|
||||
private string _invariantCacheKey;
|
||||
private bool _transformRedirect;
|
||||
private Func<ControllerContext, string> _completeResponseFunc;
|
||||
private bool _isCachingRequest;
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext filterContext) {
|
||||
|
||||
Logger.Debug("Incoming request for URL '{0}'.", filterContext.RequestContext.HttpContext.Request.RawUrl);
|
||||
|
||||
// This filter is not reentrant (multiple executions within the same request are
|
||||
// not supported) so child actions are ignored completely.
|
||||
if (filterContext.IsChildAction) {
|
||||
Logger.Debug("Action '{0}' ignored because it's a child action.", filterContext.ActionDescriptor.ActionName);
|
||||
return;
|
||||
}
|
||||
|
||||
_now = _clock.UtcNow;
|
||||
_workContext = _workContextAccessor.GetContext();
|
||||
_cacheKey = ComputeCacheKey(filterContext, GetCacheKeyParameters(filterContext));
|
||||
@@ -167,16 +173,14 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
public void OnResultExecuted(ResultExecutedContext filterContext) {
|
||||
|
||||
var captureHandlerIsAttached = false;
|
||||
|
||||
try {
|
||||
|
||||
string renderedOutput = null;
|
||||
if (_completeResponseFunc != null) {
|
||||
renderedOutput = _completeResponseFunc(filterContext);
|
||||
}
|
||||
|
||||
if (renderedOutput == null) {
|
||||
// This filter is not reentrant (multiple executions within the same request are
|
||||
// not supported) so child actions are ignored completely.
|
||||
if (filterContext.IsChildAction || !_isCachingRequest)
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug("Item '{0}' was rendered.", _cacheKey);
|
||||
|
||||
@@ -203,42 +207,52 @@ namespace Orchard.OutputCache.Filters {
|
||||
// Include each content item ID as tags for the cache entry.
|
||||
var contentItemIds = _displayedContentItemHandler.GetDisplayed().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray();
|
||||
|
||||
// Capture the response output using a custom filter stream.
|
||||
var response = filterContext.HttpContext.Response;
|
||||
var cacheItem = new CacheItem() {
|
||||
CachedOnUtc = _now,
|
||||
Duration = cacheDuration,
|
||||
GraceTime = cacheGraceTime,
|
||||
Output = renderedOutput,
|
||||
ContentType = response.ContentType,
|
||||
QueryString = filterContext.HttpContext.Request.Url.Query,
|
||||
CacheKey = _cacheKey,
|
||||
InvariantCacheKey = _invariantCacheKey,
|
||||
Url = filterContext.HttpContext.Request.Url.AbsolutePath,
|
||||
Tenant = _shellSettings.Name,
|
||||
StatusCode = response.StatusCode,
|
||||
Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray()
|
||||
var captureStream = new CaptureStream(response.Filter);
|
||||
response.Filter = captureStream;
|
||||
captureStream.Captured += (output) => {
|
||||
try {
|
||||
var cacheItem = new CacheItem() {
|
||||
CachedOnUtc = _now,
|
||||
Duration = cacheDuration,
|
||||
GraceTime = cacheGraceTime,
|
||||
Output = output,
|
||||
ContentType = response.ContentType,
|
||||
QueryString = filterContext.HttpContext.Request.Url.Query,
|
||||
CacheKey = _cacheKey,
|
||||
InvariantCacheKey = _invariantCacheKey,
|
||||
Url = filterContext.HttpContext.Request.Url.AbsolutePath,
|
||||
Tenant = _shellSettings.Name,
|
||||
StatusCode = response.StatusCode,
|
||||
Tags = new[] { _invariantCacheKey }.Union(contentItemIds).ToArray()
|
||||
};
|
||||
|
||||
// Write the rendered item to the cache.
|
||||
_cacheStorageProvider.Remove(_cacheKey);
|
||||
_cacheStorageProvider.Set(_cacheKey, cacheItem);
|
||||
|
||||
Logger.Debug("Item '{0}' was written to cache.", _cacheKey);
|
||||
|
||||
// Also add the item tags to the tag cache.
|
||||
foreach (var tag in cacheItem.Tags) {
|
||||
_tagCache.Tag(tag, _cacheKey);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
// Always release the cache key lock when the request ends.
|
||||
ReleaseCacheKeyLock();
|
||||
}
|
||||
};
|
||||
|
||||
// Write the rendered item to the cache.
|
||||
_cacheStorageProvider.Remove(_cacheKey);
|
||||
_cacheStorageProvider.Set(_cacheKey, cacheItem);
|
||||
|
||||
Logger.Debug("Item '{0}' was written to cache.", _cacheKey);
|
||||
|
||||
// Also add the item tags to the tag cache.
|
||||
foreach (var tag in cacheItem.Tags) {
|
||||
_tagCache.Tag(tag, _cacheKey);
|
||||
}
|
||||
captureHandlerIsAttached = true;
|
||||
}
|
||||
finally {
|
||||
// Always release the cache key lock when the request ends.
|
||||
if (_cacheKey != null) {
|
||||
object cacheKeyLock;
|
||||
if (_cacheKeyLocks.TryGetValue(_cacheKey, out cacheKeyLock) && Monitor.IsEntered(cacheKeyLock)) {
|
||||
Logger.Debug("Releasing cache key lock for item '{0}'.", _cacheKey);
|
||||
Monitor.Exit(cacheKeyLock);
|
||||
}
|
||||
}
|
||||
// If the response filter stream capture handler was attached then we'll trust
|
||||
// it to release the cache key lock at some point in the future when the stream
|
||||
// is flushed; otherwise we'll make sure we'll release it here.
|
||||
if (!captureHandlerIsAttached)
|
||||
ReleaseCacheKeyLock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,12 +281,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore child actions, e.g. HomeController is using RenderAction()
|
||||
if (filterContext.IsChildAction) {
|
||||
Logger.Debug("Request for item '{0}' ignored because it's a child action.", _cacheKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ignore authenticated requests unless the setting to cache them is true.
|
||||
if (_workContext.CurrentUser != null && !CacheSettings.CacheAuthenticatedRequests) {
|
||||
Logger.Debug("Request for item '{0}' ignored because user is authenticated.", _cacheKey);
|
||||
@@ -329,7 +337,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
// Vary by action parameters.
|
||||
foreach (var p in filterContext.ActionParameters)
|
||||
result.Add(p.Key, p.Value);
|
||||
result.Add("PARAM:" + p.Key, p.Value);
|
||||
|
||||
// Vary by theme.
|
||||
result.Add("theme", _themeManager.GetRequestTheme(filterContext.RequestContext).Id.ToLowerInvariant());
|
||||
@@ -438,7 +446,6 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
private void ServeCachedItem(ActionExecutingContext filterContext, CacheItem cacheItem) {
|
||||
var response = filterContext.HttpContext.Response;
|
||||
var output = cacheItem.Output;
|
||||
|
||||
// Adds some caching information to the output if requested.
|
||||
if (CacheSettings.DebugMode) {
|
||||
@@ -447,10 +454,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
}
|
||||
|
||||
// Shorcut action execution.
|
||||
filterContext.Result = new ContentResult {
|
||||
Content = output,
|
||||
ContentType = cacheItem.ContentType
|
||||
};
|
||||
filterContext.Result = new FileContentResult(cacheItem.Output, cacheItem.ContentType);
|
||||
|
||||
response.StatusCode = cacheItem.StatusCode;
|
||||
|
||||
@@ -463,18 +467,8 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
ApplyCacheControl(response);
|
||||
|
||||
// Intercept the rendered response output.
|
||||
var originalWriter = response.Output;
|
||||
var cachingWriter = new StringWriterWithEncoding(originalWriter.Encoding, originalWriter.FormatProvider);
|
||||
_completeResponseFunc = (ctx) => {
|
||||
ctx.HttpContext.Response.Output = originalWriter;
|
||||
string capturedText = cachingWriter.ToString();
|
||||
cachingWriter.Dispose();
|
||||
ctx.HttpContext.Response.Write(capturedText);
|
||||
return capturedText;
|
||||
};
|
||||
|
||||
response.Output = cachingWriter;
|
||||
// Remember that we should intercept the rendered response output.
|
||||
_isCachingRequest = true;
|
||||
}
|
||||
|
||||
private void ApplyCacheControl(HttpResponseBase response) {
|
||||
@@ -488,9 +482,8 @@ namespace Orchard.OutputCache.Filters {
|
||||
response.Cache.SetMaxAge(maxAge);
|
||||
}
|
||||
|
||||
response.DisableUserCache();
|
||||
|
||||
// Keeping this example for later usage.
|
||||
// response.DisableUserCache();
|
||||
// response.DisableKernelCache();
|
||||
// response.Cache.SetOmitVaryStar(true);
|
||||
|
||||
@@ -517,6 +510,16 @@ namespace Orchard.OutputCache.Filters {
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseCacheKeyLock() {
|
||||
if (_cacheKey != null) {
|
||||
object cacheKeyLock;
|
||||
if (_cacheKeyLocks.TryGetValue(_cacheKey, out cacheKeyLock) && Monitor.IsEntered(cacheKeyLock)) {
|
||||
Logger.Debug("Releasing cache key lock for item '{0}'.", _cacheKey);
|
||||
Monitor.Exit(cacheKeyLock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual bool IsIgnoredUrl(string url, IEnumerable<string> ignoredUrls) {
|
||||
if (ignoredUrls == null || !ignoredUrls.Any()) {
|
||||
return false;
|
||||
@@ -566,17 +569,4 @@ namespace Orchard.OutputCache.Filters {
|
||||
public class ViewDataContainer : IViewDataContainer {
|
||||
public ViewDataDictionary ViewData { get; set; }
|
||||
}
|
||||
|
||||
public sealed class StringWriterWithEncoding : StringWriter {
|
||||
private readonly Encoding encoding;
|
||||
|
||||
public StringWriterWithEncoding(Encoding encoding, IFormatProvider formatProvider)
|
||||
: base(formatProvider) {
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
public override Encoding Encoding {
|
||||
get { return encoding; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ namespace Orchard.OutputCache.Models {
|
||||
public DateTime CachedOnUtc { get; set; }
|
||||
public int Duration { get; set; }
|
||||
public int GraceTime { get; set; }
|
||||
public string Output { get; set; }
|
||||
public byte[] Output { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
public string QueryString { get; set; }
|
||||
public string CacheKey { get; set; }
|
||||
|
@@ -12,7 +12,7 @@ namespace Orchard.OutputCache.Models {
|
||||
public virtual int GraceTime { get; set; }
|
||||
public virtual DateTime ValidUntilUtc { get; set; }
|
||||
public virtual DateTime StoredUntilUtc { get; set; }
|
||||
[StringLengthMax] public virtual string Output { get; set; }
|
||||
public virtual byte[] Output { get; set; }
|
||||
public virtual string ContentType { get; set; }
|
||||
[StringLength(2048)] public virtual string QueryString { get; set; }
|
||||
[StringLength(2048)] public virtual string CacheKey { get; set; }
|
||||
|
@@ -95,6 +95,7 @@
|
||||
<Compile Include="AdminMenu.cs" />
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="Controllers\StatisticsController.cs" />
|
||||
<Compile Include="Filters\CaptureStream.cs" />
|
||||
<Compile Include="Filters\OutputCacheFilter.cs" />
|
||||
<Compile Include="Handlers\CacheSettingsPartHandler.cs" />
|
||||
<Compile Include="Handlers\DisplayedContentItemHandler.cs" />
|
||||
|
@@ -27,7 +27,7 @@ namespace Orchard.SecureSocketsLayer.Filters {
|
||||
public void OnActionExecuting(ActionExecutingContext filterContext) {
|
||||
var settings = _sslService.GetSettings();
|
||||
|
||||
if (!settings.Enabled) {
|
||||
if (filterContext.IsChildAction || !settings.Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -91,9 +91,10 @@
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<!-- Prevent iis from only allowing integrated mode configuration. -->
|
||||
<!-- Prevent IIS from only allowing integrated mode configuration. -->
|
||||
<validation validateIntegratedModeConfiguration="false"/>
|
||||
<modules runAllManagedModulesForAllRequests="false">
|
||||
<remove name="OutputCache"/>
|
||||
<remove name="WarmupHttpModule"/>
|
||||
<add name="WarmupHttpModule" type="Orchard.WarmupStarter.WarmupHttpModule, Orchard.WarmupStarter, Version=1.8.1, Culture=neutral"/>
|
||||
</modules>
|
||||
|
@@ -13,7 +13,7 @@ namespace Orchard.ContentManagement {
|
||||
public class DefaultContentDisplay : IContentDisplay {
|
||||
private readonly Lazy<IEnumerable<IContentHandler>> _handlers;
|
||||
private readonly IShapeFactory _shapeFactory;
|
||||
private readonly Lazy<IShapeTableLocator> _shapeTableLocator;
|
||||
private readonly Lazy<IShapeTableLocator> _shapeTableLocator;
|
||||
|
||||
private readonly RequestContext _requestContext;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
@@ -22,7 +22,7 @@ namespace Orchard.ContentManagement {
|
||||
public DefaultContentDisplay(
|
||||
Lazy<IEnumerable<IContentHandler>> handlers,
|
||||
IShapeFactory shapeFactory,
|
||||
Lazy<IShapeTableLocator> shapeTableLocator,
|
||||
Lazy<IShapeTableLocator> shapeTableLocator,
|
||||
RequestContext requestContext,
|
||||
IVirtualPathProvider virtualPathProvider,
|
||||
IWorkContextAccessor workContextAccessor) {
|
||||
@@ -74,13 +74,13 @@ namespace Orchard.ContentManagement {
|
||||
|
||||
// adding an alternate for [Stereotype]_Edit__[ContentType] e.g. Content-Menu.Edit
|
||||
((IShape)itemShape).Metadata.Alternates.Add(actualShapeType + "__" + content.ContentItem.ContentType);
|
||||
|
||||
|
||||
var context = new BuildEditorContext(itemShape, content, groupId, _shapeFactory);
|
||||
BindPlacement(context, null, stereotype);
|
||||
|
||||
_handlers.Value.Invoke(handler => handler.BuildEditor(context), Logger);
|
||||
|
||||
|
||||
|
||||
return context.Shape;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Orchard.ContentManagement {
|
||||
BindPlacement(context, null, stereotype);
|
||||
|
||||
_handlers.Value.Invoke(handler => handler.UpdateEditor(context), Logger);
|
||||
|
||||
|
||||
return context.Shape;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace Orchard.ContentManagement {
|
||||
Stereotype = stereotype,
|
||||
DisplayType = displayType,
|
||||
Differentiator = differentiator,
|
||||
Path = GetPath()
|
||||
Path = GetPath()
|
||||
};
|
||||
|
||||
// define which location should be used if none placement is hit
|
||||
@@ -154,8 +154,7 @@ namespace Orchard.ContentManagement {
|
||||
/// <summary>
|
||||
/// Gets the current app-relative path, i.e. ~/my-blog/foo.
|
||||
/// </summary>
|
||||
private string GetPath()
|
||||
{
|
||||
private string GetPath() {
|
||||
return VirtualPathUtility.AppendTrailingSlash(_virtualPathProvider.ToAppRelative(_requestContext.HttpContext.Request.Path));
|
||||
}
|
||||
}
|
||||
|
@@ -169,6 +169,8 @@ namespace Orchard.DisplayManagement.Descriptors.ShapeTemplateStrategy {
|
||||
context.ViewContext.ViewData = new ViewDataDictionary(context.Value);
|
||||
context.ViewContext.TempData = new TempDataDictionary();
|
||||
context.ViewContext.View = viewResult.View;
|
||||
context.ViewContext.RouteData = controllerContext.RouteData;
|
||||
context.ViewContext.RequestContext.RouteData = controllerContext.RouteData;
|
||||
viewResult.View.Render(context.ViewContext, sw);
|
||||
viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
|
||||
return new HtmlString(sw.GetStringBuilder().ToString());
|
||||
|
@@ -29,9 +29,9 @@ namespace Orchard.Localization.Services {
|
||||
.Select(c => c.GetCulture(httpContext))
|
||||
.Where(c => c != null)
|
||||
.OrderByDescending(c => c.Priority)
|
||||
.FirstOrDefault(c => !string.IsNullOrEmpty(c.CultureName));
|
||||
.FirstOrDefault(c => !String.IsNullOrEmpty(c.CultureName));
|
||||
|
||||
return culture == null ? string.Empty : culture.CultureName;
|
||||
return culture == null ? String.Empty : culture.CultureName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,18 +9,17 @@ using Orchard.Localization.Records;
|
||||
namespace Orchard.Localization.Services {
|
||||
public class DefaultCultureManager : ICultureManager {
|
||||
private readonly IRepository<CultureRecord> _cultureRepository;
|
||||
private readonly IEnumerable<ICultureSelector> _cultureSelectors;
|
||||
private readonly ISignals _signals;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly ICacheManager _cacheManager;
|
||||
|
||||
public DefaultCultureManager(IRepository<CultureRecord> cultureRepository,
|
||||
IEnumerable<ICultureSelector> cultureSelectors,
|
||||
ISignals signals,
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
ICacheManager cacheManager) {
|
||||
public DefaultCultureManager(
|
||||
IRepository<CultureRecord> cultureRepository,
|
||||
ISignals signals,
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
ICacheManager cacheManager) {
|
||||
|
||||
_cultureRepository = cultureRepository;
|
||||
_cultureSelectors = cultureSelectors;
|
||||
_signals = signals;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_cacheManager = cacheManager;
|
||||
@@ -38,12 +37,12 @@ namespace Orchard.Localization.Services {
|
||||
if (!IsValidCulture(cultureName)) {
|
||||
throw new ArgumentException("cultureName");
|
||||
}
|
||||
|
||||
|
||||
if (ListCultures().Any(culture => culture == cultureName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_cultureRepository.Create(new CultureRecord {Culture = cultureName});
|
||||
_cultureRepository.Create(new CultureRecord { Culture = cultureName });
|
||||
_signals.Trigger("culturesChanged");
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ namespace Orchard.Localization.Services {
|
||||
public bool IsValidCulture(string cultureName) {
|
||||
var segments = cultureName.Split('-');
|
||||
|
||||
if(segments.Length == 0) {
|
||||
if (segments.Length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ namespace Orchard.Localization.Services {
|
||||
if (segments.Any(s => s.Length < 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -4,19 +4,19 @@ using System.Web;
|
||||
namespace Orchard.Mvc {
|
||||
public interface IHttpContextAccessor {
|
||||
HttpContextBase Current();
|
||||
void Set(HttpContextBase stub);
|
||||
void Set(HttpContextBase httpContext);
|
||||
}
|
||||
|
||||
public class HttpContextAccessor : IHttpContextAccessor {
|
||||
private HttpContextBase _stub;
|
||||
private HttpContextBase _httpContext;
|
||||
|
||||
public HttpContextBase Current() {
|
||||
var httpContext = GetStaticProperty();
|
||||
return httpContext != null ? new HttpContextWrapper(httpContext) : _stub;
|
||||
return httpContext != null ? new HttpContextWrapper(httpContext) : _httpContext;
|
||||
}
|
||||
|
||||
public void Set(HttpContextBase stub) {
|
||||
_stub = stub;
|
||||
public void Set(HttpContextBase httpContext) {
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
private HttpContext GetStaticProperty() {
|
||||
|
@@ -83,7 +83,7 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// standin context for background tasks.
|
||||
/// Standin context for background tasks.
|
||||
/// </summary>
|
||||
class HttpContextPlaceholder : HttpContextBase {
|
||||
private readonly Lazy<string> _baseUrl;
|
||||
@@ -124,6 +124,12 @@ namespace Orchard.Mvc {
|
||||
public override string ApplyAppPathModifier(string virtualPath) {
|
||||
return virtualPath;
|
||||
}
|
||||
|
||||
public override HttpCookieCollection Cookies {
|
||||
get {
|
||||
return new HttpCookieCollection();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,7 +164,7 @@ namespace Orchard.Mvc {
|
||||
|
||||
public override NameValueCollection Headers {
|
||||
get {
|
||||
return new NameValueCollection {{"Host", _uri.Authority}};
|
||||
return new NameValueCollection { { "Host", _uri.Authority } };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,10 +190,44 @@ namespace Orchard.Mvc {
|
||||
}
|
||||
}
|
||||
|
||||
public override HttpCookieCollection Cookies {
|
||||
get {
|
||||
return new HttpCookieCollection();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsLocal {
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override string Path {
|
||||
get { return "/"; }
|
||||
}
|
||||
|
||||
public override string UserAgent {
|
||||
get {
|
||||
return "Placeholder";
|
||||
}
|
||||
}
|
||||
|
||||
public override HttpBrowserCapabilitiesBase Browser {
|
||||
get {
|
||||
return new HttpBrowserCapabilitiesPlaceholder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class HttpBrowserCapabilitiesPlaceholder : HttpBrowserCapabilitiesBase {
|
||||
public override string this[string key] {
|
||||
get {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsMobileDevice { get { return false; } }
|
||||
public override string Browser { get { return "Placeholder"; } }
|
||||
public override bool Cookies { get { return true; } }
|
||||
public override ArrayList Browsers { get { return new ArrayList(); } }
|
||||
}
|
||||
}
|
||||
}
|
@@ -24,7 +24,7 @@ namespace Orchard {
|
||||
/// <returns>True if the dependency could be resolved, false otherwise</returns>
|
||||
public abstract bool TryResolve<T>(out T service);
|
||||
|
||||
public abstract T GetState<T>(string name);
|
||||
public abstract T GetState<T>(string name);
|
||||
public abstract void SetState<T>(string name, T value);
|
||||
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user