/// <summary> /// Executes the custom runtime task component to process the input message and returns the result message. /// </summary> /// <param name="pContext">A reference to <see cref="Microsoft.BizTalk.Component.Interop.IPipelineContext"/> object that contains the current pipeline context.</param> /// <param name="pInMsg">A reference to <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object that contains the message to process.</param> /// <returns>A reference to the returned <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object which will contain the output message.</returns> public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg) { Guard.ArgumentNotNull(pContext, "pContext"); Guard.ArgumentNotNull(pInMsg, "pInMsg"); var callToken = TraceManager.PipelineComponent.TraceIn(); // It is OK to load the entire message into XML DOM. The size of these requests is anticipated to be very small. XDocument request = XDocument.Load(pInMsg.BodyPart.GetOriginalDataStream()); string transformName = (from childNode in request.Root.Descendants() where childNode.Name.LocalName == WellKnownContractMember.MessageParameters.TransformName select childNode.Value).FirstOrDefault <string>(); TraceManager.PipelineComponent.TraceInfo(TraceLogMessages.GetXslTransformRequest, transformName); IBaseMessagePart responsePart = BizTalkUtility.CreateResponsePart(pContext.GetMessageFactory(), pInMsg); XmlWriterSettings settings = new XmlWriterSettings(); MemoryStream dataStream = new MemoryStream(); pContext.ResourceTracker.AddResource(dataStream); settings.CloseOutput = false; settings.CheckCharacters = false; settings.ConformanceLevel = ConformanceLevel.Fragment; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (XmlWriter responseWriter = XmlWriter.Create(dataStream, settings)) { responseWriter.WriteResponseStartElement("r", WellKnownContractMember.MethodNames.GetXslTransformMetadata, WellKnownNamespace.ServiceContracts.General); try { Type transformType = ResolveTransformType(transformName); if (transformType != null) { // Get the actual map from the BizTalk metadata cache. BtsTransformMetadata btsTransform = BtsTransformMetadata.For(transformType); if (btsTransform != null) { // Map existence confirmed, now it's safe to instantiate the transform type. TransformBase transform = Activator.CreateInstance(transformType) as TransformBase; // Is this really a valid map that implements TransformBase? if (transform != null) { XslTransformMetadata transformMetadata = new XslTransformMetadata(transform.XmlContent, transform.XsltArgumentListContent, transform.SourceSchemas, transform.TargetSchemas); DataContractSerializer dcSerializer = new DataContractSerializer(typeof(XslTransformMetadata), String.Concat(WellKnownContractMember.MethodNames.GetXslTransformMetadata, WellKnownContractMember.ResultMethodSuffix), WellKnownNamespace.ServiceContracts.General); dcSerializer.WriteObject(responseWriter, transformMetadata); } } } } catch (Exception ex) { // Log but do not pass the exception to the caller. TraceManager.PipelineComponent.TraceError(ex); } responseWriter.WriteEndElement(); responseWriter.Flush(); } dataStream.Seek(0, SeekOrigin.Begin); responsePart.Data = dataStream; TraceManager.PipelineComponent.TraceOut(callToken); return(pInMsg); }
/// <summary> /// Executes the custom runtime task component to process the input message and returns the result message. /// </summary> /// <param name="pContext">A reference to <see cref="Microsoft.BizTalk.Component.Interop.IPipelineContext"/> object that contains the current pipeline context.</param> /// <param name="pInMsg">A reference to <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object that contains the message to process.</param> /// <returns>A reference to the returned <see cref="Microsoft.BizTalk.Message.Interop.IBaseMessage"/> object which will contain the output message.</returns> public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg) { Guard.ArgumentNotNull(pContext, "pContext"); Guard.ArgumentNotNull(pInMsg, "pInMsg"); var callToken = TraceManager.PipelineComponent.TraceIn(); // It is OK to load the entire message into XML DOM. The size of these requests is anticipated to be very small. XDocument request = XDocument.Load(pInMsg.BodyPart.GetOriginalDataStream()); string sectionName = (from childNode in request.Root.Descendants() where childNode.Name.LocalName == WellKnownContractMember.MessageParameters.SectionName select childNode.Value).FirstOrDefault <string>(); string applicationName = (from childNode in request.Root.Descendants() where childNode.Name.LocalName == WellKnownContractMember.MessageParameters.ApplicationName select childNode.Value).FirstOrDefault <string>(); string machineName = (from childNode in request.Root.Descendants() where childNode.Name.LocalName == WellKnownContractMember.MessageParameters.MachineName select childNode.Value).FirstOrDefault <string>(); TraceManager.PipelineComponent.TraceInfo(TraceLogMessages.GetConfigSectionRequest, sectionName, applicationName, machineName); IConfigurationSource configSource = ApplicationConfiguration.Current.Source; IApplicationConfigurationSource appConfigSource = configSource as IApplicationConfigurationSource; ConfigurationSection configSection = appConfigSource != null?appConfigSource.GetSection(sectionName, applicationName, machineName) : configSource.GetSection(sectionName); if (configSection != null) { IBaseMessagePart responsePart = BizTalkUtility.CreateResponsePart(pContext.GetMessageFactory(), pInMsg); XmlWriterSettings settings = new XmlWriterSettings(); MemoryStream dataStream = new MemoryStream(); pContext.ResourceTracker.AddResource(dataStream); settings.CloseOutput = false; settings.CheckCharacters = false; settings.ConformanceLevel = ConformanceLevel.Fragment; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (XmlWriter configDataWriter = XmlWriter.Create(dataStream, settings)) { configDataWriter.WriteResponseStartElement("r", WellKnownContractMember.MethodNames.GetConfigurationSection, WellKnownNamespace.ServiceContracts.General); configDataWriter.WriteResultStartElement("r", WellKnownContractMember.MethodNames.GetConfigurationSection, WellKnownNamespace.ServiceContracts.General); SerializableConfigurationSection serializableSection = configSection as SerializableConfigurationSection; if (serializableSection != null) { serializableSection.WriteXml(configDataWriter); } else { MethodInfo info = configSection.GetType().GetMethod(WellKnownContractMember.MethodNames.SerializeSection, BindingFlags.NonPublic | BindingFlags.Instance); string serialized = (string)info.Invoke(configSection, new object[] { configSection, sectionName, ConfigurationSaveMode.Full }); configDataWriter.WriteRaw(serialized); } configDataWriter.WriteEndElement(); configDataWriter.WriteEndElement(); configDataWriter.Flush(); } dataStream.Seek(0, SeekOrigin.Begin); responsePart.Data = dataStream; } else { throw new ApplicationException(String.Format(CultureInfo.InvariantCulture, ExceptionMessages.ConfigurationSectionNotFound, sectionName, ApplicationConfiguration.Current.Source.GetType().FullName)); } TraceManager.PipelineComponent.TraceOut(callToken); return(pInMsg); }
/// <summary> /// Synchronously executes the task using the specified <see cref="RuntimeTaskExecutionContext"/> execution context object. /// </summary> /// <param name="context">The execution context.</param> public override void Run(RuntimeTaskExecutionContext context) { Guard.ArgumentNotNull(context, "context"); Guard.ArgumentNotNull(context.Message, "context.Message"); var callToken = TraceManager.PipelineComponent.TraceIn(); Stream messageDataStream = null; IEnumerable <object> facts = null; string policyName = PolicyName, ctxPropName = null, ctxPropNamespace = null; Version policyVersion = PolicyVersion; RulesEngineRequest request = null; bool responseRequired = true; try { XmlReaderSettings readerSettings = new XmlReaderSettings() { CloseInput = false, CheckCharacters = false, IgnoreComments = true, IgnoreProcessingInstructions = true, IgnoreWhitespace = true, ValidationType = ValidationType.None }; if (context.Message.BodyPart != null) { messageDataStream = BizTalkUtility.EnsureSeekableStream(context.Message, context.PipelineContext); if (messageDataStream != null) { using (XmlReader messageDataReader = XmlReader.Create(messageDataStream, readerSettings)) { // Navigate through the XML reader until we find an element with the expected name and namespace. while (!messageDataReader.EOF && messageDataReader.Name != WellKnownContractMember.MessageParameters.Request && messageDataReader.NamespaceURI != WellKnownNamespace.DataContracts.General) { messageDataReader.Read(); } // Element was found, let's perform de-serialization from XML into a RulesEngineRequest object. if (!messageDataReader.EOF) { DataContractSerializer serializer = new DataContractSerializer(typeof(RulesEngineRequest)); request = serializer.ReadObject(messageDataReader, false) as RulesEngineRequest; if (request != null) { policyName = request.PolicyName; policyVersion = request.PolicyVersion; facts = request.Facts; } } } } } // Check if the policy name was supplied when this component was instantiated or retrieved from a request message. if (!String.IsNullOrEmpty(policyName)) { // If policy version is not specified, use the latest deployed version. PolicyExecutionInfo policyExecInfo = policyVersion != null ? new PolicyExecutionInfo(policyName, policyVersion) : new PolicyExecutionInfo(policyName); // Use all context properties as parameters when invoking a policy. for (int i = 0; i < context.Message.Context.CountProperties; i++) { ctxPropName = null; ctxPropNamespace = null; object ctxPropValue = context.Message.Context.ReadAt(i, out ctxPropName, out ctxPropNamespace); policyExecInfo.AddParameter(String.Format("{0}#{1}", ctxPropNamespace, ctxPropName), ctxPropValue); } // If we still haven't determined what facts should be passed to the policy, let's use the request message as a single fact. if (null == facts) { if (messageDataStream != null) { // Unwind the data stream back to the beginning. messageDataStream.Seek(0, SeekOrigin.Begin); // Read the entire message into a BRE-compliant type XML document. using (XmlReader messageDataReader = XmlReader.Create(messageDataStream, readerSettings)) { facts = new object[] { new TypedXmlDocument(Resources.DefaultTypedXmlDocumentTypeName, messageDataReader) }; responseRequired = false; } } } // Execute a BRE policy. PolicyExecutionResult policyExecResult = PolicyHelper.Execute(policyExecInfo, facts); // CHeck if we need to return a response. We don't need to reply back if we are not handling ExecutePolicy request message. if (responseRequired) { // Construct a response message. RulesEngineResponse response = new RulesEngineResponse(policyExecResult.PolicyName, policyExecResult.PolicyVersion, policyExecResult.Success); // Add all facts that were being used when invoking the policy. response.AddFacts(facts); // Create a response message. IBaseMessagePart responsePart = BizTalkUtility.CreateResponsePart(context.PipelineContext.GetMessageFactory(), context.Message); XmlWriterSettings settings = new XmlWriterSettings(); // Initialize a new stream that will hold the response message payload. MemoryStream dataStream = new MemoryStream(); context.PipelineContext.ResourceTracker.AddResource(dataStream); settings.CloseOutput = false; settings.CheckCharacters = false; settings.ConformanceLevel = ConformanceLevel.Fragment; settings.NamespaceHandling = NamespaceHandling.OmitDuplicates; using (XmlWriter responseWriter = XmlWriter.Create(dataStream, settings)) { responseWriter.WriteResponseStartElement("r", WellKnownContractMember.MethodNames.ExecutePolicy, WellKnownNamespace.ServiceContracts.General); DataContractSerializer dcSerializer = new DataContractSerializer(typeof(RulesEngineResponse), String.Concat(WellKnownContractMember.MethodNames.ExecutePolicy, WellKnownContractMember.ResultMethodSuffix), WellKnownNamespace.ServiceContracts.General); dcSerializer.WriteObject(responseWriter, response); responseWriter.WriteEndElement(); responseWriter.Flush(); } dataStream.Seek(0, SeekOrigin.Begin); responsePart.Data = dataStream; } else { if (facts != null) { TypedXmlDocument xmlDoc = facts.Where((item) => { return(item.GetType() == typeof(TypedXmlDocument)); }).FirstOrDefault() as TypedXmlDocument; if (xmlDoc != null) { // Initialize a new stream that will hold the response message payload. MemoryStream dataStream = new MemoryStream(); context.PipelineContext.ResourceTracker.AddResource(dataStream); XmlWriterSettings settings = new XmlWriterSettings { CloseOutput = false, CheckCharacters = false, ConformanceLevel = ConformanceLevel.Fragment, NamespaceHandling = NamespaceHandling.OmitDuplicates }; using (XmlWriter dataWriter = XmlWriter.Create(dataStream, settings)) { xmlDoc.Document.WriteContentTo(dataWriter); dataWriter.Flush(); } dataStream.Seek(0, SeekOrigin.Begin); context.Message.BodyPart.Data = dataStream; } } } } else { throw new ApplicationException(String.Format(CultureInfo.InvariantCulture, ExceptionMessages.PolicyNameNotSpecified)); } } finally { if (messageDataStream != null && messageDataStream.CanSeek && messageDataStream.Position > 0) { messageDataStream.Seek(0, SeekOrigin.Begin); } TraceManager.PipelineComponent.TraceOut(callToken); } }