You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,111 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Xml;
|
||||
using SR = System.ServiceModel.Activities.SR;
|
||||
|
||||
public sealed class BufferedReceiveServiceBehavior : IServiceBehavior
|
||||
{
|
||||
internal const int DefaultMaxPendingMessagesPerChannel = 512;
|
||||
|
||||
int maxPendingMessagesPerChannel = DefaultMaxPendingMessagesPerChannel;
|
||||
|
||||
public int MaxPendingMessagesPerChannel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.maxPendingMessagesPerChannel;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.MaxPendingMessagesPerChannelMustBeGreaterThanZero);
|
||||
}
|
||||
this.maxPendingMessagesPerChannel = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceHostBase is WorkflowServiceHost)
|
||||
{
|
||||
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
|
||||
{
|
||||
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
|
||||
if (channelDispatcher != null)
|
||||
{
|
||||
foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
|
||||
{
|
||||
if (WorkflowServiceBehavior.IsWorkflowEndpoint(endpointDispatcher))
|
||||
{
|
||||
// We need all incoming messages to be copyable
|
||||
endpointDispatcher.DispatchRuntime.PreserveMessage = true;
|
||||
|
||||
// Enable BufferedReceive processing for each operation
|
||||
foreach (DispatchOperation dispatchOperation in endpointDispatcher.DispatchRuntime.Operations)
|
||||
{
|
||||
dispatchOperation.BufferedReceiveEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serviceHostBase.Extensions.Add(new BufferedReceiveManager(this.MaxPendingMessagesPerChannel));
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
// Validate that ReceiveContext.ManualControl is set for each operation
|
||||
foreach (ServiceEndpoint serviceEndpoint in serviceDescription.Endpoints)
|
||||
{
|
||||
if (BufferedReceiveServiceBehavior.IsWorkflowEndpoint(serviceEndpoint))
|
||||
{
|
||||
foreach (OperationDescription operation in serviceEndpoint.Contract.Operations)
|
||||
{
|
||||
ReceiveContextEnabledAttribute receiveContextEnabled = operation.Behaviors.Find<ReceiveContextEnabledAttribute>();
|
||||
if (receiveContextEnabled == null || !receiveContextEnabled.ManualControl)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(
|
||||
new InvalidOperationException(SR.BufferedReceiveRequiresReceiveContext(operation.Name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
// See WorkflowServiceBehavior.cs for another implementation of IsWorkflowEndpoint which
|
||||
// operates against EndpointDispatchers instead of ServiceEndpoints
|
||||
internal static bool IsWorkflowEndpoint(ServiceEndpoint serviceEndpoint)
|
||||
{
|
||||
if (serviceEndpoint.IsSystemEndpoint)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (OperationDescription operation in serviceEndpoint.Contract.Operations)
|
||||
{
|
||||
if (operation.Behaviors.Find<WorkflowOperationBehavior>() == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
class ControlOperationBehavior : IOperationBehavior
|
||||
{
|
||||
bool isWrappedMode;
|
||||
|
||||
//There are two modes of operation.
|
||||
// 1) IWorkflowControlServiceOperations :: Implemented completley by the ControlOperationInvoker.
|
||||
// 2) Infrastructure endpoints(Delay/Compensation/OCS) where we wrap their invoker over ControlOperationInvoker.
|
||||
public ControlOperationBehavior(bool isWrappedMode)
|
||||
{
|
||||
this.isWrappedMode = isWrappedMode;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
|
||||
{
|
||||
ServiceHostBase serviceHost = dispatchOperation.Parent.ChannelDispatcher.Host;
|
||||
if (!(serviceHost is WorkflowServiceHost))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(
|
||||
new InvalidOperationException(SR.WorkflowBehaviorWithNonWorkflowHost(typeof(ControlOperationBehavior).Name)));
|
||||
}
|
||||
|
||||
ServiceEndpoint endpoint = null;
|
||||
foreach (ServiceEndpoint endpointToMatch in serviceHost.Description.Endpoints)
|
||||
{
|
||||
if (endpointToMatch.Id == dispatchOperation.Parent.EndpointDispatcher.Id)
|
||||
{
|
||||
endpoint = endpointToMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isWrappedMode)
|
||||
{
|
||||
CorrelationKeyCalculator keyCalculator = null;
|
||||
|
||||
if (endpoint != null)
|
||||
{
|
||||
CorrelationQueryBehavior endpointQueryBehavior = endpoint.Behaviors.Find<CorrelationQueryBehavior>();
|
||||
|
||||
if (endpointQueryBehavior != null)
|
||||
{
|
||||
keyCalculator = endpointQueryBehavior.GetKeyCalculator();
|
||||
}
|
||||
}
|
||||
|
||||
//This will be the case for infrastructure endpoints like Compensation/Interop OCS endpoints.
|
||||
dispatchOperation.Invoker = new ControlOperationInvoker(
|
||||
operationDescription,
|
||||
endpoint,
|
||||
keyCalculator,
|
||||
dispatchOperation.Invoker,
|
||||
serviceHost);
|
||||
}
|
||||
else
|
||||
{
|
||||
//This will be for IWorkflowInstanceManagement endpoint operation.
|
||||
dispatchOperation.Invoker = new ControlOperationInvoker(
|
||||
operationDescription,
|
||||
endpoint,
|
||||
null,
|
||||
serviceHost);
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(OperationDescription operationDescription)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,421 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Xml.Linq;
|
||||
|
||||
class CorrelationQueryBehavior : IEndpointBehavior, IChannelInitializer, IExtension<IContextChannel>
|
||||
{
|
||||
const string defaultQueryFormat = "sm:correlation-data('{0}')";
|
||||
const string contextCorrelationName = "wsc-instanceId";
|
||||
const string cookieCorrelationName = "http-cookie";
|
||||
static string xPathForCookie = string.Format(CultureInfo.InvariantCulture, defaultQueryFormat, cookieCorrelationName);
|
||||
CorrelationKeyCalculator correlationKeyCalculator;
|
||||
ICollection<CorrelationQuery> queries;
|
||||
ReadOnlyCollection<string> sendNames;
|
||||
ReadOnlyCollection<string> receiveNames;
|
||||
bool shouldPreserveMessage;
|
||||
|
||||
public CorrelationQueryBehavior(ICollection<CorrelationQuery> queries)
|
||||
{
|
||||
Fx.AssertAndThrow(queries != null, "queries must not be null");
|
||||
|
||||
foreach (CorrelationQuery query in queries)
|
||||
{
|
||||
Fx.AssertAndThrow(query.Where != null, "CorrelationQuery.Where must not be null");
|
||||
}
|
||||
|
||||
this.queries = queries;
|
||||
this.shouldPreserveMessage = true;
|
||||
}
|
||||
|
||||
public ICollection<CorrelationQuery> CorrelationQueries
|
||||
{
|
||||
get { return this.queries; }
|
||||
}
|
||||
|
||||
[SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode,
|
||||
Justification = "We will use this")]
|
||||
public ICollection<string> ReceiveNames
|
||||
{
|
||||
get { return this.receiveNames; }
|
||||
}
|
||||
|
||||
public ICollection<string> SendNames
|
||||
{
|
||||
get { return this.sendNames; }
|
||||
}
|
||||
|
||||
internal XName ScopeName
|
||||
{
|
||||
set;
|
||||
get;
|
||||
}
|
||||
|
||||
public XName ServiceContractName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
internal bool IsCookieBasedQueryPresent()
|
||||
{
|
||||
if (this.queries.Count > 0)
|
||||
{
|
||||
foreach (CorrelationQuery query in this.queries)
|
||||
{
|
||||
// we only need to look at queries for selectAdditional since this query should be always initializing
|
||||
foreach (MessageQuerySet messageQueryset in query.SelectAdditional)
|
||||
{
|
||||
foreach (KeyValuePair<string, MessageQuery> item in messageQueryset)
|
||||
{
|
||||
XPathMessageQuery xPathQuery = item.Value as XPathMessageQuery;
|
||||
if (xPathQuery != null && xPathQuery.Expression.Equals(xPathForCookie))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
ICorrelationDataSource source = endpoint.Binding.GetProperty<ICorrelationDataSource>(new BindingParameterCollection());
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
this.ConfigureBindingDataNames(source);
|
||||
this.ConfigureBindingDefaultQueries(endpoint, source, false);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
ICorrelationDataSource source = endpoint.Binding.GetProperty<ICorrelationDataSource>(new BindingParameterCollection());
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
this.ConfigureBindingDataNames(source);
|
||||
this.ConfigureBindingDefaultQueries(endpoint, source, true);
|
||||
}
|
||||
|
||||
ServiceDescription description = endpointDispatcher.ChannelDispatcher.Host.Description;
|
||||
WorkflowServiceHost host = endpointDispatcher.ChannelDispatcher.Host as WorkflowServiceHost;
|
||||
|
||||
if (host == null)
|
||||
{
|
||||
// setup the scope name to be the Namespace + Name of the ServiceDescription. This will be
|
||||
// either have been explicitly set by WorkflowService.Name or defaulted through the infrastructure
|
||||
this.ScopeName = XNamespace.Get(description.Namespace).GetName(description.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ScopeName = host.DurableInstancingOptions.ScopeName;
|
||||
}
|
||||
|
||||
endpointDispatcher.ChannelDispatcher.ChannelInitializers.Add(this);
|
||||
if (this.shouldPreserveMessage)
|
||||
{
|
||||
// there could be a query that might be read from the message body
|
||||
// let us buffer the message at the dispatcher
|
||||
endpointDispatcher.DispatchRuntime.PreserveMessage = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool BindingHasDefaultQueries(Binding binding)
|
||||
{
|
||||
ICorrelationDataSource source = binding.GetProperty<ICorrelationDataSource>(new BindingParameterCollection());
|
||||
bool hasDefaults = false;
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
foreach (CorrelationDataDescription data in source.DataSources)
|
||||
{
|
||||
if (data.IsDefault)
|
||||
{
|
||||
hasDefaults = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasDefaults;
|
||||
}
|
||||
|
||||
void ConfigureBindingDataNames(ICorrelationDataSource source)
|
||||
{
|
||||
List<string> receiveNames = new List<string>();
|
||||
List<string> sendNames = new List<string>();
|
||||
|
||||
foreach (CorrelationDataDescription data in source.DataSources)
|
||||
{
|
||||
if (data.ReceiveValue)
|
||||
{
|
||||
receiveNames.Add(data.Name);
|
||||
}
|
||||
// we want to optimize the correlation path for Send/SendReply cases,
|
||||
// when using httpbinding, we always have 'http-cookie' added by transport, so we
|
||||
// add data.name even when we don't have a query. This results in postponing the correlation key calculation
|
||||
// till the channel calls us back.
|
||||
if (data.SendValue)
|
||||
{
|
||||
// if the data.Name is for cookie, but there is no user added query for the cookie, we will not
|
||||
// add this to sendNames.
|
||||
// Note that we only look at user added queries. This is because http-cookie does not have a default query
|
||||
|
||||
//
|
||||
|
||||
if (data.Name == cookieCorrelationName && !this.IsCookieBasedQueryPresent())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
sendNames.Add(data.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.receiveNames = new ReadOnlyCollection<string>(receiveNames);
|
||||
this.sendNames = new ReadOnlyCollection<string>(sendNames);
|
||||
}
|
||||
|
||||
void ConfigureBindingDefaultQueries(ServiceEndpoint endpoint, ICorrelationDataSource source, bool dispatch)
|
||||
{
|
||||
if (!CorrelationQuery.IsQueryCollectionSearchable(this.queries))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we should preserve the message if there are any existing queries added by the user
|
||||
if (this.queries.Count <= 0)
|
||||
{
|
||||
this.shouldPreserveMessage = false;
|
||||
}
|
||||
|
||||
foreach (OperationDescription operation in endpoint.Contract.Operations)
|
||||
{
|
||||
string inAction;
|
||||
CorrelationQuery inQuery;
|
||||
string outAction = null;
|
||||
CorrelationQuery outQuery = null;
|
||||
CorrelationQuery noActionReplyQuery = null;
|
||||
|
||||
inAction = operation.Messages[0].Action;
|
||||
inQuery = CorrelationQuery.FindCorrelationQueryForAction(this.queries, inAction);
|
||||
|
||||
if (!operation.IsOneWay)
|
||||
{
|
||||
outAction = operation.Messages[1].Action;
|
||||
outQuery = CorrelationQuery.FindCorrelationQueryForAction(this.queries, outAction);
|
||||
if (!dispatch)
|
||||
{
|
||||
noActionReplyQuery = CorrelationQuery.FindCorrelationQueryForAction(this.queries, String.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
// we will not add default query if a query already exists for the action
|
||||
bool canDefaultIn = inQuery == null;
|
||||
bool canDefaultOut = !operation.IsOneWay && outQuery == null;
|
||||
|
||||
// if there are no user added queries for receiveReply, we add a NoActionQuery
|
||||
bool addNoActionQueryForReply = !operation.IsOneWay && !dispatch && noActionReplyQuery == null;
|
||||
|
||||
// On the client side we add special filters, SendFilter and ReceiveFilter
|
||||
// But on dispatch side, we use ActionFilter and therefore need to verify that for wildcardaction, we
|
||||
// only add a single defaultquery
|
||||
if (canDefaultIn && canDefaultOut)
|
||||
{
|
||||
//verify if any of them is a wildcardaction, in that case let's just add a single query with a MatchAllFilter
|
||||
if (inAction == MessageHeaders.WildcardAction)
|
||||
{
|
||||
canDefaultOut = false;
|
||||
}
|
||||
else if (outAction == MessageHeaders.WildcardAction)
|
||||
{
|
||||
canDefaultIn = false;
|
||||
}
|
||||
else if (inAction == outAction)
|
||||
{
|
||||
// in this case we will be adding the same query twice, let's just add once
|
||||
// a possible scenario is when we add a contractDescription with wildcardaction for request & reply
|
||||
canDefaultOut = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!canDefaultIn && !canDefaultOut)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (CorrelationDataDescription data in source.DataSources)
|
||||
{
|
||||
if (!data.IsDefault)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (canDefaultIn &&
|
||||
(dispatch && data.ReceiveValue || data.SendValue))
|
||||
{
|
||||
inQuery = CreateDefaultCorrelationQuery(inQuery, inAction, data, ref shouldPreserveMessage);
|
||||
}
|
||||
|
||||
if (canDefaultOut &&
|
||||
(dispatch && data.SendValue || data.ReceiveValue))
|
||||
{
|
||||
outQuery = CreateDefaultCorrelationQuery(outQuery, outAction, data, ref shouldPreserveMessage);
|
||||
}
|
||||
|
||||
if (addNoActionQueryForReply)
|
||||
{
|
||||
noActionReplyQuery = CreateDefaultCorrelationQuery(noActionReplyQuery, String.Empty, data, ref shouldPreserveMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (canDefaultIn && inQuery != null)
|
||||
{
|
||||
this.queries.Add(inQuery);
|
||||
}
|
||||
|
||||
if (canDefaultOut && outQuery != null )
|
||||
{
|
||||
this.queries.Add(outQuery);
|
||||
}
|
||||
|
||||
if (addNoActionQueryForReply && noActionReplyQuery != null)
|
||||
{
|
||||
this.queries.Add(noActionReplyQuery);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static CorrelationQuery CreateDefaultCorrelationQuery(CorrelationQuery query, string action, CorrelationDataDescription data, ref bool shouldPreserveMessage)
|
||||
{
|
||||
MessageQuery messageQuery = new XPathMessageQuery
|
||||
{
|
||||
Expression = string.Format(CultureInfo.InvariantCulture, defaultQueryFormat, data.Name),
|
||||
Namespaces = new XPathMessageContext()
|
||||
};
|
||||
|
||||
if (data.IsOptional)
|
||||
{
|
||||
messageQuery = new OptionalMessageQuery
|
||||
{
|
||||
Query = messageQuery
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (query == null)
|
||||
{
|
||||
MessageFilter filter;
|
||||
// verify if the data name is added by the context channel
|
||||
bool isContextQuery = (data.Name == contextCorrelationName);
|
||||
|
||||
// if there is a query that is not a context query set it to true since we might read from
|
||||
// the message body
|
||||
if (!shouldPreserveMessage && !isContextQuery)
|
||||
{
|
||||
shouldPreserveMessage = true;
|
||||
}
|
||||
// this is a server side query, we use an action filter
|
||||
if (action == MessageHeaders.WildcardAction)
|
||||
{
|
||||
filter = new MatchAllMessageFilter();
|
||||
}
|
||||
else
|
||||
{
|
||||
filter = new ActionMessageFilter(action);
|
||||
}
|
||||
|
||||
return new CorrelationQuery
|
||||
{
|
||||
Where = filter,
|
||||
|
||||
IsDefaultContextQuery = isContextQuery,
|
||||
|
||||
Select = new MessageQuerySet
|
||||
{
|
||||
{ data.Name, messageQuery }
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
query.Select[data.Name] = messageQuery;
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceEndpoint endpoint)
|
||||
{
|
||||
}
|
||||
|
||||
void IChannelInitializer.Initialize(IClientChannel channel)
|
||||
{
|
||||
channel.Extensions.Add(this);
|
||||
}
|
||||
|
||||
void IExtension<IContextChannel>.Attach(IContextChannel owner)
|
||||
{
|
||||
}
|
||||
|
||||
void IExtension<IContextChannel>.Detach(IContextChannel owner)
|
||||
{
|
||||
}
|
||||
|
||||
public CorrelationKeyCalculator GetKeyCalculator()
|
||||
{
|
||||
if (this.correlationKeyCalculator == null)
|
||||
{
|
||||
CorrelationKeyCalculator localKeyCalculator = new CorrelationKeyCalculator(this.ScopeName);
|
||||
|
||||
foreach (CorrelationQuery query in this.queries)
|
||||
{
|
||||
IDictionary<string, MessageQueryTable<string>> dictionary =
|
||||
new Dictionary<string, MessageQueryTable<string>>();
|
||||
|
||||
// consider changing Dictionary to Collection
|
||||
int count = 0;
|
||||
foreach (MessageQuerySet querySet in query.SelectAdditional)
|
||||
{
|
||||
dictionary.Add("SelectAdditional_item_" + count, querySet.GetMessageQueryTable());
|
||||
count++;
|
||||
}
|
||||
|
||||
localKeyCalculator.AddQuery(
|
||||
query.Where,
|
||||
query.Select != null ? query.Select.GetMessageQueryTable() : new MessageQueryTable<string>(),
|
||||
dictionary,
|
||||
query.IsDefaultContextQuery);
|
||||
}
|
||||
|
||||
this.correlationKeyCalculator = localKeyCalculator;
|
||||
}
|
||||
|
||||
return this.correlationKeyCalculator;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
enum DurableConsistencyScope
|
||||
{
|
||||
Global = 0,
|
||||
InstanceGlobalKeyLocal,
|
||||
Local,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Activities.Tracking;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Activities.Tracking;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public class EtwTrackingBehavior : IServiceBehavior
|
||||
{
|
||||
public EtwTrackingBehavior()
|
||||
{
|
||||
}
|
||||
|
||||
public string ProfileName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public virtual void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
if (null != workflowServiceHost)
|
||||
{
|
||||
string workflowDisplayName = workflowServiceHost.Activity.DisplayName;
|
||||
string hostReference = string.Empty;
|
||||
|
||||
if (AspNetEnvironment.Enabled)
|
||||
{
|
||||
VirtualPathExtension virtualPathExtension = serviceHostBase.Extensions.Find<VirtualPathExtension>();
|
||||
if (virtualPathExtension != null && virtualPathExtension.VirtualPath != null)
|
||||
{
|
||||
//Format Website name\Application Virtual Path|\relative service virtual path|serviceName
|
||||
string name = serviceDescription != null ? serviceDescription.Name : string.Empty;
|
||||
string application = virtualPathExtension.ApplicationVirtualPath;
|
||||
|
||||
//If the application is the root, do not include it in servicePath
|
||||
string servicePath = virtualPathExtension.VirtualPath.Replace("~", application + "|");
|
||||
hostReference = string.Format(CultureInfo.InvariantCulture, "{0}{1}|{2}", virtualPathExtension.SiteName, servicePath, name);
|
||||
}
|
||||
}
|
||||
|
||||
TrackingProfile trackingProfile = this.GetProfile(this.ProfileName, workflowDisplayName);
|
||||
workflowServiceHost.WorkflowExtensions.Add(
|
||||
() => new EtwTrackingParticipant
|
||||
{
|
||||
ApplicationReference = hostReference,
|
||||
TrackingProfile = trackingProfile
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
}
|
||||
|
||||
TrackingProfile GetProfile(string profileName, string displayName)
|
||||
{
|
||||
DefaultProfileManager profileManager = new DefaultProfileManager();
|
||||
return profileManager.GetProfile(profileName, displayName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
class SendMessageChannelCacheBehavior : IServiceBehavior
|
||||
{
|
||||
public SendMessageChannelCacheBehavior()
|
||||
{
|
||||
}
|
||||
|
||||
public bool AllowUnsafeCaching
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ChannelCacheSettings FactorySettings
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public ChannelCacheSettings ChannelSettings
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
if (workflowServiceHost != null)
|
||||
{
|
||||
workflowServiceHost.WorkflowExtensions.Add(new SendMessageChannelCache(this.FactorySettings, this.ChannelSettings, this.AllowUnsafeCaching));
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System;
|
||||
|
||||
class ServiceDescriptionData
|
||||
{
|
||||
public ServiceDescriptionData() { }
|
||||
|
||||
public bool IsInsideTransactedReceiveScope
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
//This is the first receive of the transacted receive scope tree
|
||||
//i.e. in a nested TRS scenario, this tells if the receive is one associated with the
|
||||
//Request property of the outermost TRS or not
|
||||
public bool IsFirstReceiveOfTransactedReceiveScopeTree
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Activities.DurableInstancing;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime;
|
||||
using System.Runtime.DurableInstancing;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.Xml.Linq;
|
||||
using System.Globalization;
|
||||
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public class SqlWorkflowInstanceStoreBehavior : IServiceBehavior
|
||||
{
|
||||
internal const int defaultMaximumRetries = 4;
|
||||
internal const string defaultHostRenewalString = "00:00:30.0";
|
||||
static TimeSpan defaultHostRenewalPeriod = TimeSpan.Parse(defaultHostRenewalString, CultureInfo.InvariantCulture);
|
||||
internal const string defaultRunnableInstancesDetectionPeriodString = "00:00:05.0";
|
||||
static TimeSpan defaultRunnableInstancesDetectionPeriod = TimeSpan.Parse(defaultRunnableInstancesDetectionPeriodString, CultureInfo.InvariantCulture);
|
||||
|
||||
internal const InstanceEncodingOption defaultEncodingOption = InstanceEncodingOption.GZip;
|
||||
internal const InstanceCompletionAction defaultInstanceCompletionAction = InstanceCompletionAction.DeleteAll;
|
||||
internal const InstanceLockedExceptionAction defaultInstanceLockedExceptionAction = InstanceLockedExceptionAction.NoRetry;
|
||||
|
||||
|
||||
public SqlWorkflowInstanceStoreBehavior() :
|
||||
this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public SqlWorkflowInstanceStoreBehavior(string connectionString)
|
||||
{
|
||||
this.SqlWorkflowInstanceStore = new SqlWorkflowInstanceStore(connectionString)
|
||||
{
|
||||
InstanceEncodingOption = defaultEncodingOption,
|
||||
InstanceCompletionAction = defaultInstanceCompletionAction,
|
||||
InstanceLockedExceptionAction = defaultInstanceLockedExceptionAction,
|
||||
HostLockRenewalPeriod = defaultHostRenewalPeriod,
|
||||
RunnableInstancesDetectionPeriod = defaultRunnableInstancesDetectionPeriod,
|
||||
EnqueueRunCommands = true
|
||||
};
|
||||
}
|
||||
|
||||
public InstanceEncodingOption InstanceEncodingOption
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.InstanceEncodingOption;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.InstanceEncodingOption = value;
|
||||
}
|
||||
}
|
||||
|
||||
public InstanceCompletionAction InstanceCompletionAction
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.InstanceCompletionAction;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.InstanceCompletionAction = value;
|
||||
}
|
||||
}
|
||||
|
||||
public InstanceLockedExceptionAction InstanceLockedExceptionAction
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.InstanceLockedExceptionAction;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.InstanceLockedExceptionAction = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string ConnectionString
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.ConnectionString;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.ConnectionString = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan HostLockRenewalPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.HostLockRenewalPeriod;
|
||||
}
|
||||
set
|
||||
{
|
||||
TimeoutHelper.ThrowIfNonPositiveArgument(value);
|
||||
this.SqlWorkflowInstanceStore.HostLockRenewalPeriod = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan RunnableInstancesDetectionPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.RunnableInstancesDetectionPeriod;
|
||||
}
|
||||
set
|
||||
{
|
||||
TimeoutHelper.ThrowIfNonPositiveArgument(value);
|
||||
this.SqlWorkflowInstanceStore.RunnableInstancesDetectionPeriod = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxConnectionRetries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.SqlWorkflowInstanceStore != null)
|
||||
{
|
||||
return this.SqlWorkflowInstanceStore.MaxConnectionRetries;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultMaximumRetries;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
Fx.Assert(this.SqlWorkflowInstanceStore != null, "The SqlWorkflowInstanceStore should never be null");
|
||||
if (this.SqlWorkflowInstanceStore != null)
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.MaxConnectionRetries = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SqlWorkflowInstanceStore SqlWorkflowInstanceStore
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Promote(string name, IEnumerable<XName> promoteAsSqlVariant, IEnumerable<XName> promoteAsBinary)
|
||||
{
|
||||
this.SqlWorkflowInstanceStore.Promote(name, promoteAsSqlVariant, promoteAsBinary);
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
|
||||
if (workflowServiceHost != null)
|
||||
{
|
||||
workflowServiceHost.DurableInstancingOptions.InstanceStore = this.SqlWorkflowInstanceStore;
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
//Marker Attribute for StandardEndpoint contract to opt-in for Durable setup.
|
||||
[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false)]
|
||||
public sealed class WorkflowContractBehaviorAttribute : Attribute, IContractBehavior
|
||||
{
|
||||
|
||||
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
|
||||
{
|
||||
//Only when DurableServiceBehavior is present ensure this endpoint operates in wrapped mode.
|
||||
if (dispatchRuntime.ChannelDispatcher.Host.Description.Behaviors.Contains(typeof(WorkflowServiceBehavior)))
|
||||
{
|
||||
foreach (OperationDescription operation in contractDescription.Operations)
|
||||
{
|
||||
if (operation.Behaviors.Find<ControlOperationBehavior>() == null)
|
||||
{
|
||||
operation.Behaviors.Add(new ControlOperationBehavior(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Activities;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
class WorkflowFormatterBehavior : IOperationBehavior
|
||||
{
|
||||
IDispatchMessageFormatter formatter;
|
||||
IDispatchFaultFormatter faultFormatter;
|
||||
Collection<Receive> receives;
|
||||
|
||||
public Collection<Receive> Receives
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.receives == null)
|
||||
{
|
||||
this.receives = new Collection<Receive>();
|
||||
}
|
||||
return this.receives;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new NotImplementedException());
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
|
||||
{
|
||||
Fx.Assert(operationDescription != null, "OperationDescription cannot be null!");
|
||||
Fx.Assert(dispatchOperation != null, "DispatchOperation cannot be null!");
|
||||
|
||||
if (dispatchOperation.Formatter == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.formatter = dispatchOperation.Formatter;
|
||||
this.faultFormatter = dispatchOperation.FaultFormatter;
|
||||
if (this.receives != null)
|
||||
{
|
||||
foreach (Receive receive in this.receives)
|
||||
{
|
||||
receive.SetFormatter(this.formatter, this.faultFormatter, dispatchOperation.IncludeExceptionDetailInFaults);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove operation formatter from dispatch runtime
|
||||
dispatchOperation.Formatter = null;
|
||||
dispatchOperation.DeserializeRequest = false;
|
||||
dispatchOperation.SerializeReply = false;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void Validate(OperationDescription operationDescription)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public class WorkflowIdleBehavior : IServiceBehavior
|
||||
{
|
||||
internal const string defaultTimeToPersistString = "Infinite";
|
||||
internal static TimeSpan defaultTimeToPersist = TimeSpan.MaxValue;
|
||||
internal const string defaultTimeToUnloadString = "00:01:00";
|
||||
internal static TimeSpan defaultTimeToUnload = TimeSpan.Parse(defaultTimeToUnloadString, CultureInfo.InvariantCulture);
|
||||
|
||||
TimeSpan timeToPersist;
|
||||
TimeSpan timeToUnload;
|
||||
|
||||
public WorkflowIdleBehavior()
|
||||
{
|
||||
this.timeToPersist = defaultTimeToPersist;
|
||||
this.timeToUnload = defaultTimeToUnload;
|
||||
}
|
||||
|
||||
public TimeSpan TimeToPersist
|
||||
{
|
||||
get { return this.timeToPersist; }
|
||||
set
|
||||
{
|
||||
if (value < TimeSpan.Zero)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ErrorTimeToPersistLessThanZero);
|
||||
}
|
||||
this.timeToPersist = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TimeSpan TimeToUnload
|
||||
{
|
||||
get { return this.timeToUnload; }
|
||||
set
|
||||
{
|
||||
if (value < TimeSpan.Zero)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ErrorTimeToUnloadLessThanZero);
|
||||
}
|
||||
this.timeToUnload = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
if (workflowServiceHost != null)
|
||||
{
|
||||
workflowServiceHost.IdleTimeToPersist = this.TimeToPersist;
|
||||
workflowServiceHost.IdleTimeToUnload = this.TimeToUnload;
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceDescription == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceDescription");
|
||||
}
|
||||
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Runtime;
|
||||
using System.Security.Principal;
|
||||
using System.ServiceModel.Activation;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.Xml;
|
||||
using System.ServiceModel.Security;
|
||||
using System.Net.Security;
|
||||
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public sealed class WorkflowInstanceManagementBehavior : IServiceBehavior
|
||||
{
|
||||
public const string ControlEndpointAddress = "System.ServiceModel.Activities_IWorkflowInstanceManagement";
|
||||
|
||||
static Binding httpBinding;
|
||||
static Binding namedPipeBinding;
|
||||
|
||||
string windowsGroup;
|
||||
|
||||
public WorkflowInstanceManagementBehavior()
|
||||
{
|
||||
this.windowsGroup = GetDefaultBuiltinAdministratorsGroup();
|
||||
}
|
||||
|
||||
public string WindowsGroup
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.windowsGroup;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNullOrEmpty("WindowsGroup");
|
||||
}
|
||||
|
||||
this.windowsGroup = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Binding HttpControlEndpointBinding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (httpBinding == null)
|
||||
{
|
||||
httpBinding = new WSHttpBinding
|
||||
{
|
||||
TransactionFlow = true,
|
||||
Security = new WSHttpSecurity
|
||||
{
|
||||
Mode = SecurityMode.Message,
|
||||
Message = new NonDualMessageSecurityOverHttp
|
||||
{
|
||||
ClientCredentialType = MessageCredentialType.Windows
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return httpBinding;
|
||||
}
|
||||
}
|
||||
|
||||
public static Binding NamedPipeControlEndpointBinding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (namedPipeBinding == null)
|
||||
{
|
||||
namedPipeBinding = new NetNamedPipeBinding
|
||||
{
|
||||
TransactionFlow = true,
|
||||
Security = new NetNamedPipeSecurity
|
||||
{
|
||||
Mode = NetNamedPipeSecurityMode.Transport,
|
||||
Transport = new NamedPipeTransportSecurity
|
||||
{
|
||||
ProtectionLevel = ProtectionLevel.Sign
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return namedPipeBinding;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
|
||||
if (workflowServiceHost != null)
|
||||
{
|
||||
CreateWorkflowManagementEndpoint(workflowServiceHost);
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
internal static string GetDefaultBuiltinAdministratorsGroup()
|
||||
{
|
||||
SecurityIdentifier identifier = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
|
||||
NTAccount account = (NTAccount)identifier.Translate(typeof(NTAccount));
|
||||
return account.Value;
|
||||
}
|
||||
|
||||
void CreateWorkflowManagementEndpoint(WorkflowServiceHost workflowServiceHost)
|
||||
{
|
||||
Binding controlEndpointBinding;
|
||||
if (workflowServiceHost.InternalBaseAddresses.Contains(Uri.UriSchemeNetPipe))
|
||||
{
|
||||
controlEndpointBinding = NamedPipeControlEndpointBinding;
|
||||
}
|
||||
else if (workflowServiceHost.InternalBaseAddresses.Contains(Uri.UriSchemeHttp))
|
||||
{
|
||||
controlEndpointBinding = HttpControlEndpointBinding;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Uri controlEndpointAddress = ServiceHost.GetVia(controlEndpointBinding.Scheme, new Uri(ControlEndpointAddress, UriKind.Relative), workflowServiceHost.InternalBaseAddresses);
|
||||
XmlQualifiedName contractName = new XmlQualifiedName(XD2.WorkflowInstanceManagementService.ContractName, XD2.WorkflowServices.Namespace);
|
||||
//Create the Endpoint Dispatcher
|
||||
EndpointAddress address = new EndpointAddress(controlEndpointAddress.AbsoluteUri);
|
||||
EndpointDispatcher endpointDispatcher = new EndpointDispatcher(address,
|
||||
XD2.WorkflowInstanceManagementService.ContractName,
|
||||
XD2.WorkflowServices.Namespace, true)
|
||||
{
|
||||
ContractFilter = new ActionMessageFilter(
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Abandon, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Cancel, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Run, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Suspend, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Terminate, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedCancel, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedRun, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedSuspend, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedTerminate, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedUnsuspend, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.TransactedUpdate, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Unsuspend, null, false),
|
||||
NamingHelper.GetMessageAction(contractName, XD2.WorkflowInstanceManagementService.Update, null, false)),
|
||||
};
|
||||
|
||||
//Create Listener
|
||||
ServiceEndpoint endpoint = new ServiceEndpoint(WorkflowControlEndpoint.WorkflowControlServiceContract, controlEndpointBinding, address);
|
||||
BindingParameterCollection parameters = workflowServiceHost.GetBindingParameters(endpoint);
|
||||
|
||||
IChannelListener listener;
|
||||
if (controlEndpointBinding.CanBuildChannelListener<IDuplexSessionChannel>(controlEndpointAddress, parameters))
|
||||
{
|
||||
listener = controlEndpointBinding.BuildChannelListener<IDuplexSessionChannel>(controlEndpointAddress, parameters);
|
||||
}
|
||||
else if (controlEndpointBinding.CanBuildChannelListener<IReplySessionChannel>(controlEndpointAddress, parameters))
|
||||
{
|
||||
listener = controlEndpointBinding.BuildChannelListener<IReplySessionChannel>(controlEndpointAddress, parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
listener = controlEndpointBinding.BuildChannelListener<IReplyChannel>(controlEndpointAddress, parameters);
|
||||
}
|
||||
|
||||
//Add the operations
|
||||
bool formatRequest;
|
||||
bool formatReply;
|
||||
foreach (OperationDescription operation in WorkflowControlEndpoint.WorkflowControlServiceContract.Operations)
|
||||
{
|
||||
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = new DataContractSerializerOperationBehavior(operation);
|
||||
|
||||
DispatchOperation operationDispatcher = new DispatchOperation(endpointDispatcher.DispatchRuntime, operation.Name,
|
||||
NamingHelper.GetMessageAction(operation, false), NamingHelper.GetMessageAction(operation, true))
|
||||
{
|
||||
Formatter = (IDispatchMessageFormatter)dataContractSerializerOperationBehavior.GetFormatter(operation, out formatRequest, out formatReply, false),
|
||||
Invoker = new ControlOperationInvoker(
|
||||
operation,
|
||||
new WorkflowControlEndpoint(controlEndpointBinding, address),
|
||||
null,
|
||||
workflowServiceHost),
|
||||
};
|
||||
endpointDispatcher.DispatchRuntime.Operations.Add(operationDispatcher);
|
||||
|
||||
OperationBehaviorAttribute operationAttribute = operation.Behaviors.Find<OperationBehaviorAttribute>();
|
||||
((IOperationBehavior)operationAttribute).ApplyDispatchBehavior(operation, operationDispatcher);
|
||||
}
|
||||
|
||||
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
|
||||
dispatchRuntime.ConcurrencyMode = ConcurrencyMode.Multiple;
|
||||
dispatchRuntime.InstanceContextProvider = new DurableInstanceContextProvider(workflowServiceHost);
|
||||
dispatchRuntime.InstanceProvider = new DurableInstanceProvider(workflowServiceHost);
|
||||
dispatchRuntime.ServiceAuthorizationManager = new WindowsAuthorizationManager(this.WindowsGroup);
|
||||
|
||||
//Create the Channel Dispatcher
|
||||
ServiceDebugBehavior serviceDebugBehavior = workflowServiceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
|
||||
ServiceBehaviorAttribute serviceBehaviorAttribute = workflowServiceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>();
|
||||
|
||||
bool includeDebugInfo = false;
|
||||
if (serviceDebugBehavior != null)
|
||||
{
|
||||
includeDebugInfo |= serviceDebugBehavior.IncludeExceptionDetailInFaults;
|
||||
}
|
||||
if (serviceBehaviorAttribute != null)
|
||||
{
|
||||
includeDebugInfo |= serviceBehaviorAttribute.IncludeExceptionDetailInFaults;
|
||||
}
|
||||
|
||||
ChannelDispatcher channelDispatcher = new ChannelDispatcher(listener, controlEndpointBinding.Name, controlEndpointBinding)
|
||||
{
|
||||
MessageVersion = controlEndpointBinding.MessageVersion,
|
||||
Endpoints = { endpointDispatcher },
|
||||
ServiceThrottle = workflowServiceHost.ServiceThrottle
|
||||
};
|
||||
workflowServiceHost.ChannelDispatchers.Add(channelDispatcher);
|
||||
}
|
||||
|
||||
sealed class WindowsAuthorizationManager : ServiceAuthorizationManager
|
||||
{
|
||||
SecurityIdentifier sid;
|
||||
|
||||
public WindowsAuthorizationManager(string windowsGroup)
|
||||
{
|
||||
NTAccount identity = new NTAccount(windowsGroup);
|
||||
|
||||
try
|
||||
{
|
||||
this.sid = identity.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
|
||||
}
|
||||
catch (IdentityNotMappedException)
|
||||
{
|
||||
throw FxTrace.Exception.Argument(windowsGroup, SR.WindowsGroupNotFound(windowsGroup));
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool CheckAccessCore(OperationContext operationContext)
|
||||
{
|
||||
WindowsPrincipal principal = new WindowsPrincipal(operationContext.ServiceSecurityContext.WindowsIdentity);
|
||||
|
||||
bool isAuthorized = false;
|
||||
|
||||
if (!operationContext.ServiceSecurityContext.IsAnonymous)
|
||||
{
|
||||
isAuthorized = principal.IsInRole(sid);
|
||||
}
|
||||
|
||||
return isAuthorized;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Activities;
|
||||
using System.Runtime;
|
||||
using System.Runtime.Diagnostics;
|
||||
using System.Runtime.DurableInstancing;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Diagnostics;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
using System.Transactions;
|
||||
|
||||
class WorkflowOperationBehavior : IOperationBehavior
|
||||
{
|
||||
Bookmark bookmark;
|
||||
|
||||
|
||||
public WorkflowOperationBehavior(Bookmark bookmark, bool canCreateInstance)
|
||||
: this(canCreateInstance)
|
||||
{
|
||||
Fx.Assert(bookmark != null, "bookmark must not be null!");
|
||||
this.bookmark = bookmark;
|
||||
}
|
||||
|
||||
protected WorkflowOperationBehavior(bool canCreateInstance)
|
||||
{
|
||||
this.CanCreateInstance = canCreateInstance;
|
||||
}
|
||||
|
||||
internal bool CanCreateInstance
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
|
||||
{
|
||||
if (operationDescription == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("operationDescription");
|
||||
}
|
||||
if (dispatchOperation == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("dispatchOperation");
|
||||
}
|
||||
if (dispatchOperation.Parent == null
|
||||
|| dispatchOperation.Parent.ChannelDispatcher == null
|
||||
|| dispatchOperation.Parent.ChannelDispatcher.Host == null
|
||||
|| dispatchOperation.Parent.ChannelDispatcher.Host.Description == null
|
||||
|| dispatchOperation.Parent.ChannelDispatcher.Host.Description.Behaviors == null)
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.DispatchOperationInInvalidState));
|
||||
}
|
||||
|
||||
ServiceHostBase serviceHost = dispatchOperation.Parent.ChannelDispatcher.Host;
|
||||
if (!(serviceHost is WorkflowServiceHost))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(
|
||||
new InvalidOperationException(SR.WorkflowBehaviorWithNonWorkflowHost(typeof(WorkflowOperationBehavior).Name)));
|
||||
}
|
||||
|
||||
CorrelationKeyCalculator correlationKeyCalculator = null;
|
||||
|
||||
ServiceEndpoint endpoint = null;
|
||||
foreach (ServiceEndpoint endpointToMatch in serviceHost.Description.Endpoints)
|
||||
{
|
||||
if (endpointToMatch.Id == dispatchOperation.Parent.EndpointDispatcher.Id)
|
||||
{
|
||||
endpoint = endpointToMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endpoint != null)
|
||||
{
|
||||
CorrelationQueryBehavior queryBehavior = endpoint.Behaviors.Find<CorrelationQueryBehavior>();
|
||||
|
||||
if (queryBehavior != null)
|
||||
{
|
||||
correlationKeyCalculator = queryBehavior.GetKeyCalculator();
|
||||
}
|
||||
}
|
||||
|
||||
dispatchOperation.Invoker = new WorkflowOperationInvoker(operationDescription,
|
||||
endpoint, correlationKeyCalculator, this, serviceHost, dispatchOperation.Invoker);
|
||||
}
|
||||
|
||||
public void Validate(OperationDescription operationDescription)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal virtual Bookmark OnResolveBookmark(WorkflowOperationContext context, out BookmarkScope bookmarkScope, out object value)
|
||||
{
|
||||
Fx.Assert(this.bookmark != null, "bookmark must not be null!");
|
||||
|
||||
CorrelationMessageProperty correlationMessageProperty;
|
||||
if (CorrelationMessageProperty.TryGet(context.OperationContext.IncomingMessageProperties, out correlationMessageProperty))
|
||||
{
|
||||
bookmarkScope = new BookmarkScope(correlationMessageProperty.CorrelationKey.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
bookmarkScope = BookmarkScope.Default;
|
||||
}
|
||||
value = context;
|
||||
return this.bookmark;
|
||||
}
|
||||
|
||||
//Invoker for workflowbased application endpoint operation
|
||||
class WorkflowOperationInvoker : ControlOperationInvoker, IInstanceTransaction
|
||||
{
|
||||
bool performanceCountersEnabled;
|
||||
bool propagateActivity;
|
||||
bool isHostingEndpoint;
|
||||
IOperationInvoker innerInvoker;
|
||||
WorkflowOperationBehavior behavior;
|
||||
bool isFirstReceiveOfTransactedReceiveScopeTree;
|
||||
|
||||
public WorkflowOperationInvoker(OperationDescription operationDescription, ServiceEndpoint endpoint,
|
||||
CorrelationKeyCalculator keyCalculator, WorkflowOperationBehavior behavior, ServiceHostBase host, IOperationInvoker innerInvoker)
|
||||
: base(operationDescription, endpoint, keyCalculator, host)
|
||||
{
|
||||
Fx.Assert(operationDescription != null, "Null OperationDescription");
|
||||
Fx.Assert(behavior != null, "Null WorkflowOperationBehavior");
|
||||
this.StaticBookmarkName = behavior.bookmark == null ? null : behavior.bookmark.Name;
|
||||
this.behavior = behavior;
|
||||
this.CanCreateInstance = behavior.CanCreateInstance;
|
||||
this.performanceCountersEnabled = PerformanceCounters.PerformanceCountersEnabled;
|
||||
this.propagateActivity = TraceUtility.ShouldPropagateActivity;
|
||||
this.isHostingEndpoint = endpoint is WorkflowHostingEndpoint;
|
||||
this.innerInvoker = innerInvoker;
|
||||
this.isFirstReceiveOfTransactedReceiveScopeTree = operationDescription.IsFirstReceiveOfTransactedReceiveScopeTree;
|
||||
}
|
||||
|
||||
public override object[] AllocateInputs()
|
||||
{
|
||||
if (this.isHostingEndpoint)
|
||||
{
|
||||
return this.innerInvoker.AllocateInputs();
|
||||
}
|
||||
// InternalReceiveMessage & InternalSendMessage is always MessageIn - MessageOut.
|
||||
// Therefore we always need an array of size 1.
|
||||
// DispatchOperationRuntime saves the request into this array in this case ( i.e., when DeserializeRequest is false)
|
||||
return new object[1];
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginServiceOperation(WorkflowServiceInstance workflowInstance, OperationContext operationContext,
|
||||
object[] inputs, Transaction currentTransaction, IInvokeReceivedNotification notification, TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
Fx.Assert(workflowInstance != null, "caller must verify");
|
||||
Fx.Assert(inputs != null, "caller must verify");
|
||||
|
||||
return WorkflowOperationContext.BeginProcessRequest(workflowInstance, operationContext, this.OperationName, inputs,
|
||||
this.performanceCountersEnabled, this.propagateActivity, currentTransaction, notification, this.behavior, this.endpoint, timeout, callback, state);
|
||||
}
|
||||
|
||||
protected override object OnEndServiceOperation(WorkflowServiceInstance durableInstance, out object[] outputs, IAsyncResult result)
|
||||
{
|
||||
// InternalSendMessage always redirects the replyMessage into the returnValue
|
||||
object returnValue = WorkflowOperationContext.EndProcessRequest(result, out outputs);
|
||||
|
||||
//we will just assert that outputs is always an empty array
|
||||
Fx.Assert(this.isHostingEndpoint || outputs == null || outputs.Length == 0, "Workflow returned a non-empty out-arg");
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public Transaction GetTransactionForInstance(OperationContext operationContext)
|
||||
{
|
||||
Transaction tx = null;
|
||||
|
||||
// We are only going to go ask the PPD for the transaction if we are NOT the first
|
||||
// Receive in a TransactedReceiveScope;
|
||||
if (!this.isFirstReceiveOfTransactedReceiveScopeTree)
|
||||
{
|
||||
// We need to get the InstanceKey.
|
||||
InstanceKey instanceKey;
|
||||
ICollection<InstanceKey> additionalKeys;
|
||||
this.GetInstanceKeys(operationContext, out instanceKey, out additionalKeys);
|
||||
Fx.Assert((instanceKey != null) && (instanceKey.IsValid), "InstanceKey is null or invalid in GetInstanceTransaction");
|
||||
|
||||
tx = this.InstanceManager.PersistenceProviderDirectory.GetTransactionForInstance(instanceKey);
|
||||
}
|
||||
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Activities;
|
||||
using System.ServiceModel;
|
||||
using System.ServiceModel.Activities.Dispatcher;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Dispatcher;
|
||||
|
||||
class WorkflowServiceBehavior : IServiceBehavior
|
||||
{
|
||||
public WorkflowServiceBehavior(WorkflowDefinitionProvider workflowDefinitionProvider)
|
||||
{
|
||||
this.WorkflowDefinitionProvider = workflowDefinitionProvider;
|
||||
}
|
||||
|
||||
public WorkflowDefinitionProvider WorkflowDefinitionProvider
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceDescription == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceDescription");
|
||||
}
|
||||
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
|
||||
DurableInstanceContextProvider instanceContextProvider = new DurableInstanceContextProvider(serviceHostBase);
|
||||
DurableInstanceProvider instanceProvider = new DurableInstanceProvider(serviceHostBase);
|
||||
|
||||
ServiceDebugBehavior serviceDebugBehavior = serviceDescription.Behaviors.Find<ServiceDebugBehavior>();
|
||||
|
||||
bool includeExceptionDetailInFaults = serviceDebugBehavior != null ?
|
||||
serviceDebugBehavior.IncludeExceptionDetailInFaults
|
||||
: false;
|
||||
|
||||
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
|
||||
{
|
||||
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
|
||||
|
||||
if (channelDispatcher != null)
|
||||
{
|
||||
foreach (EndpointDispatcher endPointDispatcher in channelDispatcher.Endpoints)
|
||||
{
|
||||
if (IsWorkflowEndpoint(endPointDispatcher))
|
||||
{
|
||||
DispatchRuntime dispatchRuntime = endPointDispatcher.DispatchRuntime;
|
||||
dispatchRuntime.AutomaticInputSessionShutdown = true;
|
||||
dispatchRuntime.ConcurrencyMode = ConcurrencyMode.Multiple;
|
||||
|
||||
//
|
||||
dispatchRuntime.InstanceContextProvider = instanceContextProvider;
|
||||
dispatchRuntime.InstanceProvider = instanceProvider;
|
||||
|
||||
if (includeExceptionDetailInFaults)
|
||||
{
|
||||
dispatchRuntime.SetDebugFlagInDispatchOperations(includeExceptionDetailInFaults);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceDescription == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceDescription");
|
||||
}
|
||||
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsWorkflowEndpoint(EndpointDispatcher endpointDispatcher)
|
||||
{
|
||||
if (endpointDispatcher.IsSystemEndpoint)
|
||||
{
|
||||
//Check whether the System Endpoint Opted in for WorkflowDispatch
|
||||
|
||||
ServiceHostBase serviceHost = endpointDispatcher.ChannelDispatcher.Host;
|
||||
ServiceEndpoint serviceEndpoint = null;
|
||||
foreach (ServiceEndpoint endpointToMatch in serviceHost.Description.Endpoints)
|
||||
{
|
||||
if (endpointToMatch.Id == endpointDispatcher.Id)
|
||||
{
|
||||
serviceEndpoint = endpointToMatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceEndpoint != null)
|
||||
{
|
||||
//User defined Std Endpoint with WorkflowContractBehaviorAttribute.
|
||||
return serviceEndpoint is WorkflowHostingEndpoint || serviceEndpoint.Contract.Behaviors.Contains(typeof(WorkflowContractBehaviorAttribute));
|
||||
}
|
||||
return false; //Some Einstein scenario where EndpointDispatcher is added explicitly without associated ServiceEndpoint.
|
||||
}
|
||||
return true; //Application Endpoint
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
public enum WorkflowUnhandledExceptionAction
|
||||
{
|
||||
Abandon,
|
||||
Cancel,
|
||||
Terminate,
|
||||
AbandonAndSuspend,
|
||||
}
|
||||
|
||||
static class WorkflowUnhandledExceptionActionHelper
|
||||
{
|
||||
internal static bool IsDefined(WorkflowUnhandledExceptionAction value)
|
||||
{
|
||||
return (value == WorkflowUnhandledExceptionAction.Abandon ||
|
||||
value == WorkflowUnhandledExceptionAction.Cancel ||
|
||||
value == WorkflowUnhandledExceptionAction.Terminate ||
|
||||
value == WorkflowUnhandledExceptionAction.AbandonAndSuspend);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//----------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//----------------------------------------------------------------
|
||||
|
||||
namespace System.ServiceModel.Activities.Description
|
||||
{
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
|
||||
[Fx.Tag.XamlVisible(false)]
|
||||
public class WorkflowUnhandledExceptionBehavior : IServiceBehavior
|
||||
{
|
||||
internal const WorkflowUnhandledExceptionAction defaultAction = WorkflowUnhandledExceptionAction.AbandonAndSuspend;
|
||||
|
||||
WorkflowUnhandledExceptionAction action;
|
||||
|
||||
public WorkflowUnhandledExceptionBehavior()
|
||||
{
|
||||
this.action = defaultAction;
|
||||
}
|
||||
|
||||
public WorkflowUnhandledExceptionAction Action
|
||||
{
|
||||
get { return this.action; }
|
||||
set
|
||||
{
|
||||
if (!WorkflowUnhandledExceptionActionHelper.IsDefined(value))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new ArgumentOutOfRangeException("value"));
|
||||
}
|
||||
this.action = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
WorkflowServiceHost workflowServiceHost = serviceHostBase as WorkflowServiceHost;
|
||||
if (workflowServiceHost != null)
|
||||
{
|
||||
workflowServiceHost.UnhandledExceptionAction = this.Action;
|
||||
}
|
||||
}
|
||||
|
||||
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
|
||||
{
|
||||
if (serviceDescription == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceDescription");
|
||||
}
|
||||
|
||||
if (serviceHostBase == null)
|
||||
{
|
||||
throw FxTrace.Exception.ArgumentNull("serviceHostBase");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user