diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js b/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js
index d1fb8874a..edbae4a0a 100644
--- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js
+++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js
@@ -1,5 +1,5 @@
-jQuery(document).ready(function ($) {
- $(function () {
+(function ($) {
+ $(document).ready(function () {
// default shape window height when first opened
var defaultHeight = 200;
@@ -461,4 +461,4 @@
return node;
}
-});
+})(jQuery);
diff --git a/src/Orchard.Web/Orchard.Web.csproj b/src/Orchard.Web/Orchard.Web.csproj
index 5f6286d6f..b04239903 100644
--- a/src/Orchard.Web/Orchard.Web.csproj
+++ b/src/Orchard.Web/Orchard.Web.csproj
@@ -74,6 +74,7 @@
3.5
+
diff --git a/src/Orchard/Environment/DefaultOrchardHost.cs b/src/Orchard/Environment/DefaultOrchardHost.cs
index 00553c25f..be112c42c 100644
--- a/src/Orchard/Environment/DefaultOrchardHost.cs
+++ b/src/Orchard/Environment/DefaultOrchardHost.cs
@@ -51,6 +51,11 @@ namespace Orchard.Environment {
get { return BuildCurrent().ToReadOnlyCollection(); }
}
+ public ShellContext GetShellContext(ShellSettings shellSettings) {
+ return Current
+ .Single(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name));
+ }
+
void IOrchardHost.Initialize() {
Logger.Information("Initializing");
BuildCurrent();
diff --git a/src/Orchard/Environment/IOrchardHost.cs b/src/Orchard/Environment/IOrchardHost.cs
index dd9018657..476f6af72 100644
--- a/src/Orchard/Environment/IOrchardHost.cs
+++ b/src/Orchard/Environment/IOrchardHost.cs
@@ -1,4 +1,6 @@
+using System.Collections.Generic;
using Orchard.Environment.Configuration;
+using Orchard.Environment.ShellBuilders;
namespace Orchard.Environment {
public interface IOrchardHost {
@@ -23,6 +25,8 @@ namespace Orchard.Environment {
///
void EndRequest();
+ ShellContext GetShellContext(ShellSettings shellSettings);
+
///
/// Can be used to build an temporary self-contained instance of a shell's configured code.
/// Services may be resolved from within this instance to configure and initialize it's storage.
diff --git a/src/Orchard/Environment/RunningShellTable.cs b/src/Orchard/Environment/RunningShellTable.cs
index 4e4db5987..e78ac9cb6 100644
--- a/src/Orchard/Environment/RunningShellTable.cs
+++ b/src/Orchard/Environment/RunningShellTable.cs
@@ -10,6 +10,7 @@ namespace Orchard.Environment {
void Remove(ShellSettings settings);
void Update(ShellSettings settings);
ShellSettings Match(HttpContextBase httpContext);
+ ShellSettings Match(string host, string appRelativeCurrentExecutionFilePath);
}
public class RunningShellTable : IRunningShellTable {
@@ -75,15 +76,15 @@ namespace Orchard.Environment {
}
public ShellSettings Match(HttpContextBase httpContext) {
- // use Host header to prevent proxy alteration of the orignal request
- var host = httpContext.Request.Headers["Host"];
+ return Match(httpContext.Request.Headers["Host"], httpContext.Request.AppRelativeCurrentExecutionFilePath);
+ }
+ public ShellSettings Match(string host, string appRelativePath) {
+ // use Host header to prevent proxy alteration of the orignal request
var hostLength = host.IndexOf(':');
if (hostLength != -1)
host = host.Substring(0, hostLength);
- var appRelativePath = httpContext.Request.AppRelativeCurrentExecutionFilePath;
-
var mostQualifiedMatch = _shellsByHost
.Where(group => host.EndsWith(group.Key, StringComparison.OrdinalIgnoreCase))
.SelectMany(group => group
@@ -93,6 +94,5 @@ namespace Orchard.Environment {
return mostQualifiedMatch ?? _fallback;
}
-
}
}
diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj
index 6e21aa3e1..3e58275c3 100644
--- a/src/Orchard/Orchard.Framework.csproj
+++ b/src/Orchard/Orchard.Framework.csproj
@@ -121,6 +121,8 @@
3.0
+
+
@@ -494,6 +496,10 @@
+
+
+
+
diff --git a/src/Orchard/Wcf/OrchardDependencyInjectionServiceBehavior.cs b/src/Orchard/Wcf/OrchardDependencyInjectionServiceBehavior.cs
new file mode 100644
index 000000000..7c9453233
--- /dev/null
+++ b/src/Orchard/Wcf/OrchardDependencyInjectionServiceBehavior.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Description;
+using System.ServiceModel.Dispatcher;
+using Autofac;
+using Autofac.Core;
+
+namespace Orchard.Wcf {
+ public class OrchardDependencyInjectionServiceBehavior : IServiceBehavior {
+ private readonly IWorkContextAccessor _workContextAccessor;
+ private readonly Type _implementationType;
+ private readonly IComponentRegistration _componentRegistration;
+
+ public OrchardDependencyInjectionServiceBehavior(IWorkContextAccessor workContextAccessor, Type implementationType, IComponentRegistration componentRegistration) {
+ if (workContextAccessor == null) {
+ throw new ArgumentNullException("workContextAccessor");
+ }
+
+ if (implementationType == null) {
+ throw new ArgumentNullException("implementationType");
+ }
+
+ if (componentRegistration == null) {
+ throw new ArgumentNullException("componentRegistration");
+ }
+
+ _workContextAccessor = workContextAccessor;
+ _implementationType = implementationType;
+ _componentRegistration = componentRegistration;
+ }
+
+ public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) {
+ }
+
+ public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
+ if (serviceDescription == null) {
+ throw new ArgumentNullException("serviceDescription");
+ }
+
+ if (serviceHostBase == null) {
+ throw new ArgumentNullException("serviceHostBase");
+ }
+
+ IEnumerable source = serviceDescription.Endpoints.Where(delegate(ServiceEndpoint ep) {
+ return ep.Contract.ContractType.IsAssignableFrom(this._implementationType);
+ }).Select(delegate(ServiceEndpoint ep) {
+ return ep.Contract.Name;
+ });
+
+ OrchardInstanceProvider provider = new OrchardInstanceProvider(this._workContextAccessor, this._componentRegistration);
+ foreach (ChannelDispatcherBase base2 in serviceHostBase.ChannelDispatchers) {
+ ChannelDispatcher dispatcher = base2 as ChannelDispatcher;
+ if (dispatcher != null) {
+ foreach (EndpointDispatcher dispatcher2 in dispatcher.Endpoints) {
+ if (source.Contains(dispatcher2.ContractName)) {
+ dispatcher2.DispatchRuntime.InstanceProvider = provider;
+ }
+ }
+ continue;
+ }
+ }
+ }
+
+ public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {
+ }
+ }
+}
diff --git a/src/Orchard/Wcf/OrchardInstanceContext.cs b/src/Orchard/Wcf/OrchardInstanceContext.cs
new file mode 100644
index 000000000..19fd96800
--- /dev/null
+++ b/src/Orchard/Wcf/OrchardInstanceContext.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Linq;
+using System.ServiceModel;
+using Autofac;
+using Autofac.Core;
+
+namespace Orchard.Wcf {
+ public class OrchardInstanceContext : IExtension, IDisposable {
+ private readonly IWorkContextScope _workContextScope;
+
+ public OrchardInstanceContext(IWorkContextAccessor workContextAccessor) {
+ _workContextScope = workContextAccessor.CreateWorkContextScope();
+ }
+
+ public void Attach(InstanceContext owner) {}
+
+ public void Detach(InstanceContext owner) {}
+
+ public void Dispose() {
+ _workContextScope.Dispose();
+ }
+
+ public object Resolve(IComponentRegistration registration) {
+ if (registration == null) {
+ throw new ArgumentNullException("registration");
+ }
+
+ return _workContextScope.Resolve().Resolve(registration, Enumerable.Empty());
+ }
+ }
+}
diff --git a/src/Orchard/Wcf/OrchardInstanceProvider.cs b/src/Orchard/Wcf/OrchardInstanceProvider.cs
new file mode 100644
index 000000000..1d1336d80
--- /dev/null
+++ b/src/Orchard/Wcf/OrchardInstanceProvider.cs
@@ -0,0 +1,35 @@
+using System.ServiceModel;
+using System.ServiceModel.Channels;
+using System.ServiceModel.Dispatcher;
+using Autofac;
+using Autofac.Core;
+
+namespace Orchard.Wcf {
+ public class OrchardInstanceProvider : IInstanceProvider {
+ private readonly IWorkContextAccessor _workContextAccessor;
+ private readonly IComponentRegistration _componentRegistration;
+
+ public OrchardInstanceProvider(IWorkContextAccessor workContextAccessor, IComponentRegistration componentRegistration) {
+ _workContextAccessor = workContextAccessor;
+ _componentRegistration = componentRegistration;
+ }
+
+ public object GetInstance(InstanceContext instanceContext, Message message) {
+ OrchardInstanceContext item = new OrchardInstanceContext(_workContextAccessor);
+ instanceContext.Extensions.Add(item);
+ return item.Resolve(_componentRegistration);
+
+ }
+
+ public object GetInstance(InstanceContext instanceContext) {
+ return GetInstance(instanceContext, null);
+ }
+
+ public void ReleaseInstance(InstanceContext instanceContext, object instance) {
+ OrchardInstanceContext context = instanceContext.Extensions.Find();
+ if (context != null) {
+ context.Dispose();
+ }
+ }
+ }
+}
diff --git a/src/Orchard/Wcf/OrchardServiceHostFactory.cs b/src/Orchard/Wcf/OrchardServiceHostFactory.cs
new file mode 100644
index 000000000..52eccb3b4
--- /dev/null
+++ b/src/Orchard/Wcf/OrchardServiceHostFactory.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Linq;
+using System.ServiceModel;
+using System.ServiceModel.Activation;
+using Autofac;
+using Autofac.Core;
+using Orchard.Environment;
+using Orchard.Environment.Configuration;
+using Orchard.Environment.ShellBuilders;
+
+namespace Orchard.Wcf {
+ public class OrchardServiceHostFactory : ServiceHostFactory, IShim {
+ public OrchardServiceHostFactory() {
+ OrchardHostContainerRegistry.RegisterShim(this);
+ }
+
+ public IOrchardHostContainer HostContainer { get; set; }
+
+ public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses) {
+ IComponentRegistration registration;
+ if (constructorString == null) {
+ throw new ArgumentNullException("constructorString");
+ }
+
+ if (constructorString == string.Empty) {
+ throw new ArgumentOutOfRangeException("constructorString");
+ }
+
+ if (HostContainer == null) {
+ throw new InvalidOperationException();
+ }
+
+ // Create work context
+ IRunningShellTable runningShellTable = HostContainer.Resolve();
+ ShellSettings shellSettings = runningShellTable.Match(baseAddresses.First().Host, baseAddresses.First().LocalPath);
+
+ IOrchardHost orchardHost = HostContainer.Resolve();
+ ShellContext shellContext = orchardHost.GetShellContext(shellSettings);
+ IWorkContextAccessor workContextAccessor = shellContext.LifetimeScope.Resolve();
+
+ using (IWorkContextScope workContext = workContextAccessor.CreateWorkContextScope()) {
+
+ ILifetimeScope lifetimeScope = workContext.Resolve();
+ if (!lifetimeScope.ComponentRegistry.TryGetRegistration(new KeyedService(constructorString, typeof (object)), out registration)) {
+ Type serviceType = Type.GetType(constructorString, false);
+ if (serviceType != null) {
+ lifetimeScope.ComponentRegistry.TryGetRegistration(new TypedService(serviceType), out registration);
+ }
+ }
+ }
+
+ if (registration == null) {
+ throw new InvalidOperationException();
+ }
+
+ if (!registration.Activator.LimitType.IsClass) {
+ throw new InvalidOperationException();
+ }
+
+ return CreateServiceHost(workContextAccessor, registration, registration.Activator.LimitType, baseAddresses);
+ }
+
+ private ServiceHost CreateServiceHost(IWorkContextAccessor workContextAccessor, IComponentRegistration registration, Type implementationType, Uri[] baseAddresses) {
+ ServiceHost host = CreateServiceHost(implementationType, baseAddresses);
+
+ host.Opening += delegate {
+ host.Description.Behaviors.Add(new OrchardDependencyInjectionServiceBehavior(workContextAccessor, implementationType, registration));
+ };
+
+ return host;
+ }
+ }
+}