Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / Description / CorrelationQueryBehavior.cs / 1480445 / CorrelationQueryBehavior.cs
//---------------------------------------------------------------- // 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{ 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 queries; ReadOnlyCollection sendNames; ReadOnlyCollection receiveNames; bool shouldPreserveMessage; public CorrelationQueryBehavior(ICollection 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 CorrelationQueries { get { return this.queries; } } [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "We will use this")] public ICollection ReceiveNames { get { return this.receiveNames; } } public ICollection 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 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 (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 (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 (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 receiveNames = new List (); List sendNames = new List (); 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 (receiveNames); this.sendNames = new ReadOnlyCollection (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 .Attach(IContextChannel owner) { } void IExtension .Detach(IContextChannel owner) { } public CorrelationKeyCalculator GetKeyCalculator() { if (this.correlationKeyCalculator == null) { CorrelationKeyCalculator localKeyCalculator = new CorrelationKeyCalculator(this.ScopeName); foreach (CorrelationQuery query in this.queries) { IDictionary > dictionary = new Dictionary >(); // 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 (), dictionary, query.IsDefaultContextQuery); } this.correlationKeyCalculator = localKeyCalculator; } return this.correlationKeyCalculator; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MetadataItemCollectionFactory.cs
- ExpressionBuilder.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- SmiSettersStream.cs
- DataColumnMappingCollection.cs
- SpeechUI.cs
- SafeProcessHandle.cs
- DataList.cs
- Win32SafeHandles.cs
- TimerExtension.cs
- DrawingCollection.cs
- SequentialWorkflowRootDesigner.cs
- FormsAuthenticationUserCollection.cs
- recordstate.cs
- Soap11ServerProtocol.cs
- SQLByte.cs
- TextElementEnumerator.cs
- ShaperBuffers.cs
- HtmlControl.cs
- BlobPersonalizationState.cs
- HtmlShim.cs
- SqlDataSourceStatusEventArgs.cs
- UIElementParaClient.cs
- HttpWriter.cs
- AdjustableArrowCap.cs
- DataGridViewCellCancelEventArgs.cs
- JsonReader.cs
- UpDownEvent.cs
- RadioButton.cs
- WorkflowInstance.cs
- ReflectionPermission.cs
- DbConnectionPoolGroup.cs
- ForAllOperator.cs
- TogglePattern.cs
- RadialGradientBrush.cs
- SignedXml.cs
- ExpressionBuilderCollection.cs
- UrlMappingsModule.cs
- CorrelationResolver.cs
- XsltInput.cs
- Attribute.cs
- Substitution.cs
- ListViewPagedDataSource.cs
- RegexRunner.cs
- ExpressionsCollectionEditor.cs
- MdbDataFileEditor.cs
- CompositeKey.cs
- BitmapEffectDrawing.cs
- BasicHttpBindingElement.cs
- MultilineStringConverter.cs
- AutomationElementCollection.cs
- DCSafeHandle.cs
- COM2IVsPerPropertyBrowsingHandler.cs
- Configuration.cs
- PagePropertiesChangingEventArgs.cs
- OrderingInfo.cs
- PackageRelationshipSelector.cs
- InputQueue.cs
- ElementHostAutomationPeer.cs
- TranslateTransform3D.cs
- PenContexts.cs
- TcpClientSocketManager.cs
- UserPersonalizationStateInfo.cs
- BuildManagerHost.cs
- WmpBitmapDecoder.cs
- SimplePropertyEntry.cs
- MachineKey.cs
- TextServicesLoader.cs
- DataGridViewCellStateChangedEventArgs.cs
- WorkflowMarkupSerializationProvider.cs
- SmiXetterAccessMap.cs
- TextParagraphView.cs
- SmtpReplyReaderFactory.cs
- XmlUrlResolver.cs
- Mutex.cs
- DependencyPropertyDescriptor.cs
- StylusLogic.cs
- TraceFilter.cs
- SetIterators.cs
- BuilderInfo.cs
- DebuggerService.cs
- CodePageUtils.cs
- IPGlobalProperties.cs
- IPipelineRuntime.cs
- OdbcConnectionFactory.cs
- DefaultProxySection.cs
- TextDataBindingHandler.cs
- BidOverLoads.cs
- TreeNodeSelectionProcessor.cs
- WebBrowserUriTypeConverter.cs
- VectorAnimationUsingKeyFrames.cs
- XmlSchemaSimpleContentRestriction.cs
- PipeStream.cs
- SupportsEventValidationAttribute.cs
- FixedDocumentPaginator.cs
- XmlWriter.cs
- Ops.cs
- Processor.cs
- VariableQuery.cs
- DataGridViewAccessibleObject.cs