1737 lines
73 KiB
C#
1737 lines
73 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.Workflow.Activities
|
|
{
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Collections;
|
|
using System.Collections.ObjectModel;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.Design;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IdentityModel.Claims;
|
|
using System.Security.Permissions;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Description;
|
|
using System.ServiceModel.Dispatcher;
|
|
using System.Workflow.Activities;
|
|
using System.Workflow.ComponentModel;
|
|
using System.Workflow.ComponentModel.Compiler;
|
|
using System.Workflow.ComponentModel.Design;
|
|
using System.Workflow.ComponentModel.Serialization;
|
|
using System.Workflow.Runtime;
|
|
using System.Xml;
|
|
|
|
[SR2Description(SR2DescriptionAttribute.ReceiveActivityDescription)]
|
|
[SR2Category(SR2CategoryAttribute.Standard)]
|
|
[Designer(typeof(ReceiveActivityDesigner), typeof(IDesigner))]
|
|
[ToolboxBitmap(typeof(ReceiveActivity), "Design.Resources.ReceiveActivity.png")]
|
|
[ActivityValidator(typeof(ReceiveActivityValidator))]
|
|
[Serializable]
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public sealed class ReceiveActivity : SequenceActivity,
|
|
IEventActivity,
|
|
IActivityEventListener<QueueEventArgs>,
|
|
IServiceDescriptionBuilder
|
|
{
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
public static readonly DependencyProperty FaultMessageProperty =
|
|
DependencyProperty.Register("FaultMessage",
|
|
typeof(FaultException),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(null));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
public static readonly DependencyProperty OperationValidationEvent =
|
|
DependencyProperty.Register("OperationValidation",
|
|
typeof(EventHandler<OperationValidationEventArgs>),
|
|
typeof(ReceiveActivity));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
public static readonly DependencyProperty WorkflowServiceAttributesProperty =
|
|
DependencyProperty.RegisterAttached("WorkflowServiceAttributes",
|
|
typeof(WorkflowServiceAttributes), typeof(ReceiveActivity),
|
|
new PropertyMetadata(null, DependencyPropertyOptions.Metadata,
|
|
ReceiveActivity.GetWorkflowServiceAttributesValueOverride, null),
|
|
typeof(WorkflowServiceAttributesDynamicPropertyValidator));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
internal static readonly DependencyProperty CanCreateInstanceProperty =
|
|
DependencyProperty.Register("CanCreateInstance",
|
|
typeof(bool),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(false, DependencyPropertyOptions.Metadata));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
internal static readonly DependencyProperty ContextTokenProperty =
|
|
DependencyProperty.Register("ContextToken",
|
|
typeof(ContextToken),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(null, DependencyPropertyOptions.Metadata));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
internal static readonly DependencyProperty ParameterBindingsProperty =
|
|
DependencyProperty.Register("ParameterBindings",
|
|
typeof(WorkflowParameterBindingCollection),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(DependencyPropertyOptions.Metadata | DependencyPropertyOptions.ReadOnly));
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
|
internal static readonly DependencyProperty ServiceOperationInfoProperty =
|
|
DependencyProperty.Register("ServiceOperationInfo",
|
|
typeof(OperationInfoBase),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(DependencyPropertyOptions.Metadata));
|
|
|
|
private static readonly DependencyProperty QueueNameProperty =
|
|
DependencyProperty.Register("QueueName",
|
|
typeof(string),
|
|
typeof(ReceiveActivity));
|
|
|
|
private static readonly DependencyProperty RequestContextProperty =
|
|
DependencyProperty.Register("RequestContext",
|
|
typeof(WorkflowRequestContext),
|
|
typeof(ReceiveActivity));
|
|
|
|
static DependencyProperty QueueInitializationModeProperty =
|
|
DependencyProperty.Register("QueueInitializationMode",
|
|
typeof(QueueInitializationMode),
|
|
typeof(ReceiveActivity),
|
|
new PropertyMetadata(QueueInitializationMode.Standalone));
|
|
|
|
[NonSerialized]
|
|
private ReceiveOperationInfoHelper operationHelper;
|
|
|
|
private IActivityEventListener<QueueEventArgs> securityShim;
|
|
private IActivityEventListener<QueueEventArgs> validationShim;
|
|
|
|
[NonSerialized]
|
|
private static Hashtable requestContextsCache = Hashtable.Synchronized(new Hashtable());
|
|
private bool isContextCached;
|
|
|
|
public ReceiveActivity()
|
|
{
|
|
base.SetReadOnlyPropertyValue(ReceiveActivity.ParameterBindingsProperty,
|
|
new WorkflowParameterBindingCollection(this));
|
|
}
|
|
|
|
public ReceiveActivity(string name)
|
|
: base(name)
|
|
{
|
|
base.SetReadOnlyPropertyValue(ReceiveActivity.ParameterBindingsProperty,
|
|
new WorkflowParameterBindingCollection(this));
|
|
}
|
|
|
|
[SRCategory(SR2CategoryAttribute.Handlers)]
|
|
[SR2Description(SR2DescriptionAttribute.Receive_OperationValidation_Description)]
|
|
[MergableProperty(false)]
|
|
public event EventHandler<OperationValidationEventArgs> OperationValidation
|
|
{
|
|
add
|
|
{
|
|
base.AddHandler(OperationValidationEvent, value);
|
|
}
|
|
remove
|
|
{
|
|
base.RemoveHandler(OperationValidationEvent, value);
|
|
}
|
|
}
|
|
|
|
[Browsable(true)]
|
|
[DefaultValue(false)]
|
|
[SR2Category(SR2CategoryAttribute.Activity)]
|
|
[SR2Description(SR2DescriptionAttribute.Receive_CanCreateInstance_Description)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public bool CanCreateInstance
|
|
{
|
|
get
|
|
{
|
|
return ((bool)(base.GetValue(ReceiveActivity.CanCreateInstanceProperty)));
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ReceiveActivity.CanCreateInstanceProperty, value);
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public IDictionary<string, string> Context
|
|
{
|
|
get
|
|
{
|
|
if (this.ContextToken == null)
|
|
{
|
|
return ReceiveActivity.GetRootContext(this);
|
|
}
|
|
return ReceiveActivity.GetContext(this, this.ContextToken);
|
|
}
|
|
}
|
|
|
|
[DefaultValue(null)]
|
|
[MergableProperty(false)]
|
|
[RefreshProperties(RefreshProperties.All)]
|
|
[SR2Category(SR2CategoryAttribute.Activity)]
|
|
[SR2Description(SR2DescriptionAttribute.Receive_ContextToken_Description)]
|
|
[TypeConverter(typeof(ContextTokenTypeConverter))]
|
|
public ContextToken ContextToken
|
|
{
|
|
get
|
|
{
|
|
return base.GetValue(ContextTokenProperty) as ContextToken;
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ContextTokenProperty, value);
|
|
}
|
|
}
|
|
|
|
[Browsable(true)]
|
|
[DefaultValue(null)]
|
|
[SR2Category(SR2CategoryAttribute.Activity)]
|
|
[SR2Description(SR2DescriptionAttribute.Receive_FaultMessage_Description)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public FaultException FaultMessage
|
|
{
|
|
get
|
|
{
|
|
return ((FaultException)base.GetValue(ReceiveActivity.FaultMessageProperty));
|
|
}
|
|
|
|
set
|
|
{
|
|
base.SetValue(ReceiveActivity.FaultMessageProperty, value);
|
|
}
|
|
}
|
|
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public WorkflowParameterBindingCollection ParameterBindings
|
|
{
|
|
get
|
|
{
|
|
return ((WorkflowParameterBindingCollection)(base.GetValue(ReceiveActivity.ParameterBindingsProperty)));
|
|
}
|
|
}
|
|
|
|
|
|
[Browsable(true)]
|
|
[SR2Category(SR2CategoryAttribute.Activity)]
|
|
[SR2Description(SR2DescriptionAttribute.Receive_OperationInfo_Description)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
public OperationInfoBase ServiceOperationInfo
|
|
{
|
|
get
|
|
{
|
|
return ((OperationInfoBase)(base.GetValue(ReceiveActivity.ServiceOperationInfoProperty)));
|
|
}
|
|
set
|
|
{
|
|
OperationInfoBase currentValue = ((OperationInfoBase)(base.GetValue(ReceiveActivity.ServiceOperationInfoProperty)));
|
|
if (value != null && currentValue != value)
|
|
{
|
|
DependencyProperty ParentDependencyObjectProperty =
|
|
DependencyProperty.FromName("ParentDependencyObject", typeof(DependencyObject));
|
|
|
|
Activity currentParent = value.GetValue(ParentDependencyObjectProperty) as Activity;
|
|
|
|
if (currentParent != null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
|
|
"value",
|
|
SR2.GetString(SR2.Error_OperationIsAlreadyAssociatedWithActivity,
|
|
value,
|
|
currentParent.QualifiedName));
|
|
}
|
|
|
|
if (currentValue != null)
|
|
{
|
|
currentValue.SetValue(ParentDependencyObjectProperty, null);
|
|
}
|
|
|
|
value.SetValue(ParentDependencyObjectProperty, this);
|
|
}
|
|
|
|
if (this.DesignMode && value is OperationInfo)
|
|
{
|
|
Activity rootActivity = this.RootActivity;
|
|
rootActivity.RemoveProperty(DynamicContractTypeBuilder.DynamicContractTypesProperty);
|
|
}
|
|
|
|
base.SetValue(ReceiveActivity.ServiceOperationInfoProperty, value);
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
internal WorkflowRequestContext RequestContext
|
|
{
|
|
get
|
|
{
|
|
return ((WorkflowRequestContext)(base.GetValue(ReceiveActivity.RequestContextProperty)));
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ReceiveActivity.RequestContextProperty, value);
|
|
}
|
|
}
|
|
|
|
IComparable IEventActivity.QueueName
|
|
{
|
|
get { return this.GetValue(ReceiveActivity.QueueNameProperty) as string; }
|
|
}
|
|
|
|
ReceiveOperationInfoHelper OperationHelper
|
|
{
|
|
get
|
|
{
|
|
if (this.operationHelper == null)
|
|
{
|
|
if (this.UserData.Contains(typeof(ReceiveOperationInfoHelper)))
|
|
{
|
|
this.operationHelper = this.UserData[typeof(ReceiveOperationInfoHelper)] as ReceiveOperationInfoHelper;
|
|
}
|
|
}
|
|
|
|
if (this.operationHelper == null)
|
|
{
|
|
this.operationHelper = new ReceiveOperationInfoHelper(this.Site, this);
|
|
this.UserData[typeof(ReceiveOperationInfoHelper)] = this.operationHelper;
|
|
}
|
|
|
|
return this.operationHelper;
|
|
}
|
|
}
|
|
|
|
private QueueInitializationMode QueueInitializationMode
|
|
{
|
|
get
|
|
{
|
|
return (QueueInitializationMode)base.GetValue(ReceiveActivity.QueueInitializationModeProperty);
|
|
}
|
|
set
|
|
{
|
|
base.SetValue(ReceiveActivity.QueueInitializationModeProperty, value);
|
|
}
|
|
}
|
|
|
|
public static IDictionary<string, string> GetContext(Activity activity,
|
|
ContextToken contextToken)
|
|
{
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
if (contextToken == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextToken");
|
|
}
|
|
|
|
if (contextToken.IsRootContext)
|
|
{
|
|
return GetRootContext(activity);
|
|
}
|
|
|
|
return GetContext(activity, contextToken.Name, contextToken.OwnerActivityName);
|
|
}
|
|
|
|
public static IDictionary<string, string> GetContext(Activity activity,
|
|
string contextName,
|
|
string ownerActivityName)
|
|
{
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
if (string.IsNullOrEmpty(contextName))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("contextName",
|
|
SR2.GetString(SR2.Error_ArgumentValueNullOrEmptyString));
|
|
}
|
|
|
|
ReceiveContext receiveContext = ContextToken.GetReceiveContext(activity, contextName, ownerActivityName);
|
|
if (receiveContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_CannotFindReceiveContext, contextName)));
|
|
}
|
|
|
|
return receiveContext.Properties;
|
|
}
|
|
|
|
public static IDictionary<string, string> GetRootContext(Activity activity)
|
|
{
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
|
|
ReceiveContext receiveContext = ContextToken.GetRootReceiveContext(activity);
|
|
if (receiveContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_CannotFindReceiveContext, ContextToken.RootContextName)));
|
|
}
|
|
|
|
return receiveContext.Properties;
|
|
}
|
|
|
|
public static object GetWorkflowServiceAttributes(object dependencyObject)
|
|
{
|
|
if (dependencyObject == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
|
|
}
|
|
if (!(dependencyObject is Activity))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
|
|
"dependencyObject",
|
|
SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
|
|
}
|
|
|
|
return (dependencyObject as DependencyObject).GetValue(ReceiveActivity.WorkflowServiceAttributesProperty);
|
|
}
|
|
|
|
public static void SetWorkflowServiceAttributes(object dependencyObject,
|
|
object value)
|
|
{
|
|
if (dependencyObject == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
|
|
}
|
|
if (!(dependencyObject is Activity))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
|
|
"dependencyObject",
|
|
SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
|
|
}
|
|
|
|
(dependencyObject as DependencyObject).SetValue(ReceiveActivity.WorkflowServiceAttributesProperty, value);
|
|
}
|
|
|
|
void IActivityEventListener<QueueEventArgs>.OnEvent(object sender,
|
|
QueueEventArgs e)
|
|
{
|
|
if (sender == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
|
|
}
|
|
|
|
if (e == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("e");
|
|
}
|
|
|
|
ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid,
|
|
"sender",
|
|
typeof(ActivityExecutionContext))));
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(e.QueueName);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound, e.QueueName)));
|
|
}
|
|
|
|
if (workflowQueue.Count != 0)
|
|
{
|
|
WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
|
|
if (requestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
|
|
this.QualifiedName)));
|
|
}
|
|
if (ValidationShim.EvaluateSecurityConstraints(executionContext, this, requestContext))
|
|
{
|
|
workflowQueue.UnregisterForQueueItemAvailable(this);
|
|
this.RequestContext = workflowQueue.Dequeue() as WorkflowRequestContext;
|
|
CacheRequestContext(this.RequestContext);
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
if (this.securityShim != null)
|
|
{
|
|
workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
|
|
this.securityShim = null;
|
|
}
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
|
|
if (this.RequestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable, this.QualifiedName)));
|
|
}
|
|
|
|
if (ExecuteActivity(this.RequestContext, executionContext) == ActivityExecutionStatus.Closed)
|
|
{
|
|
try
|
|
{
|
|
executionContext.CloseActivity();
|
|
}
|
|
finally
|
|
{
|
|
RemoveRequestContext();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
workflowQueue.Dequeue();
|
|
|
|
try
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
|
|
}
|
|
catch (CommunicationException cex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, cex);
|
|
}
|
|
catch (TimeoutException tex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, tex);
|
|
}
|
|
|
|
if (requestContext.ContextProperties == null ||
|
|
!(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.WorkflowInstanceId)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void IEventActivity.Subscribe(ActivityExecutionContext parentContext,
|
|
IActivityEventListener<QueueEventArgs> parentEventHandler)
|
|
{
|
|
if (parentContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentContext");
|
|
}
|
|
|
|
if (parentEventHandler == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentEventHandler");
|
|
}
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
this.QueueInitializationMode = QueueInitializationMode.EventDriven;
|
|
}
|
|
|
|
// make sure that we are getting the proper queue
|
|
// even if that means creating a new queue
|
|
// given our conversation context and execution context.
|
|
//
|
|
WorkflowQueue workflowQueue = GetWorkflowQueue(parentContext);
|
|
if (workflowQueue != null)
|
|
{
|
|
if (this.QueueInitializationMode == QueueInitializationMode.EventDriven)
|
|
{
|
|
workflowQueue.Enabled = true;
|
|
}
|
|
|
|
if (this.validationShim == null)
|
|
{
|
|
this.validationShim = new ValidationShim(this, parentEventHandler);
|
|
}
|
|
if (this.securityShim == null)
|
|
{
|
|
this.securityShim = new SecurityShim(this);
|
|
}
|
|
|
|
workflowQueue.RegisterForQueueItemArrived(this.securityShim);
|
|
workflowQueue.RegisterForQueueItemAvailable(this.validationShim, this.QualifiedName);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void IEventActivity.Unsubscribe(ActivityExecutionContext parentContext,
|
|
IActivityEventListener<QueueEventArgs> parentEventHandler)
|
|
{
|
|
if (parentContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentContext");
|
|
}
|
|
|
|
if (parentEventHandler == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parentEventHandler");
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = parentContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
// get the queue using the queue name
|
|
// at this point the conversation context should have been re-initialized if necessary
|
|
//
|
|
WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(((IEventActivity)this).QueueName);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
|
|
((IEventActivity)this).QueueName)));
|
|
}
|
|
|
|
if (this.securityShim != null)
|
|
{
|
|
workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
|
|
this.securityShim = null;
|
|
}
|
|
if (this.validationShim != null)
|
|
{
|
|
workflowQueue.UnregisterForQueueItemAvailable(this.validationShim);
|
|
}
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.EventDriven)
|
|
{
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2103")] // Review imperative security, because constructing PrincipalPermission
|
|
void IServiceDescriptionBuilder.BuildServiceDescription(ServiceDescriptionContext context)
|
|
{
|
|
if (context == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
|
|
}
|
|
|
|
if (!this.Enabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
|
|
if (serviceOperationInfo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
|
|
}
|
|
|
|
// set the workflow service behavior
|
|
//
|
|
IServiceDescriptionBuilder serviceAttributes =
|
|
GetWorkflowServiceAttributes(this.RootActivity) as IServiceDescriptionBuilder;
|
|
|
|
if (serviceAttributes != null)
|
|
{
|
|
serviceAttributes.BuildServiceDescription(context);
|
|
}
|
|
|
|
if (context.ReflectedContracts == null || context.WorkflowOperationBehaviors == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// add contract types and configure the operation behavior
|
|
//
|
|
Type contractType = serviceOperationInfo.GetContractType(((IComponent)this).Site);
|
|
|
|
List<Type> interfaces = ServiceOperationHelpers.GetContracts(contractType);
|
|
for (int i = 0; i < interfaces.Count; i++)
|
|
{
|
|
Type interfaceType = interfaces[i];
|
|
ContractDescription contractDescription = null;
|
|
|
|
if (!context.ReflectedContracts.Contains(interfaceType))
|
|
{
|
|
contractDescription = ContractDescription.GetContract(interfaceType);
|
|
ServiceOperationHelpers.SetWorkflowOperationBehavior(contractDescription, context);
|
|
|
|
context.Contracts.Add(contractDescription.ConfigurationName, contractDescription);
|
|
context.ReflectedContracts.Add(contractDescription.ContractType);
|
|
}
|
|
else
|
|
{
|
|
contractDescription = context.Contracts[ContractDescription.GetContract(interfaceType).ConfigurationName];
|
|
}
|
|
|
|
Collection<ContractDescription> inheritedContractDescriptions = contractDescription.GetInheritedContracts();
|
|
for (int j = 0; j < inheritedContractDescriptions.Count; j++)
|
|
{
|
|
ContractDescription inheritedContractDescription = inheritedContractDescriptions[j];
|
|
if (!context.ReflectedContracts.Contains(inheritedContractDescription.ContractType))
|
|
{
|
|
ServiceOperationHelpers.SetWorkflowOperationBehavior(inheritedContractDescription, context);
|
|
|
|
context.Contracts.Add(inheritedContractDescription.ConfigurationName, inheritedContractDescription);
|
|
context.ReflectedContracts.Add(inheritedContractDescription.ContractType);
|
|
}
|
|
}
|
|
}
|
|
|
|
Type operationDeclaringType = null;
|
|
MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(((IComponent)this).Site);
|
|
if (methodInfo != null)
|
|
{
|
|
operationDeclaringType = methodInfo.DeclaringType;
|
|
}
|
|
|
|
if (operationDeclaringType != null)
|
|
{
|
|
WorkflowOperationBehavior behavior = null;
|
|
KeyValuePair<Type, string> operationKey =
|
|
new KeyValuePair<Type, string>(operationDeclaringType, serviceOperationInfo.Name);
|
|
|
|
if (context.WorkflowOperationBehaviors.TryGetValue(operationKey, out behavior) && behavior != null)
|
|
{
|
|
if (!behavior.CanCreateInstance && this.CanCreateInstance)
|
|
{
|
|
behavior.CanCreateInstance = true;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(serviceOperationInfo.PrincipalPermissionRole)
|
|
|| !string.IsNullOrEmpty(serviceOperationInfo.PrincipalPermissionName))
|
|
{
|
|
if (behavior.ServiceAuthorizationManager == null)
|
|
{
|
|
PrincipalPermission permission =
|
|
new PrincipalPermission(serviceOperationInfo.PrincipalPermissionName,
|
|
serviceOperationInfo.PrincipalPermissionRole, true);
|
|
|
|
PrincipalPermissionServiceAuthorizationManager authManager
|
|
= new PrincipalPermissionServiceAuthorizationManager(permission);
|
|
|
|
behavior.ServiceAuthorizationManager = authManager;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected internal override void Initialize(IServiceProvider provider)
|
|
{
|
|
if (provider == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("provider");
|
|
}
|
|
|
|
ContextToken.Register(this, this.WorkflowInstanceId);
|
|
|
|
SetQueueInitializationMode();
|
|
|
|
// make sure that we are getting the proper queue
|
|
// even if that means creating a new queue
|
|
// given our conversation context and execution context.
|
|
//
|
|
WorkflowQueue workflowQueue = GetWorkflowQueue(provider);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
|
|
((IEventActivity)this).QueueName)));
|
|
}
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.StateMachine)
|
|
{
|
|
workflowQueue.Enabled = true;
|
|
}
|
|
|
|
base.Initialize(provider);
|
|
}
|
|
|
|
internal void GetParameterPropertyDescriptors(IDictionary properties)
|
|
{
|
|
if (properties == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
|
|
}
|
|
|
|
if (((IComponent)this).Site == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
|
|
if (serviceOperationInfo != null)
|
|
{
|
|
MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(((IComponent)this).Site);
|
|
if (methodInfo != null)
|
|
{
|
|
ArrayList paramInfo = new ArrayList(methodInfo.GetParameters());
|
|
if (!(methodInfo.ReturnType == typeof(void)))
|
|
{
|
|
paramInfo.Add(methodInfo.ReturnParameter);
|
|
}
|
|
|
|
foreach (ParameterInfo param in paramInfo)
|
|
{
|
|
if (param.ParameterType != null)
|
|
{
|
|
PropertyDescriptor prop =
|
|
new ParameterInfoBasedPropertyDescriptor(typeof(ReceiveActivity),
|
|
param, true, DesignOnlyAttribute.Yes);
|
|
|
|
properties[prop.Name] = prop;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext)
|
|
{
|
|
try
|
|
{
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
|
|
((IEventActivity)this).QueueName)));
|
|
}
|
|
|
|
workflowQueue.UnregisterForQueueItemAvailable(this);
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
if (this.securityShim != null)
|
|
{
|
|
workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
|
|
this.securityShim = null;
|
|
}
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
RemoveRequestContext();
|
|
}
|
|
|
|
return base.Cancel(executionContext);
|
|
}
|
|
|
|
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
|
|
{
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
// make sure that we are getting the proper queue
|
|
// even if that means creating a new queue
|
|
// given our conversation context and execution context.
|
|
//
|
|
WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
|
|
((IEventActivity)this).QueueName)));
|
|
}
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone && workflowQueue.Count == 0)
|
|
{
|
|
workflowQueue.Enabled = true;
|
|
|
|
if (this.securityShim == null)
|
|
{
|
|
this.securityShim = new SecurityShim(this);
|
|
}
|
|
workflowQueue.RegisterForQueueItemArrived(this.securityShim);
|
|
workflowQueue.RegisterForQueueItemAvailable(this, this.QualifiedName);
|
|
return ActivityExecutionStatus.Executing;
|
|
}
|
|
else if (workflowQueue.Count == 0)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
|
|
this.QualifiedName)));
|
|
}
|
|
|
|
WorkflowRequestContext requestContext = workflowQueue.Dequeue() as WorkflowRequestContext;
|
|
|
|
if (requestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
|
|
this.QualifiedName)));
|
|
}
|
|
else
|
|
{
|
|
if (this.validationShim != null)
|
|
{
|
|
this.RequestContext = requestContext;
|
|
CacheRequestContext(requestContext);
|
|
}
|
|
else if (ValidationShim.EvaluateSecurityConstraints(executionContext, this, requestContext) == true)
|
|
{
|
|
this.RequestContext = requestContext;
|
|
CacheRequestContext(requestContext);
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
|
|
}
|
|
catch (CommunicationException cex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, cex);
|
|
}
|
|
catch (TimeoutException tex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, tex);
|
|
}
|
|
|
|
if (requestContext.ContextProperties == null ||
|
|
!(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.WorkflowInstanceId)));
|
|
}
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
if (this.securityShim == null)
|
|
{
|
|
this.securityShim = new SecurityShim(this);
|
|
}
|
|
workflowQueue.RegisterForQueueItemArrived(this.securityShim);
|
|
}
|
|
|
|
workflowQueue.RegisterForQueueItemAvailable(this, this.QualifiedName);
|
|
return ActivityExecutionStatus.Executing;
|
|
}
|
|
}
|
|
|
|
return ExecuteActivity(this.RequestContext, executionContext);
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
|
|
Justification = "Supress any exceptions thrown by SendFault to avoid calling HandleFault infinitely.")]
|
|
protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext,
|
|
Exception exception)
|
|
{
|
|
try
|
|
{
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
if (exception == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("exception");
|
|
}
|
|
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = GetWorkflowQueue(executionContext);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound,
|
|
((IEventActivity)this).QueueName)));
|
|
}
|
|
|
|
workflowQueue.UnregisterForQueueItemAvailable(this);
|
|
|
|
if (this.QueueInitializationMode == QueueInitializationMode.Standalone)
|
|
{
|
|
if (this.securityShim != null)
|
|
{
|
|
workflowQueue.UnregisterForQueueItemArrived(this.securityShim);
|
|
this.securityShim = null;
|
|
}
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
|
|
RestoreRequestContext();
|
|
|
|
if (this.RequestContext != null)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - sending fault response message",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
if (this.FaultMessage != null)
|
|
{
|
|
try
|
|
{
|
|
this.RequestContext.SendFault(this.FaultMessage, null);
|
|
}
|
|
catch
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send response fault message.",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
this.RequestContext.SendFault(exception, null);
|
|
}
|
|
catch
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send response fault message.",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
RemoveRequestContext();
|
|
}
|
|
|
|
return base.HandleFault(executionContext, exception);
|
|
}
|
|
|
|
protected override void InitializeProperties()
|
|
{
|
|
OperationInfoBase serviceOperationInfo = this.ServiceOperationInfo;
|
|
|
|
if (serviceOperationInfo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
|
|
}
|
|
|
|
OperationParameterInfoCollection parameters = null;
|
|
|
|
Activity definitionRoot = base.RootActivity.GetValue(Activity.WorkflowDefinitionProperty) as Activity;
|
|
if (definitionRoot != null)
|
|
{
|
|
ReceiveActivity definition = definitionRoot.GetActivityByName(this.QualifiedName, true) as ReceiveActivity;
|
|
if ((definition != null) && definition.UserData.Contains(typeof(OperationParameterInfoCollection)))
|
|
{
|
|
parameters = definition.UserData[typeof(OperationParameterInfoCollection)] as OperationParameterInfoCollection;
|
|
}
|
|
}
|
|
|
|
if (parameters == null)
|
|
{
|
|
parameters = serviceOperationInfo.GetParameters(this.Site);
|
|
this.UserData[typeof(OperationParameterInfoCollection)] = parameters;
|
|
}
|
|
|
|
WorkflowParameterBindingCollection bindings = this.ParameterBindings;
|
|
|
|
foreach (OperationParameterInfo parameter in parameters)
|
|
{
|
|
if (!bindings.Contains(parameter.Name))
|
|
{
|
|
bindings.Add(new WorkflowParameterBinding(parameter.Name));
|
|
}
|
|
}
|
|
|
|
base.InitializeProperties();
|
|
}
|
|
|
|
protected override void OnSequenceComplete(ActivityExecutionContext executionContext)
|
|
{
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
try
|
|
{
|
|
RestoreRequestContext();
|
|
if (this.RequestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_RequestContextUnavailable,
|
|
this.QualifiedName)));
|
|
}
|
|
|
|
object returnValue;
|
|
object[] outputValues;
|
|
|
|
if (this.FaultMessage != null)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - sending fault response message",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
try
|
|
{
|
|
this.RequestContext.SendFault(this.FaultMessage, null);
|
|
}
|
|
catch (CommunicationException cex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault response message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, cex);
|
|
throw;
|
|
}
|
|
catch (TimeoutException tex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault response message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, tex);
|
|
throw;
|
|
}
|
|
}
|
|
else if (!this.OperationHelper.IsOneWay)
|
|
{
|
|
returnValue = this.OperationHelper.GetOutputs(this, out outputValues);
|
|
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - sending response message",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
try
|
|
{
|
|
this.RequestContext.SendReply(returnValue, outputValues, null);
|
|
}
|
|
catch (CommunicationException cex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send response message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, cex);
|
|
throw;
|
|
}
|
|
catch (TimeoutException tex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send response message. Error: {2}",
|
|
this.WorkflowInstanceId, this.QualifiedName, tex);
|
|
throw;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - completing one way operation",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
this.RequestContext.SetOperationCompleted();
|
|
}
|
|
|
|
base.OnSequenceComplete(executionContext);
|
|
|
|
// Null out the request context to reduce serialization size of the activity.
|
|
this.RequestContext = null;
|
|
}
|
|
finally
|
|
{
|
|
RemoveRequestContext();
|
|
}
|
|
}
|
|
|
|
static object GetWorkflowServiceAttributesValueOverride(object dependencyObject)
|
|
{
|
|
if (dependencyObject == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("dependencyObject");
|
|
}
|
|
|
|
if (!(dependencyObject is Activity))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
|
|
"dependencyObject",
|
|
SR2.GetString(SR2.Error_UnexpectedArgumentType, typeof(Activity).FullName));
|
|
}
|
|
|
|
Activity activity = dependencyObject as Activity;
|
|
|
|
if (activity.GetValueBase(ReceiveActivity.WorkflowServiceAttributesProperty) == null)
|
|
{
|
|
if (activity.DesignMode)
|
|
{
|
|
WorkflowServiceAttributes workflowServiceAttribsValue = new WorkflowServiceAttributes();
|
|
Activity rootActivity = activity.RootActivity;
|
|
if (rootActivity != null)
|
|
{
|
|
string fullClassName = (String)rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty);
|
|
if (!String.IsNullOrEmpty(fullClassName))
|
|
{
|
|
string namespaceName;
|
|
string className;
|
|
Helpers.GetNamespaceAndClassName(fullClassName, out namespaceName, out className);
|
|
workflowServiceAttribsValue.ConfigurationName = fullClassName;
|
|
workflowServiceAttribsValue.Name = className;
|
|
}
|
|
}
|
|
activity.SetValue(ReceiveActivity.WorkflowServiceAttributesProperty, workflowServiceAttribsValue);
|
|
return workflowServiceAttribsValue;
|
|
}
|
|
}
|
|
return activity.GetValueBase(ReceiveActivity.WorkflowServiceAttributesProperty);
|
|
}
|
|
|
|
private ActivityExecutionStatus ExecuteActivity(WorkflowRequestContext requestContext,
|
|
ActivityExecutionContext executionContext)
|
|
{
|
|
if (requestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestContext");
|
|
}
|
|
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
|
|
}
|
|
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - received message",
|
|
this.WorkflowInstanceId, this.QualifiedName);
|
|
|
|
this.OperationHelper.PopulateInputs(this, requestContext.Inputs);
|
|
|
|
return base.Execute(executionContext);
|
|
}
|
|
|
|
private WorkflowQueue GetWorkflowQueue(IServiceProvider provider)
|
|
{
|
|
if (provider == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("provider");
|
|
}
|
|
|
|
if (this.ServiceOperationInfo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, this.Name)));
|
|
}
|
|
|
|
WorkflowQueuingService queuingService =
|
|
provider.GetService(typeof(WorkflowQueuingService)) as WorkflowQueuingService;
|
|
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService,
|
|
typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = null;
|
|
string queueName = this.OperationHelper.GetWorkflowQueueName(this.Context);
|
|
this.SetValue(QueueNameProperty, queueName);
|
|
|
|
if (!queuingService.Exists(queueName))
|
|
{
|
|
workflowQueue = queuingService.CreateWorkflowQueue(queueName, false);
|
|
workflowQueue.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
workflowQueue = queuingService.GetWorkflowQueue(queueName);
|
|
}
|
|
|
|
return workflowQueue;
|
|
}
|
|
|
|
private void SetQueueInitializationMode()
|
|
{
|
|
if (this.parent != null && this.parent is EventDrivenActivity)
|
|
{
|
|
if (this.parent.parent != null && this.parent.parent is StateActivity)
|
|
{
|
|
this.QueueInitializationMode = QueueInitializationMode.StateMachine;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CacheRequestContext(WorkflowRequestContext requestContext)
|
|
{
|
|
string keyValue = WorkflowEnvironment.WorkflowInstanceId.ToString() + ":" +
|
|
this.GetValue(ReceiveActivity.QueueNameProperty) as string;
|
|
requestContextsCache[keyValue] = requestContext;
|
|
this.isContextCached = true;
|
|
}
|
|
|
|
private void RestoreRequestContext()
|
|
{
|
|
string keyValue = WorkflowEnvironment.WorkflowInstanceId.ToString() + ":"
|
|
+ this.GetValue(ReceiveActivity.QueueNameProperty) as string;
|
|
if (requestContextsCache.ContainsKey(keyValue))
|
|
{
|
|
this.RequestContext = requestContextsCache[keyValue] as WorkflowRequestContext;
|
|
}
|
|
}
|
|
|
|
private void RemoveRequestContext()
|
|
{
|
|
requestContextsCache.Remove(WorkflowEnvironment.WorkflowInstanceId.ToString() + ":" +
|
|
this.GetValue(ReceiveActivity.QueueNameProperty) as string);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
try
|
|
{
|
|
if (disposing && this.isContextCached)
|
|
{
|
|
RemoveRequestContext();
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
base.Dispose(disposing);
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
class ReceiveOperationInfoHelper
|
|
{
|
|
string baseQueueName;
|
|
bool hasReturnValue = false;
|
|
IList<KeyValuePair<int, string>> inputParameters;
|
|
bool isOneWay = false;
|
|
IDictionary<int, Type> notNullableParameters;
|
|
bool nullableReturnValue = true;
|
|
string operationName;
|
|
IList<KeyValuePair<int, string>> outputParameters;
|
|
string returnTypeName;
|
|
|
|
public ReceiveOperationInfoHelper(IServiceProvider serviceProvider, ReceiveActivity activity)
|
|
{
|
|
outputParameters = new List<KeyValuePair<int, string>>();
|
|
inputParameters = new List<KeyValuePair<int, string>>();
|
|
notNullableParameters = new Dictionary<int, Type>();
|
|
hasReturnValue = false;
|
|
nullableReturnValue = true;
|
|
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
|
|
OperationInfoBase serviceOperationInfo = activity.ServiceOperationInfo;
|
|
if (serviceOperationInfo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ServiceOperationInfoNotSpecified, activity.Name)));
|
|
}
|
|
|
|
MethodInfo methodInfo = serviceOperationInfo.GetMethodInfo(serviceProvider);
|
|
if (methodInfo == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_MethodInfoNotAvailable, activity.Name)));
|
|
}
|
|
|
|
if (methodInfo.ReturnType != null && methodInfo.ReturnType != typeof(void))
|
|
{
|
|
hasReturnValue = true;
|
|
this.returnTypeName = methodInfo.ReturnType.FullName;
|
|
nullableReturnValue =
|
|
!((methodInfo.ReturnType.IsPrimitive || methodInfo.ReturnType.IsEnum || methodInfo.ReturnType.IsValueType) && !ServiceOperationHelpers.IsNullableType(methodInfo.ReturnType));
|
|
}
|
|
|
|
foreach (ParameterInfo parameter in methodInfo.GetParameters())
|
|
{
|
|
if (parameter.ParameterType.IsByRef ||
|
|
parameter.IsOut || (parameter.IsIn && parameter.IsOut))
|
|
{
|
|
outputParameters.Add(new KeyValuePair<int, string>(parameter.Position, parameter.Name));
|
|
|
|
if (parameter.ParameterType.IsByRef &&
|
|
parameter.ParameterType.GetElementType().IsValueType &&
|
|
!ServiceOperationHelpers.IsNullableType(parameter.ParameterType))
|
|
{
|
|
notNullableParameters.Add(parameter.Position, parameter.ParameterType);
|
|
}
|
|
}
|
|
|
|
if (!parameter.IsOut || (parameter.IsIn && parameter.IsOut))
|
|
{
|
|
inputParameters.Add(new KeyValuePair<int, string>(parameter.Position, parameter.Name));
|
|
}
|
|
}
|
|
|
|
this.operationName = serviceOperationInfo.Name;
|
|
|
|
this.baseQueueName = QueueNameHelper.Create(methodInfo.DeclaringType, this.operationName);
|
|
|
|
object[] operationContractAttribs = methodInfo.GetCustomAttributes(typeof(OperationContractAttribute), true);
|
|
|
|
if (operationContractAttribs != null && operationContractAttribs.Length > 0)
|
|
{
|
|
if (operationContractAttribs[0] is OperationContractAttribute)
|
|
{
|
|
this.isOneWay = ((OperationContractAttribute)operationContractAttribs[0]).IsOneWay;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public bool IsOneWay
|
|
{
|
|
get
|
|
{
|
|
return this.isOneWay;
|
|
}
|
|
}
|
|
|
|
public object GetOutputs(ReceiveActivity activity, out object[] outputs)
|
|
{
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
|
|
outputs = new object[outputParameters.Count];
|
|
object returnValue = null;
|
|
|
|
WorkflowParameterBindingCollection bindings = activity.ParameterBindings;
|
|
|
|
for (int index = 0; index < outputParameters.Count; ++index)
|
|
{
|
|
KeyValuePair<int, string> parameterInfo = outputParameters[index];
|
|
if (bindings[parameterInfo.Value].Value == null &&
|
|
this.notNullableParameters.Keys.Contains(parameterInfo.Key))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ReceiveActivityInvalidParameterValue,
|
|
activity.Name, parameterInfo.Value, this.notNullableParameters[parameterInfo.Key])));
|
|
}
|
|
|
|
outputs[index] = bindings[parameterInfo.Value].Value;
|
|
}
|
|
|
|
if (hasReturnValue)
|
|
{
|
|
if (bindings["(ReturnValue)"].Value == null &&
|
|
!this.nullableReturnValue)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ReceiveActivityInvalidReturnValue,
|
|
activity.Name, this.returnTypeName)));
|
|
}
|
|
|
|
returnValue = bindings["(ReturnValue)"].Value;
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
public string GetWorkflowQueueName(IDictionary<string, string> context)
|
|
{
|
|
return QueueNameHelper.Create(this.baseQueueName, context);
|
|
}
|
|
|
|
public void PopulateInputs(ReceiveActivity activity, ReadOnlyCollection<object> inputs)
|
|
{
|
|
if (activity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activity");
|
|
}
|
|
|
|
if (inputs == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("inputs");
|
|
}
|
|
|
|
WorkflowParameterBindingCollection bindings = activity.ParameterBindings;
|
|
|
|
for (int index = 0; index < inputParameters.Count; index++)
|
|
{
|
|
KeyValuePair<int, string> parameterInfo = inputParameters[index];
|
|
|
|
if (!bindings.Contains(parameterInfo.Value))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_ParameterBindingMissing,
|
|
parameterInfo.Value,
|
|
this.operationName,
|
|
activity.Name)));
|
|
}
|
|
if (index >= inputs.Count)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_InputValueUnavailable,
|
|
parameterInfo.Value,
|
|
this.operationName,
|
|
activity.Name)));
|
|
}
|
|
|
|
WorkflowParameterBinding parameterBinding = bindings[parameterInfo.Value];
|
|
parameterBinding.Value = inputs[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
class SecurityShim : IActivityEventListener<QueueEventArgs>, IDisposable
|
|
{
|
|
ReceiveActivity receiveActivity;
|
|
|
|
internal SecurityShim(ReceiveActivity receiveActivity)
|
|
{
|
|
if (receiveActivity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
|
|
}
|
|
|
|
this.receiveActivity = receiveActivity;
|
|
}
|
|
|
|
void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs queueEventArgs)
|
|
{
|
|
if (sender == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
|
|
}
|
|
|
|
if (queueEventArgs == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("queueEventArgs");
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = sender as WorkflowQueue;
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid, "sender", typeof(WorkflowQueue))));
|
|
}
|
|
|
|
WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
|
|
if (requestContext != null)
|
|
{
|
|
IDependencyObjectAccessor doa = (IDependencyObjectAccessor)receiveActivity;
|
|
EventHandler<OperationValidationEventArgs>[] eventHandlers =
|
|
doa.GetInvocationList<EventHandler<OperationValidationEventArgs>>(
|
|
ReceiveActivity.OperationValidationEvent);
|
|
|
|
if (eventHandlers != null && eventHandlers.Length > 0)
|
|
{
|
|
requestContext.PopulateAuthorizationState();
|
|
}
|
|
}
|
|
}
|
|
|
|
void IDisposable.Dispose()
|
|
{
|
|
this.receiveActivity.Dispose();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
class ValidationShim : IActivityEventListener<QueueEventArgs>, IDisposable
|
|
{
|
|
IActivityEventListener<QueueEventArgs> activityEventListener;
|
|
ReceiveActivity receiveActivity;
|
|
|
|
internal ValidationShim(ReceiveActivity receiveActivity, IActivityEventListener<QueueEventArgs> activityEventListener)
|
|
{
|
|
if (receiveActivity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
|
|
}
|
|
|
|
if (activityEventListener == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("activityEventListener");
|
|
}
|
|
|
|
this.receiveActivity = receiveActivity;
|
|
this.activityEventListener = activityEventListener;
|
|
}
|
|
|
|
void IActivityEventListener<QueueEventArgs>.OnEvent(object sender, QueueEventArgs queueEventArgs)
|
|
{
|
|
if (sender == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("sender");
|
|
}
|
|
|
|
if (queueEventArgs == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("queueEventArgs");
|
|
}
|
|
|
|
ActivityExecutionContext executionContext = sender as ActivityExecutionContext;
|
|
if (executionContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new ArgumentException(SR2.GetString(SR2.Error_ArgumentTypeInvalid, "sender", typeof(ActivityExecutionContext))));
|
|
}
|
|
|
|
WorkflowQueuingService queuingService = executionContext.GetService<WorkflowQueuingService>();
|
|
if (queuingService == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.General_MissingService, typeof(WorkflowQueuingService))));
|
|
}
|
|
|
|
WorkflowQueue workflowQueue = queuingService.GetWorkflowQueue(queueEventArgs.QueueName);
|
|
if (workflowQueue == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new InvalidOperationException(SR2.GetString(SR2.Error_QueueNotFound, queueEventArgs.QueueName)));
|
|
}
|
|
|
|
WorkflowRequestContext requestContext = workflowQueue.Peek() as WorkflowRequestContext;
|
|
if (requestContext != null)
|
|
{
|
|
if (EvaluateSecurityConstraints(executionContext, this.receiveActivity, requestContext) == true)
|
|
{
|
|
this.activityEventListener.OnEvent(sender, queueEventArgs);
|
|
}
|
|
else
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Verbose, 0,
|
|
"Workflow Instance {0}, receive activity {1} - message validation failed. Message will be discarded.",
|
|
this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName);
|
|
|
|
workflowQueue.Dequeue();
|
|
try
|
|
{
|
|
requestContext.SendFault(new FaultException(SR2.GetString(SR2.SecurityCheckFailed)), null);
|
|
}
|
|
catch (CommunicationException cex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName, cex);
|
|
}
|
|
catch (TimeoutException tex)
|
|
{
|
|
System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Error, 0,
|
|
"Workflow Instance {0}, receive activity {1} - failed to send fault for rejected message. Error: {2}",
|
|
this.receiveActivity.WorkflowInstanceId, this.receiveActivity.QualifiedName, tex);
|
|
}
|
|
|
|
if (requestContext.ContextProperties == null ||
|
|
!(requestContext.ContextProperties.Keys.Contains(WellKnownContextProperties.InstanceId)))
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new FaultException(SR2.GetString(SR2.Error_FailedToValidateActivatingMessage, this.receiveActivity.WorkflowInstanceId)));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.activityEventListener.OnEvent(sender, queueEventArgs);
|
|
}
|
|
}
|
|
|
|
void IDisposable.Dispose()
|
|
{
|
|
this.receiveActivity.Dispose();
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
internal static bool EvaluateSecurityConstraints(IServiceProvider serviceProvider, ReceiveActivity receiveActivity, WorkflowRequestContext requestContext)
|
|
{
|
|
bool retVal = true;
|
|
|
|
if (serviceProvider == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceProvider");
|
|
}
|
|
|
|
if (receiveActivity == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("receiveActivity");
|
|
}
|
|
|
|
if (requestContext == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestContext");
|
|
}
|
|
|
|
IDependencyObjectAccessor doa = (IDependencyObjectAccessor)receiveActivity;
|
|
EventHandler<OperationValidationEventArgs>[] eventHandlers =
|
|
doa.GetInvocationList<EventHandler<OperationValidationEventArgs>>(
|
|
ReceiveActivity.OperationValidationEvent);
|
|
|
|
if (eventHandlers != null && eventHandlers.Length > 0)
|
|
{
|
|
ReadOnlyCollection<ClaimSet> claims = requestContext.AuthorizationContext == null ?
|
|
new ReadOnlyCollection<ClaimSet>(new List<ClaimSet>()) :
|
|
requestContext.AuthorizationContext.ClaimSets;
|
|
OperationValidationEventArgs e = new OperationValidationEventArgs(claims);
|
|
receiveActivity.RaiseGenericEvent(ReceiveActivity.OperationValidationEvent,
|
|
receiveActivity, e);
|
|
retVal = e.IsValid;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
}
|
|
}
|
|
}
|