Adrift in .Net
For this post I am assuming you are familiar with Commerce Server 2009 and operation sequences, which in my opinion are the main reason to use the upgraded Commerce Server product. You can find some background on operation sequences on MSDN.
The problem we are trying to solve here is the addition of new properties to the Commerce Server Profile system, but we want a one-to-many relationship between the user profile and the new property. As an example, we will be adding a number of Tests to the user’s profile. In this case the user needs to participate in a number of tests that we can track, because these tests determine what products a user will be able to purchase. The more tests and test categories the user participates in, the more products they are eligible for.
The basic steps for this are:
See How to Use the Profiles Schema Manager on MSDN for documentation on the Profiles editor in Commerce Server Manager.
<CommerceEntity name="Test">
<DisplayName value="Test"/>
<EntityMappings>
<EntityMapping
csType="Microsoft.CommerceServer.Runtime.Profiles.Profile"
csAssembly="Microsoft.CommerceServer.Runtime, Version=6.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
csDefinitionName="Test"
csArea="Profiles">
<PropertyMappings>
<PropertyMapping property="TestId" csProperty="GeneralInfo.TestId" />
<PropertyMapping property="TestName" csProperty="GeneralInfo.TestName" />
<PropertyMapping property="TestCategory" csProperty="GeneralInfo.TestCategory" />
</PropertyMappings>
</EntityMapping>
</EntityMappings>
<Properties>
<Property name="TestId" dataType="String" />
<Property name="TestName" dataType="String" />
<Property name="TestCategory" dataType="String" />
</Properties>
<Relationships/>
</CommerceEntity>
<Relationships>
<Relationship name="Tests" type="Relationship" modelName="Test" isMultipleItems="true">
<DisplayName value="Tests" />
<Description value="User's Tests" />
</Relationship>
</Relationships>
namespace CommerceDemo
{
[Serializable]
public class Test
public string TestId { get; set; }
public string TestName { get; set; }
public string TestCategory { get; set; }
}
public class UserProfileTestProcessor : RelatedProfileProcessorBase
// Methods
protected override bool CanDeleteRelatedItem(string relatedItemId)
return true;
// Properties
protected override string CommercePreferredIdKeyName
get
return "GeneralInfo.Test";
protected override string CommerceRelatedIdsKeyName
protected override string ParentProfileModelName
return "UserProfile";
protected override string PreferredItemRelationshipName
return "TestId";
protected override string ProfileModelName
return "Test";
protected override string RelationshipName
return "Tests";
class UserProfileTestCommitter: ProfileCommitterBase
get { return "Test"; }
class TestResponseBuilder : ProfileResponseBuilderBase
<MessageHandler name="CommerceQueryOperation_UserProfile" responseType="Microsoft.Commerce.Contracts.Messages.CommerceQueryOperationResponse, Microsoft.Commerce.Contracts, Version=1.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35">
<OperationSequence>
<Component name="User Profile Loader" type="Microsoft.Commerce.Providers.Components.UserProfileLoader, Microsoft.Commerce.Providers, Version=1.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35"/>
<Component name="User Profile Test Processor" type="CommerceDemo.UserProfileTestProcessor, CommerceDemo, Version=1.0.0.0, Culture=neutral,PublicKeyToken=fbeb08efdb2d0b73"/>
<Component name="User Profile Response Builder" type="Microsoft.Commerce.Providers.Components.UserProfileResponseBuilder, Microsoft.Commerce.Providers, Version=1.0.0.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" />
<Component name="User Profile Test Response Builder" type="CommerceDemo.UserProfileTestResponseBuilder, CommerceDemo, Version=1.0.0.0, Culture=neutral,PublicKeyToken=fbeb08efdb2d0b73" />
</OperationSequence>
</MessageHandler>
public static Test ConvertTest(CommerceEntity testEntity)
Test result = new Test();
result.Id = testEntity.Id;
result.TestName = testEntity.Properties[“TestName”].ToString();
result.TestCategory = testEntity.Properties[“TestCategory”].ToString();
return result;
So how does this look when wired up? That’s a complex question to be sure, but here is a simplified example, assuming we have a User object class with simple common properties:
public User GetUser(string userId)
User user = null;
OperationServiceAgent svc= new OperationServiceAgent();
CommerceQuery<CommerceEntity> query = new CommerceQuery<CommerceEntity>("UserProfile");
query.SearchCriteria.Model.Properties["Email"] = userId;
CommercePropertyCollection properties = new CommercePropertyCollection();
properties.Add("Email");
properties.Add("FirstName");
properties.Add("LastName");
query.Model.Properties = properties;
CommerceQueryRelatedItem<CommerceEntity> test= new CommerceQueryRelatedItem<CommerceEntity>("Tests", "Test");
test.Model.Properties.Add("TestId");
test.Model.Properties.Add("TestNumber");
test.Model.Properties.Add("TestCategory");
query.RelatedOperations.Add(test);
CommerceResponse response = svc.ProcessRequest(GetRequestContext(), query.ToRequest());
CommerceQueryOperationResponse queryResponse = response.OperationResponses[0] as ommerceQueryOperationResponse;
if (queryResponse !=null && queryResponse.CommerceEntities.Count > 0)
Convert(queryResponse.CommerceEntities[0]);
return user;
public static User Convert(CommerceEntity userEntity)
User result = new User();
result.Id = userEntity.Properties["Id"] as string;
result.Email = userEntity.Properties["Email"] as string;
result.LastName = userEntity.Properties["FirstName"] as string;
result.FirstName = userEntity.Properties["LastName"] as string;
CommerceRelationshipList relationships = userEntity.Properties["Tests"] as CommerceRelationshipList;
result.Tests = ConvertTest(relationships); //Function above in post
return output;
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.