With the introduction of multi-channel, we are able to inject the functionality easily into the application through channel configuration. That means the broker controls the execution of the operations through the Microsoft Multi-Channel Commerce Foundation operation sequence. In some instances, we need to know what data exists in request and response object and there is no such mechanism OOB with commerce server 2009 to see the object’s data (like health monitoring system in BizTalk). To address this problem, I come up with small component which will log the object (context, request and response) information into text file.
Note: This is costly operation (creating text file per request) and request not to use it in production system.
Here are the steps we should follow to create logging component.
- Create a class project – CS2009ObjectLogger and sign the assembly with a key.
- Add a new class name CS2009RequestLogger.cs
- Copy below code in CS file.
// This code is created by Ravi Kanth Koppala and the developer
// can use this code as it is or tweak the code to address
// the requirement. The author will not support the code.
// Copyright 2010 – CommerceServerGuru.comusing System;
using System.Collections.Generic;
using Microsoft.Commerce.Contracts.Messages;
using Microsoft.Commerce.Broker;
using Microsoft.Commerce.Providers.Components;
using System.Xml.Serialization;namespace CommerceServerGuru.Tools.Loggers
{
public class CS2009RequestLogger : OperationSequenceComponent
{const string CRLF = "\r\n";
static Dictionary<string, CommerceQueryOperationResponse> previousResponses = new Dictionary<string, CommerceQueryOperationResponse>();
/// <summary>
/// Handles the Query operation for Marketing Templates
/// </summary>
/// <param name="queryOperation">Operation to process</param>
/// <param name="operationCache">Request-level cache</param>
/// <param name="response">Response for the operation</param>
public override void ExecuteQuery(
CommerceQueryOperation queryOperation,
OperationCacheDictionary operationCache,
CommerceQueryOperationResponse response)
{CommerceRequestContext commerceRequestContext
= OperationContext.CurrentInstance.RequestContext;var encoding = new System.Text.ASCIIEncoding();
var myStream = new System.IO.FileStream(@"C:\inetpub\wwwroot\wss\VirtualDirectories\1234\bin\Requests_" + commerceRequestContext.RequestId + ".xml", System.IO.FileMode.Append);var extraTypes = new Type[3];
extraTypes[0] = typeof(Microsoft.Commerce.Contracts.CommerceRelationshipList);
extraTypes[1] = typeof(CommerceQueryRelatedItem);
extraTypes[2] = typeof(CommerceModelSearch);String rawXml =
@"<CommerceRequest><Channel>{0}</Channel><RequestId>{1}</RequestId><UserId>{2}</UserId><UserLocale>{3}</UserLocale><UserUILocale>4</UserUILocale><CommerceRequest>";
string processXML = string.Format(rawXml,
commerceRequestContext.Channel,
commerceRequestContext.RequestId,
commerceRequestContext.UserId,
commerceRequestContext.UserLocale,
commerceRequestContext.UserUILocale
);
// Note: You may get following error when you try to serialize CommerceRequestContext.
// System.InvalidOperationException: The type Microsoft.Commerce.Portal.Common.Contracts.Messages.CommerceRequestContext was not expected.
// Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
try
{
if (!previousResponses.ContainsKey(commerceRequestContext.RequestId))
{
byte[] exBytes = encoding.GetBytes(processXML);
myStream.Write(exBytes,0, exBytes.Length);
}
}
catch (Exception ex)
{
WriteStringToStream(ex.ToString(), myStream);
}myStream.Write(encoding.GetBytes(CRLF), 0, encoding.GetBytes(CRLF).Length);
var mySerializer = new XmlSerializer(typeof(CommerceQueryOperation), extraTypes);
try
{
if (!previousResponses.ContainsKey(commerceRequestContext.RequestId))
{
mySerializer.Serialize(myStream, queryOperation);
}
}
catch (Exception ex)
{
WriteStringToStream(ex.ToString(), myStream);
}myStream.Write(encoding.GetBytes(CRLF), 0, encoding.GetBytes(CRLF).Length);
var mySerializerResponse = new XmlSerializer(typeof(CommerceQueryOperationResponse), extraTypes);
try
{
mySerializerResponse.Serialize(myStream, response);
}
catch (Exception ex)
{
WriteStringToStream(ex.ToString(), myStream);
}if (previousResponses.ContainsKey(commerceRequestContext.RequestId))
{
WriteStringToStream("Found Previous Request:" + CRLF, myStream);
mySerializerResponse.Serialize(myStream, previousResponses[commerceRequestContext.RequestId]);
}
else
{
previousResponses.Add(commerceRequestContext.RequestId, response);
}myStream.Write(encoding.GetBytes(CRLF), 0, encoding.GetBytes(CRLF).Length);
myStream.Close();
myStream.Dispose();}
/// <summary>
/// Logs error into the log file.
/// </summary>
/// <param name="myString">Error message to write to log</param>
/// <param name="myStream">File stream</param>
private void WriteStringToStream(string myString, System.IO.FileStream myStream)
{
if (myStream == null) throw new ArgumentNullException("myStream");
var encoding = new System.Text.ASCIIEncoding();
byte[] exBytes = encoding.GetBytes(myString);myStream.Write(exBytes, 0, exBytes.Length);
}}
}
- Note: the file location is hardcoded and if possible you can write the file in common location (c:\windows\temp).
- Build the solution and deploy the tool in GAC.
- The next step is to modify site’s ChannelConfiguration.config file and add the below code wherever you need logging functionality.
| <Component name="CommerceSererGuru Tools – Logging" type="Your Full Class Type, Your Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=Your Public Key"/> |
That’s all, now you have completed your operation sequence. If you execute the application, you can able to see xml files (with data) created in the folder. Click below link to download the code.
If you like this post, please click on our sponsor advertisement.
