# Tuesday, 18 October 2011

Foundation-logouCommerce comes with a bunch of built-in targets that you can use to set up new campaign items, but you can extend Marketing Foundation with your own targets as well.

To build a new target you have to deal with three concerns:

  • Business logic, this is the target itself
  • User interface, the UI a customer will use to configure your target
  • Data access, creating new instances of your target and loading existing ones

“Buy More Than”-target

In this article you will learn how to extend Marketing Foundation with a “Buy more than”-target, which is what uCommerce calls an Act target. The “Buy more than”-target will be an order line level target, which will be combined with a “Buy product”-target to create a discount triggered.

It can be used stand-alone as well in which case the customer just needs to “Buy more than” of whatever product she decides. Not the most common discount type, but it does show the power of being able to combine targets.

image

Advertise and Act Targets

uCommerce supports two kinds of targets: The advertise target and the act target. Display targets are used in the process of targeting campaign items for specific customers, i.e. these are the ones you set up under the “Advertise” section of a campaign item.

Act targets are evaluated against a cart to determine whether the customer actually “acted” the way we wanted them to and thus trigger an award.

A target might be either an advertise target, an act target, or both, e.g. a product target is actually both an advertise target and an act target as it works for both scenarios.

As mentioned advertise targets are used to determine which campaign items a customer should see using the XSLT extension:

<xsl:variable name="targetedCampaignItems" select="CommerceLibrary:GetTargetedCampaignItems()"/>

Or via .NET

var targetingService = ObjectFactory.Instance.Resolve<ITargetingService>();
IList<CampaignItem> targetedCampaignItems = targetingService.GetTargetedCampaignItems();

Act targets are executed by the basket pipeline using the pipeline task Basket.ApplyAwards.

Our “Buy more than”-target will be an act target targeting individual order lines. Before we get to that though let’s take a look at what’s required to create an advertise target or IDisplayTarget as they’re called internally in uCommerce.

Implementing IDisplayTarget

image

To implement a display target you’ll implement the interface called IDisplayTarget, which has a single method called IsSatisfiedBy. This is the method invoked by uCommerce to determine whether the target is satisfied by the current targeting context.

Basically you’ll evaluated the targeting context and see if it fits with what you want your target to do, e.g. is the customer viewing a particular product, is the customer logged, etc..

Pretty simple.

A Word On The TargetingContext

image

The targeting context is gathered by uCommerce during runtime and tells you all manner of interesting information about what the customer is currently viewing, e.g. what’s the current page, store, catalog, category, list of products being viewed, etc.. You can add your own information to the targeting context if you require additional information. We’ll cover that in another article.

Implementing An Act Target: IPurchaseOrderTarget, IOrderLineTarget

image

Act targets are evaluated against the customer’s cart to verify that the customer actually bought or did what we wanted her to do. You can opt into two interfaces depending on whether you’re targeting the entire order or individual order lines: IPurchaseOrderTarget and IOrderLineTarget.

For our “Buy more than” target we’ll implement the IOrderLineTarget because that’s where we’ll find the quantity of a particular item. Our new “Buy more than”-target would probably be combined with a “Buy this product”-target in most cases, which would require a customer to buy a certain amount of the product.

image

As you can see the logic is pretty simple. We’re receiving an order line from Marketing Foundation and our job is to figure our whether the target is satisfied by this particular order line. In our case the customer just needs to buy more than the configured quantity on the our target.

This leads us to the next question: How do we actually configure a target? Enter the ITargetUi and IConfigurable…

Implementing Configuration UI for the Target

The configuration UI for our new target is responsible for creating a new instance of our particular target and saving it the data store of your choice. Also it serves to reconfigure existing targets of the type that we’re working with; in this instance QuantityTarget.

To add a config UI for our new target we need to create a new user control in .NET. Let’s put it in /umbraco/ucommerce/marketing/targets, which is where the standard target UIs are located. Also remember to put the generated DLL in the /bin folder.

Our user control needs to plugin into the UI framework defined by uCommerce. All that’s required to do so is to inherit ViewEnabledControl<IEditCampaignItemView> and implement IConfigurable.

image

Inheriting ViewEnabledControl<IEditCampaignItemView> gives us access to the context in the UI, i.e. the campaign item currently being configured.

IConfigurable is the interface which lets uCommerce create your target and subsequently reconfigure it when a user wants to edit it.

image

For our target we need a specialized version of IConfigurable called ITargetUi. This is due to the fact that the target might be used as both an advertise target, an act target, or both.

uCommerce will tell you whether it’s one context or the other by assigning the EnabledForDisplay and EnabledForApply values on your UI.

image

So our user control ends up looking like this. Please note that the New() method acts not only as a factory method for our target, but has the responsibility for storing that instance in the data store also. If this doesn’t happen the instance is lost and won’t be displayed as part of the campaign item.

image

Before we can actually use the control we need to register it with uCommerce.

Register Target Configuration UI

To add the target UI to uCommerce we’ll add it to the table called uCommerce_EntityUi. This table holds the mapping between the type, which is to be configured, i.e. our QuantityTarget, and our UI to do the configuration, i.e. our QuantityUi.ascx user control.

image

Because uCommerce is multilingual we’ll want to add a description of the new UI in the table uCommerce_EntityUiDescription otherwise the target UI will show up blank in the drop down lists.

image

When the “Add” button is clicked our new target UI is added to the campaign item and the New() method is called on our user control thus creating a new instance of the target we’re configuring.

image

image

With that in place our new UI is now available when setting up new campaign items and we can create new quantity targets, so we’re ready to move on to dealing with existing targets.

Feeding Marketing Foundation with Targets using TargetAggregator

With the previous steps complete we need to deal with existing targets so Marketing Foundation can find them and evaluate them for customers entering the site: Enter the TargetAggregator.

TargetAggregator is responsible for finding targets for any given campaign item configured in Marketing Foundation.

var targetAggregator = ObjectFactory.Instance.Resolve<ITargetAggregator>();
IList<ITarget> targets = targetAggregator.GetTargets(campaignItem);

TargetAggregator relies on individual TargetResolvers to find targets for a campaign item, e.g. uCommerce has a single target resolver called DefaultTargetResolver, which handles the built-in targets.

We’ll build a custom target resolver by implemeting the ITargetResolver. It will handle our Quantity target and any other future targets.

image

Thus our QuantityTargetResolver ends up looking like this:

image

Register Custom Target Resolver with TargetAggregator

At this point uCommerce doesn’t know about our custom target resolver yet so we’ll have to tell it about it. This is done using the Marketing configuration file found in /ucommerce/configuration/Marketing.config.

We’ll have to register a new component and add it to the target aggregator registration.

First the new component

image

And finally grab the id from the component and add it to the target aggregator registration in the same file.

image

That’s it. Our new target is good to go and will act exactly as the built-in targets, which ship with uCommerce.

In Summary

image

This article showed you how to add custom targeting logic to uCommerce, the user interface to configure it, and how to handle data access for it as well. When you think about it each target is a mini-application hosted inside uCommerce dealing with all the usual concerns of a full-blown  app.

Some of the concerns like the resolver need only be implemented once while others like the UI and the target itself are highly specific to the task they’re trying to accomplish and require a new implementation for each new type you need.

Marketing and particularly discounting are areas, which often come with very specific business rules highly different dependent on the individual business. uCommerce ships with a bunch of useful targets, but having the ability to add your own ensures that you can accommodate any targeting scenario.

posted on Tuesday, 18 October 2011 17:13:10 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback

Foundation-logoMarketing Foundation introduced with uCommerce 2.0 adds rich marketing capabilities, which can be used to stimulate customers to buy. It’s built based on three simple principles: Advertise, Act, and Award.

Advertise

One of the common issues with discounts is that customers are never told about them thus a discount does not work its full effect. Basically the customer is only made aware of the discount once they actually trigger it, which is akin to throwing marketing dollars out the window as the customer was likely to buy anyway.

That’s why we built each campaign item in uCommerce to include the “Advertise” component so marketers actively have to decide whether to advertise or not; at the end of the day why wouldn’t you?

When doing advertisements in uCommerce you will select a number of targets, which are to be satisfied in order for the campaign item to be displayed. You can think of them in terms of, “Customer is viewing this category”, “Customer is viewing this page”, “Customer is in this particular store or catalog”.

If multiple targets are configured in the “Advertise” section the campaign item will be displayed if any of the targets are satisfied.

Once a campaign item is targeted for the current customer its contents can be displayed, which includes rich text, video, HTML, and even the actual targets and awards inside the campaign item. What this boils down to is that you can display banners, which feature video, sound, or HTML content and you can take this a step further by actually telling the customer what she needs to do in order to receive a particular discount.

image

Say you have a campaign item set up called “Free shipping for orders over 400€”. The intent is clear enough, but what if you could actually tell the customer how close she is to get that discount? It just so happens that you can.

Using the information produced by Marketing Foundation you can tell the customer exactly what she must do to trigger the discount.

Say she’s got items in the cart with a total value of 350€. You’d pop up a message telling her that by buying for 50€ more she’d get free shipping; oh and by the way here are some products which 50€ or more making it easy for the customer to take the action we want her to.

Act

image

The act section of a campaign item is the thing we want the customer to do to trigger a discount. When you think about it a discount is actually composed of two things: The thing we want the customer to do; the act part, and the thing the customer gets; the award part.

Think of “Act” as “The customer must buy this particular product”, “The customer must buy for more than x amount”, “The customer must buy something from this particular store, catalog, or category”, etc.

Targets can be combined to form even more powerful campaign items such as a product bundle or kit depending on which side of the pond you’re on.

If multiple targets are set up in the “Act” section of the campaign item they must all be satisfied in order to trigger the discount. Say you want to the customer to buy two products to get a discount. You’ll set up two targets: One for each of the products in involved. uCommerce will look for these products in the cart of they are both found will trigger the discount.

Award

AwardThe final piece of the puzzle is the “Award”, i.e. the thing the customer gets. The award is completely separate from the rest of the campaign item and thus can be reused for many different types of discounts, e.g. “Buy for more than 400€ and get free shipping ” could also be “Enter this promo code and get free shipping”. The only difference is that the “Buy for more than 400€” act section is substituted with “Enter this promo code”. The award remains the same.

Types of awards include “Get amount of unit price”, “Get amount off order total”, “Get amount off order lines total”, “Get percentage off shipping”. Awards can be combined like targets and effectively gives you a discount for each of the awards configured.

It’s important to distinguish between order discounts and order line discounts. The difference being that order level discounts are typically applied only once per order, e.g. “Get amount off order total” will only add a single discount to the order as you’d expect.

Order line discounts on the other hand can involve multiple order lines as in the case of the bundle or kit. Here two or more order lines are involved in the discount thus each of lines will have the order line discount applied, e.g. “Get 10% off unit price” will produce two discounts; one for each order line satisfied by the Act section.

Campaign Items

image

The campaign item ties together our “Advertise”, “Act”, and “Award” sections and is the unit, which can be thought of as a “Discount”.  However, the campaign item does more than just set up a discount, it serves as the content for the advertisement as well.

A campaign item is assigned a “definition” when it’s created. The definition determines the content that the marketer can add to the advertisement. So this is basically where you’d add all the rich content we discussed in the beginning of the article.

image

You can read more about definitions in Catalog Foundation Explained: Product Definitions. The basic concept of the definition is the same for campaign items as for products although obviously a campaign item definition does not deal with variants.

Because the campaign items are configured using definitions you can add your own properties and multilingual properties effectively giving you multilingual marketing campaigns right there. No need to configure the same campaign item twice if you want to target different languages, just add the relevant multilingual properties and you’re done!

Multiple Discounts Per Order, Or No

image

In some cases you don’t want the customer to receive multiple discounts. That’s where the configuration of the campaign item comes in. Of course you can disable individual campaign items that you don’t customer to receive at all by removing the checkmark in the “Enabled” checkbox.

More interestingly you can configure a campaign item to not allow additional discounts if the “Act” section of current campaign item is satisfied. Combine this with the priority of individual campaign items and you can effectively control which discounts the customer is awarded based on your business rules.

You can prioritize campaign items by right-clicking the campaign and choosing “Prioritize campaign items” in the tree menu.

Campaigns

image

Finally we come to the top-most level of Marketing Foundation: The campaigns. A marketing campaign is a collection of campaign items grouped together under a name so each campaign will effectively hold all the planned marketing activities for a given period of time.

A marketing campaign is assigned an interval for which it is active. uCommerce will automatically activate campaign items within in the campaign once the activation period is reached and disabled them again once the activation period is done.

In Summary

uCommerce Marketing Foundation is a highly flexible way to set up marketing messages and discounts in your online store. Combined targets and awards make for interesting possibilities when it comes to different discount types and best of all you can let your customers know exactly what they need to do to get a discount, which is the way it should be.

More importantly Marketing Foundation is built-in from the ground up using our Framework First approach, which means that new targets and awards can easily be added. You can even go so far as to change the inner workings on Marketing Foundation. What this means for your online store is that marketing can be tailored to meet your needs exactly.

posted on Tuesday, 18 October 2011 13:34:57 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Tuesday, 16 August 2011

imageIn a previous article we discussed 4 Steps to Building an Apple-style Product Configurator with uCommerce, which detailed how to piece together a complete product from multiple product options configured in the catalog.

This article will help you deal with those composite items as a unit rather than separate line items.

Step 1: Adding a Composite Product to Basket

When adding the main product and options to the basket we’ll need some way to tell the “master order line” from the “sub order lines”.

We’ll use dynamic order properties to enrich the order lines  for the required information linking each product option line to a master order line containing the main product; our MacBook Air 11 inch.

With that in mind here’s the Razor code in Umbraco to add all the selected options to the basket.

ProductCatalog catalog = ProductCatalog.All().Single(x => x.Name == SiteContext.Current.CatalogContext.CurrentCatalogName);
    
// Check if we're dealing with a post
if (!string.IsNullOrEmpty(Request["masterSku"]))
{
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
        
    // Add the master order line
    var mainProduct = Product.All().Single(x => x.Sku == Request["masterSku"] && x.ParentProductId == null);
    var masterOrderLine = basket.AddProduct(catalog, mainProduct, 1, false);
        
    // Mark the master as such
    masterOrderLine["master"] = true.ToString();
 
    // Save basket to generate ids for the order line
    basket.Save();
        
    // Add each product option to the basket
    foreach (string key in Request.Params.AllKeys.Where(x => x.Substring(0, 3) == "SKU"))
    {
        // Split the value of the posted skus to get both sku and variant sku (where applicable)
        // Example Intel-Core-CPU,i7-1.7
        string[] skus = Request[key].Split(',');
        string sku = skus[0];
        string variantSku = skus.Length == 2 ? skus[1] : null;
            
        // Add the option order line
        var optionProduct = Product.All().Single(x => x.Sku == sku && x.VariantSku == variantSku);
        OrderLine subOrderLine = basket.AddProduct(catalog, optionProduct, 1, false);
 
        // Add a reference back to the master order line
        subOrderLine["masterOrderlineId"] = masterOrderLine.OrderLineId.ToString();
    }
 
    basket.Save();
 
    // Execute the basket pipeline to recalculate basket
    Library.ExecuteBasketPipeline();
}

Now we’ve got all the items added to the basket let’s move on to displaying the items in a nice way on the basket page.

Step 2:  Displaying the Composite Product

Now we’ll need to leverage that extra information we added in the previous step to group the items together.

@using UCommerce.EntitiesV2;
@using UCommerce.Runtime;
@{
    // Load basket
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
}
 
@foreach (var masterOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "master" && y.Value == true.ToString()).Count() > 0))
{
    <form method="post">
    <input type="hidden" name="masterOrderLineId" value="@masterOrderLine.OrderLineId"/>
    <div>
        <h4>@masterOrderLine.ProductName</h4>
        <ul>
            @foreach (var subOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLine.OrderLineId.ToString()).Count() > 0))
            {
                <li>@subOrderLine.ProductName</li>
            }
        </ul>
        <input type="submit" value="Remove" name="remove" />
    </div>
    </form>
}

Here’s what the basket looks like when Umbraco and Razor renders it:

image

Step 3: Remove a Composite Product

Next we’ll want to let the customer remove composite items from the basket by remove the master order line along with any sub order lines it might have.

@using UCommerce.EntitiesV2;
@using UCommerce.Runtime;
@using UCommerce.Xslt;
@{
    // Load basket
    var basket = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
 
    // Check for post
    if (!string.IsNullOrEmpty(Request["masterOrderLineId"]))
    {
        int masterOrderLineId = Convert.ToInt32(Request["masterOrderLineId"]);
 
        // Find all sub order lines for master
        var subOrderlines = basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLineId.ToString()).Count() > 0).ToList();
 
        // Remove sub order lines from basket
        foreach (var subOrderLine in subOrderlines)
        {
            basket.RemoveOrderLine(subOrderLine);
        }
 
        // Now remove the master order line
        OrderLine masterOrderLine = basket.OrderLines.Single(x => x.OrderLineId == masterOrderLineId);
 
        basket.RemoveOrderLine(masterOrderLine);
        basket.Save();
 
        // Recalculate basket
        Library.ExecuteBasketPipeline();
    }
  
}
 
@foreach (var masterOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "master" && y.Value == true.ToString()).Count() > 0))
{
    <form method="post">
    <input type="hidden" name="masterOrderLineId" value="@masterOrderLine.OrderLineId"/>
    <div>
        <h4>@masterOrderLine.ProductName</h4>
        <ul>
            @foreach (var subOrderLine in basket.OrderLines.Where(x => x.OrderProperties.Where(y => y.Key == "masterOrderLineId" && y.Value == masterOrderLine.OrderLineId.ToString()).Count() > 0))
            {
                <li>@subOrderLine.ProductName</li>
            }
        </ul>
        <input type="submit" value="Remove" name="remove" />
    </div>
    </form>
}

Summary

Managing multiple items as one in the basket is handy when working with complex product options like we did for the MacBook Air just now. At all times should customers be certain as to what they’re buying and managing the items should be as straightforward as for “simple items”.

Combining multiple items into one visually is a matter of adding a bit of extra information to tie the items together and doing a clever presentation of the items.

All the internal calculations and stock management stay the same behind the scenes so you just have to worry about doing a nice presentation of the basket.

posted on Tuesday, 16 August 2011 22:55:31 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback

imageVariants is a great way to offer up products which have varying properties, but sometimes they are just not enough or it’s too cumbersome to maintain each and every variant combination you want.

In this article you’ll discover how to build an Apple-style product configurator with uCommerce.

There are two pieces to doing a highly flexible product configurator: The configurator itself and the subsequent presentation of the basket.

We’ll cover the configurator itself in this article and do a separate article for the basket itself.

Step 1: Product Definition for the Main Product

First we’ll need a main product which is the one that we want to configure. For the sake of concreteness let’s build a product configurator for an Apple MacBook Air.

We’ll build a definition to hold main products. Let’s call it “Configurable”. The product definition will hold information to present the main product unique selling proposition like what you see on the main product page on Apple.com.

We won’t be doing any variants for this product definition as the options will come from somewhere else.

Before we move on let’s create the MacBook Air in the product catalog.

image

Step 2: Add Options to the Catalog

For a MacBook Air we’ll need to be able to configure the CPU, the amount of storage, and a couple of add-ons like an external optical drive and display.

We’ll do the options as individual products, which incidentally they typically are anyway with their own inventory.

Let’s add a couple more product definition for the various types of options: CPU, Flash Storage, and Display.

We’ll do variants for the product options as they will become the actual choices the customer has to choose from when configuring the final product.

Here are the product options configured in a separate category for good measure. Note that each option has a number of variants configured.

image

image

I did go ahead and create a definition for each type of add-on, but that’s not a strict requirement. I’m just being a smartass and showing off some other features of uCommerce :)

Step 3: Configure Available Options

Now we’ve got a catalog of products and main products and now for the good stuff: Configuring the available options for each main product. Customers will be able to select CPU, Flash Storage, and optional optical drive or Display for our MacBook Air.

uCommerce supports related products, which is a handy way of building up a list of available options for a given product. So let’s see if we can make that work for our configurator.

First let’s set up a new relationship kind called “Option” to help us find available options later on.

image

And now let’s actually add the options to our MacBook Air.

image

Step 4: Build the Configurator

With the previous steps concluded we’ve got the required information set up in the catalog and now we’re ready to present the options to our rabid following; sorry, loyal customers :)

Enter Razor. Enter the code!

First we’ll load up the product that we wish to configure. Of course it would typically come from a listing, but we’ll just grab it directly to get to the point.

Finally we’ll grab the “Option” relations and present them in a list. Here’s what the Razor code in Umbraco will look like.

@using UCommerce.EntitiesV2;
@using UCommerce.Runtime;
@{
    // Check if we're dealing with a post
    if (!string.IsNullOrEmpty(Request["masterSku"]))
    {
        // Iterate the posted values and add each value to basket
        foreach (string key in Request.Params.AllKeys.Where(x => x.Substring(0, 3) == "SKU"))
        {
            Response.Write(Request[key]);
        }
    }
}
 
@{
    // Grab a price group to work from
    var priceGroup = ProductCatalog.All().Single(x => x.Name == SiteContext.Current.CatalogContext.CurrentCatalogName).PriceGroup;
 
    // Load MacBook Air product
    Product macbookAir = Product.All().Single(x => x.Sku == "MacBook-Air-11-inch");
 
    // Load options relationship kind
    ProductRelationType optionRelation = ProductRelationType.All().Single(x => x.Name == "Option");
 
    // Load the product options, "Option" relation kind only
    var options = macbookAir.GetRelatedProducts()[optionRelation];
}
 
<h1>@macbookAir.Name</h1>
<form>
<input type="hidden" name="masterSku" value="@macbookAir.Sku"/>
@foreach (Product option in options)
{
    <h2>@option.GetDescription("en-us").DisplayName</h2>
    if (option.ProductDefinition.IsProductFamily())
    {
        foreach (Product selectableOption in option.Variants)
        {
            <input type="radio" group="@option.Name" name="SKU,@option.Sku" value="@option.Sku,@selectableOption.VariantSku">@selectableOption.GetDescription("en-us").DisplayName</input>
            if (selectableOption.GetPrice(priceGroup).Price > 0)
            {
                <span>[Add $@selectableOption.GetPrice(priceGroup).Price.Value.ToString("#.00")]</span>
            }
            <br />
        }
    }
    else
    {
        <input type="radio" group="@option.Name" name="SKU,@option.Name" value="@option.Sku">@option.GetDescription("en-us").DisplayName</input>
        
        if (option.GetPrice(priceGroup).Price > 0)
        {
            <span>[Add $@option.GetPrice(priceGroup).Price.Value.ToString("#.00")]</span>
        }
        <br />  
    }
}
<br />
<input type="submit" value="Add to basket" />
</form>

And here’s what the product configurator looks like when the customer sees it in Umbraco. Add some CSS and images to the HTML and you’ve got your product configurator.

image

Summary

Creating and maintaining highly configurable products in uCommerce is a perfect way to offer up nice customization opportunities for customers.

By using the out of the box capabilities like product definitions, relationship kinds, and relationships combined with the API you can build a rich product configurator, which will present product options dynamically based on the options attached to any given product.

Also doing configurable products like this is a great way to manage inventory of individual components instead of complete product configurations. This means that less inventory is required because any given option might be part of multiple different product configurations thus inventory will seem higher with this approach.

In this article you saw how we can use uCommerce to build an Apple-style configurator, but this technique can be further extended to present even more complex decision trees if required.

Imagine building the options themselves with sub-options by doing deeper relationships. This way you can support some very complex scenarios and have complete decision trees for product with very different options, e.g. triple-play service providers of TV, phone, and internet services, which require very different configuration for each option.

posted on Tuesday, 16 August 2011 09:10:18 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Wednesday, 10 August 2011

imageWhen working with an e-commerce transaction system in an online store typically the information stored on the orders and order lines will come from the products themselves in the catalog system.

However, in some cases you might want to add custom information such as a personalized message, an indication whether gift wrapping is required, serial numbers, measurements, or something else entirely.

Enter Dynamic Order Properties

For this specific scenario uCommerce supports dynamic order properties, which is a way to add information to basket, orders, and individual order lines.

You can add as many as you want and you don’t have to stick with the same number of properties or even the same names across orders.

Using Dynamic Order Properties in Razor and .NET

// Grab the basket of the current customer
Basket basket = SiteContext.Current.OrderContext.GetBasket();
PurchaseOrder order = basket.PurchaseOrder;
 
//Add dynamic order property to the order
order["gift_message"] = "Happy birthday!";
order.Save();
// Grab the basket of the current customer
Basket basket = SiteContext.Current.OrderContext.GetBasket();
PurchaseOrder order = basket.PurchaseOrder;
 
//Add dynamic order property to an order line
OrderLine orderLine = order.OrderLines.First();
orderLine["serial_number"] = "ZX456-123";
 
order.Save();
PurchaseOrder purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
 
// Reading the properties back is just as simple
string giftMessage = purchaseOrder["gift_message"];
string serialNumber = purchaseOrder.OrderLines.First()["serial_number"];
 

Using Dynamic Order Properties in XSLT

For convenience you can also work with dynamic order properties in XSLT courtesy the Commerce Library.

For order level properties you go:

<xsl:variable name="result" select="CommerceLibrary:SetOrderProperty('gift_message', 'Happy birthday!')"/>

For individual order lines you’ll refer to the index of the order line to target a specific one. That the first parameter. The index values will be part of the order XML produced by CommerceLibrary:GetBasket().

<xsl:variable name="basket" select="CommerceLibrary:GetBasket()"/>
 
<!-- Grab the index of the first line item -->
<xsl:variable name="firstLineItemIndex" select="$cart/purchaseOrder/lineItems/*[1]/@index"/>
 
<!-- Now set a dynamic order property on the line item with that index -->
<xsl:variable name="result" select="CommerceLibrary:SetOrderProperty(@firstLineItemIndex, 'serial_number', 'ZX456-123')"/>

Once set the dynamic order property will be outputted as part of the XML produced by GetBasket() or GetPurchaseOrder() in the orderProperties element under the order itself or under individual order lines.

<purchaseOrder index="0" orderNumber="WEB-20" orderGuid="62093368-877a-42d8-94c7-332f6f0031f1" status="New order" createdDate="8/10/2011 8:24:14 AM" completedDate="8/10/2011 8:25:10 AM" note="" vat="479.00" orderTotal="2874.00" discount="0.00" discountTotal="100.00" shippingTotal="0.00" paymentTotal="0.00" taxTotal="" subTotal="2395.00" lineItemCount="1" billingCurrency="EUR" productCount="1">
    <customer index="0" id="69" firstName="Søren" lastName="Spelling Lund" emailAddress="soren.spelling.lund@ucommerce.dk" phoneNumber="4540385659" mobilePhoneNumber="4540385659" umbracoMemberId="">
        <addresses />
    </customer>
    <discounts />
    <orderProperties>
        <orderProperty key="gift_message" value="Happy birthday!" />
    </orderProperties>
    <lineItems>
        <lineItem index="0" sku="100-000-001" variantSku="003" productName="uCommerce 1.0 RTM Go-Live" price="2495.00" quantity="1" discount="100.00" unitDiscount="100.00" vat="479.00" vatRate="0.20" total="2874.00">
            <orderProperties>
                <orderProperty key="serial_number" value="ZX456-123" />
            </orderProperties>
            <discounts>
                <discount index="0" campaignName="Default Campaign" campaignItemName="Discounted unit price" description="" amountOff="100.00" />
            </discounts>
        </lineItem>
    </lineItems>
    <shipments>
        <shipment index="0" shipmentId="17" name="Download" createdDate="8/10/2011 8:25:06 AM" shippingMethodId="8" deliveryNote="Download" trackAndTrace="" price="0.00" taxRate="0.20" tax="0.00" shipmentTotal="0.00">
            <address addressId="76" addressName="Shipment" index="0" firstName="Søren" lastName="Spelling Lund" emailAddress="" phoneNumber="" mobilePhoneNumber="" company="uCommerce ApS" line1="Ny Banegårdsgade 55" line2="" postalCode="8000" city="Aarhus C" state="" country="Denmark" attention="" />
        </shipment>
    </shipments>
    <payments>
        <payment id="27" index="0" transactionId="33c6e85e-05f5-41d1-b32e-8b57212883a2" name="Account" dateCreated="8/10/2011 8:25:08 AM" fee="0.00" feeTotal="0.00" feePercentage="0.0000" amount="2874.00" statusId="1" paymentMethodId="6" />
    </payments>
    <addresses />
    <billingAddress>
        <address addressId="75" addressName="Billing" index="0" firstName="Søren" lastName="Spelling Lund" emailAddress="soren.spelling.lund@ucommerce.dk" phoneNumber="+4561799997" mobilePhoneNumber="" company="uCommerce ApS" line1="Ny Banegårdsgade 55" line2="" postalCode="8000" city="Aarhus C" state="" country="Denmark" attention="" />
    </billingAddress>
</purchaseOrder>

Admin

Dynamic order properties will be displayed in uCommerce Admin as part of the order overview.

image

Summary

Dynamic order properties is a great way to add custom information to orders during checkout or indeed later in the order process if required. It can be used to capture customer choice for later use such as custom messages, newsletter sign up flags, and more.

Because they are automatically picked up by the order management interface in the backend they are useful for information store managers need to know during the order management process.

posted on Wednesday, 10 August 2011 08:40:08 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Wednesday, 03 August 2011

imageMore often than not you will leverage uCommerce in a web context either via the Commerce Library XSLT extensions or through .NET directly.

In some cases though you might need to leverage the API outside a web context for automated integration between systems, for custom web services, or integration of uCommerce functionality directly in other custom applications such as point of sale- or kiosk apps.

This article outlines the steps required to get the API going.

Reference uCommerce Assemblies

First you need to reference the uCommerce assemblies and their dependencies in your project.

You’ll need to add references to:

  • UCommerce.dll
  • UCommerce.Infrastructure.dll
  • UCommerce.Umbraco.dll
  • businesslogic.dll (Umbraco)
  • Castle.Core.dll
  • Castle.Windsor.dll
  • FluentNhibernate.dll
  • NHibernate.dll
  • Nhibernate.ByteCode.Castle.dll

Modify App.Config

uCommerce needs some configuration to run. You’ll find examples of the relevant groups in web.config in your Umbraco installation. You’ll want to copy the commerce sectionGroup, connectionStrings, and commerce sections.

Add configSection Element

<configSections>
    <sectionGroup name="commerce" type="System.Configuration.ConfigurationSectionGroup">
        <section name="runtimeConfiguration" type="UCommerce.Infrastructure.Configuration.RuntimeConfigurationSection, UCommerce.Infrastructure" />
    </sectionGroup>
</configSections>

Add connectionStrings Element
<connectionStrings>
    <add name="ucommerce" connectionString="Data Source=(local);Initial Catalog=Umbraco;integrated security=SSPI;" providerName="System.Data.SqlClient"/>
</connectionStrings>

Add commerce Element

<commerce>
    <runtimeConfiguration componentsConfigurationFile="Components.config" enableCache="false" cacheProvider="" />
</commerce>

With all that in place your App.config file should look like this

<configuration>
    <configSections>
        <sectionGroup name="commerce" type="System.Configuration.ConfigurationSectionGroup">
            <section name="runtimeConfiguration" type="UCommerce.Infrastructure.Configuration.RuntimeConfigurationSection, UCommerce.Infrastructure" />
        </sectionGroup>
    </configSections>
    <connectionStrings>
        <add name="ucommerce" connectionString="Data Source=(local);Initial Catalog=Umbraco;integrated security=SSPI;" providerName="System.Data.SqlClient"/>
    </connectionStrings>
    <commerce>
        <runtimeConfiguration componentsConfigurationFile="Components.config" enableCache="false" cacheProvider="" />
    </commerce>
</configuration>

Add Configs to Application Folder

Components.config holds information about all the various subsystems in uCommerce. Copy Components.config and Marketing.config from the website folder you installed Umbraco and uCommerce in, e.g. c:\inetpub\Umbraco\uCommerce\Configuration and copy them to your app folder.

Modify Components.config to Work Outside Web Context

The configuration files assume a web context so we’ll have to update them to work in a non web environment. Open up Components.config in your favorite editor and modify any life cycle with a value of “PerWebRequest” to “Thread”.

This tells uCommerce to create an instance of the object once per thread as opposed to once per request, which oviously doesn’t make sense for what we’re trying to do.

Do the same for Marketing.config if you intend to use that in your application.

Remove Includes in Components.config

Be sure to remove includes in components.config, which refer to Presenters.config and XmlRenderings.config.

Summary

Leveraging uCommerce outside a web site makes for some interesting use cases. Foremost is automated integration with other systems, but you could use this method to establish an offline Point of Sale or Kiosk-type system with a completely different frontend done in Windows Presentation Foundation for a rich in store experience.

posted on Wednesday, 03 August 2011 14:05:37 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Tuesday, 07 June 2011

FoundationWhen we first conceived of uCommerce years ago there was no uCommerce HQ and no real plan for what uCommerce should become. When time came to choose a data access layer we went the RAD route and chose Subsonic for its productivity benefits. Since then Subsonic has been a blessing and a course.

A blessing because it got us off the ground rapidly as intended and it introduced some pretty cool concepts to the uCommerce API such as LINQ based Active Record.

What really hurt was the complete lack of options for tuning queries for optimum performance. Subsonic is great for throwing together custom queries, but is rather lacking in projecting the needed result into an existing model. Basically this means lots of lots of lazy loading, which hurts performance badly due to the many tiny SQL queries being issued to the database.

Thus we decided to switch to a more full featured ORM and the natural choice at the time was NHibernate.

NHibernate has been present in uCommerce since the very early days. In fact it was introduced in uCommerce 1.0.2 to improve performance when querying the catalog via the XSLT API. We’ve slowly migrated bits and pieces of uCommerce to NHibernate where it made sense over the years.

uCommerce 2.0

During the past two years we’ve kept uCommerce backwards compatible with previous versions to make it simple to upgrade to new versions of uCommerce. With version 2.0 we didn’t really have that option anymore as we reached the end of what was possible to achieve internally so we decided to migrate the final uCommerce .NET APIs to EntitiesV2 and NHibernate.

What this means for you and existing code written against UCommerce.Entities, UCommerce.Runtime, and  UCommerce.Pipelines will have to be migrated to UCommerce.EntitiesV2.

The following article describes changes required to make your code run against the new API. Completing the migration will give you several benefits:

  • A clearer API to work with
  • Less code to write
  • Better performance
  • Caching support
  • Single programming model for everything

Ids vs Entities

One of the common patterns you see in Subsonic is the use of id properties to tie object together. This is not possible in NHibernate, which has a more entity focused approach.

NHibernate moves the responsibility of handling the association to the “aggregate root” or in other words to the more logical owner of the child object, e.g. the order handles order line.

Subsonic

var purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder();
var orderLine = new OrderLine();
orderLine.OrderId = purchaseOrder.OrderId;
orderLine.Save();

NHibernate

var purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
var orderLine = new OrderLine();
// Notice that the purchase order is responsible for handling the operation
purchaseOrder.AddOrderLine(orderLine);
purchaseOrder.Save();

Three things are worth nothing here:

  1. We’re not setting any ids. It’s all handled behind the scenes by NHibernate.
  2. The order line is added via the AddOrderLine() method, which is a very common pattern in EntitiesV2.
  3. The purchase order is responsible for saving both the order itself and the order line.

Simple Deletes

More often than not you don’t want to delete an entire aggregate, but just a portion of it. Subsonic and NHibernate deal with this is different ways.

Subsonic

var orderLine = OrderLine.All().Single(x => x.OrderLineId == orderLineId);
orderLine.Delete();

NHibernate

var orderLine = OrderLine.All().Single(x => x.OrderLineId == myOrderLineId);
var purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
// Notice the RemoveOrderLine patterns. Use it whenever you can to delete.
purchaseOrder.RemoveOrderLine(orderLine);
purchaseOrder.Save();

As you can see the order is still responsible for handling the delete of the order line. You simply remove the order line from the order with the RemoveOrderLine() method and it will get deleted automatically when the order is saved. Because the operations are not actually carried out until the Save is issued you get the benefit of bulk operations because they will be batched together once you save.

If you don’t use the method, but go the orderLine.Delete() route instead, you’ll often see the following error message, “deleted object would be re-saved by cascade (remove deleted object from associations)[UCommerce.EntitiesV2.OrderLine#2] ==> RemoveEntity”. This happens because the loaded order has a reference to the object and would re-save it to the database.

Deep Deletes

In Subsonic the pattern for deleting an object is very straightforward: You simply go order.Delete(). The issue with Subsonic is that it has no knowledge of relationships between objects so in many cases simply deleting an order would cause a SQL error because other data would be related to the order like order lines, properties, customer, shipments, addresses, etc.. So you have to know about these related objects and the order in which to delete them. Not very user friendly.

Subsonic

var purchaseOrder = PurchaseOrder.All().Single(x => x.OrderId == myPurchaseOrderId);
OrderAddress.Delete(x => x.OrderId == myPurchaseOrderId);
Shipment.Delete(x => x.OrderId == myPurchaseOrderId);
OrderProperty.Delete(x => x.OrderId == myPurchaseOrderId);
OrderLine.Delete(x => x.OrderId == myPurchaseOrderId);
// etc.
purchaseOrder.Delete();

NHibernate

var purchaseOrder = PurchaseOrder.All().Single(x => x.PurchaseOrderId == myPurchaseOrderId);
purchaseOrder.Delete();
// simple, no? :)

NHibernate is smart enough to know about the relationships between objects, so it’ll go ahead and delete related objects where it makes sense so you don’t have to think about it. These are called cascades and it’s the same mechanism, which ensured that our order line got saved in the previous example.

One to One Relationships

An interesting design decision with Subsonic is that it doesn’t expression one to one relationships, e.g. PurchaseOrder has one Customer. Instead Subsonic will treat all relationships as many to many, e.g. PurchaseOrder has many Customers, which makes sense from an ORM implementation point of view, but is very confusing for a developer trying to use an API built on this approach.

Of course NHibernate lets us map data exactly the way we want, which makes the API so much cleaner and simple to understand.

Subsonic

var purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
// You have to know that there's only a single customer in the database explicitly.
var customer = purchaseOrder.Customers.Single();

NHibernate

var purchaseOrder = SiteContext.Current.OrderContext.GetBasket().PurchaseOrder;
// With NHibernate the customer is mapped properly
var customer = purchaseOrder.Customer;

Many to Many Relationships

While Subsonic defines everything as a one to many relation it’s not so great a handling many to many relations. Typically these are implemented with a relation table to go between object A and B, like in the case of a category and product relationship where the same product might be present in multiple categories. Subsonic will map the go-between and require more code to handle the relationship.

Subsonic

// Grab a random product and category
var product = Product.All().First();
var category = Category.All().First();
 
// Create the relationship
var categoryProductRelation = new CategoryProductRelation();
categoryProductRelation.ProductId = product.ProductId;
categoryProductRelation.CategoryId = category.CategoryId;
categoryProductRelation.Save();

NHibernate

// Grab a random category and product
var category = Category.All().First();
var product = Product.All().First();
// Simply add the product to the category and you're done
category.AddProduct(product);
category.Save();

As you can see NHibernate completely eliminates the requirement to create the relation object yourself. It will handle the intricacies of the relationship behind the scenes for you.

LINQ to uCommerce

With the switch to NHibernate LINQ to uCommerce will gain new options as well. The most obvious change is that you can get away with writing less code than today when doing joins. In many cases you can even get rid of the join altogether.

Subsonic

var query = from product in Product.All()
            join categoryRelation in CategoryProductRelation.All() on product.ProductId equals categoryRelation.ProductId
            join category in Category.All() on categoryRelation.CategoryId equals category.CategoryId
            where category.Name = "My Category"
            select product;

NHibernate

var query = from category in Category.All()
            join categoryRelation in CategoryRelation.All() on category equals categoryRelation.Category
            join product in Product.All() on categoryRelation.Product equals product
            select product;
// Notice that ids are omitted from the query

Summary

As you can see there are significant changes between the Entities and EntitiesV2 APIs, but rest assured that migrating to the newer API is very straightforward. uCommerce Admin, which is a pretty significant codebase written entirely against the Entities API was migrated to EntitiesV2 in three days straight including testing. The benefits we’ve seen from the migration are significant. UIs are more responsive, code required to do a certain operation is clearer, and more often than not there’s less of it.

posted on Tuesday, 07 June 2011 11:38:33 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Wednesday, 18 May 2011

Baskets, carts, bags, whatever you want to call them, people have very different expectations of how they should work given the business they’re in. By default uCommerce uses cookies to find the basket for a given customer, which is handy because the basket automatically carries over if the customer logs in. No need to migrate it from an anonymous context to a customer context.

But what if you have scenario where multiple people use the same computer to shop from? Effectively they’d share the same basket because it’s effectively tied to the computer, not the customer.

Fortunately the uCommerce Foundation API makes it simple to override this behavior. So lets take a look at what’s required to change the default basket behavior.

IOrderContext

uCommerce uses the IOrderContext interface to determine the basket of the current customer, specifically the GetBasket() and GetBasket(Boolean) methods are used. Let’s take a look at what the IOrderContext interface contains.

image

To make things are little easier we’re not going to implement IOrderContext from scratch, rather we’ll modify the default implementation, which comes with uCommerce called OrderContext.

OrderContext

As mentioned we’re looking to change the behavior of loading a basket for a customer and OrderContext has two methods for this purpose: GetBasket() and GetBasket(Boolean). Basically what we’re going to do is use the default behavior when a customer is not logged in and use our custom behavior whenever a customer is logged in.

Overriding GetBasket(Boolean)

First we need a new class to inherit the existing OrderContext and second override the two GetBasket methods.

using System;
using System.Linq;
using UCommerce.Entities;
using UCommerce.Runtime;
using umbraco.cms.businesslogic.member;
 
namespace MyUCommerceApp.Library
{
    public class MyOrderContext : OrderContext
    {
        protected ICatalogContext CatalogContext { get; set; }
 
        public MyOrderContext(ICatalogContext catalogContext) : base(catalogContext)
        {
            CatalogContext = catalogContext;
        }
 
        public override Basket GetBasket(bool create) {}
 
        public override Basket GetBasket()
        {
            return GetBasket(false);
        }
    }
}

So right now it doesn’t do much, so lets make it behave like the existing OrderContext when a customer is not logged in. We’re going to use the Umbraco Member API to determine whether a customer is logged in.

using System;
using System.Linq;
using UCommerce.Entities;
using UCommerce.Runtime;
using umbraco.cms.businesslogic.member;
 
namespace MyUCommerceApp.Library
{
    public class MyOrderContext : OrderContext
    {
        protected ICatalogContext CatalogContext { get; set; }
 
        public MyOrderContext(ICatalogContext catalogContext) : base(catalogContext)
        {
            CatalogContext = catalogContext;
        }
 
        public override Basket GetBasket(bool create)
        {
            // Member is not logged on use default behavior
            if (!Member.IsLoggedOn()) return base.GetBasket(create);
        }
 
        public override Basket GetBasket()
        {
            return GetBasket(false);
        }
 
    }
}

Now we’re actually detecting whether the customer is logged in and use the default behavior of OrderContext for customers not logged in.

Right now that means that the code is going to fail if a customer logs in, so lets add the final piece where we load the basket basket based on the current member id. If we can’t find a basket like that we’ll have to create one. Here we go.

using System;
using System.Linq;
using UCommerce.Entities;
using UCommerce.Runtime;
using umbraco.cms.businesslogic.member;
 
namespace MyUCommerceApp.Library
{
    public class MyOrderContext : OrderContext
    {
        protected ICatalogContext CatalogContext { get; set; }
 
        public MyOrderContext(ICatalogContext catalogContext) : base(catalogContext)
        {
            CatalogContext = catalogContext;
        }
 
        public override Basket GetBasket(bool create)
        {
            // Member is not logged on use default behavior
            if (!Member.IsLoggedOn()) return base.GetBasket(create);
 
            // Otherwise try and load a basket for the current member, create one if it doesn't exist
            Basket basket = GetBasketForCurrentMember() ?? CreateBasket();
 
            return basket;
 
        }
        public override Basket GetBasket()
        {
            return GetBasket(false);
        }
 
        private Basket GetBasketForCurrentMember()
        {
            PurchaseOrder order = PurchaseOrder.SingleOrDefault(
                x => x.OrderProperties.Where(y => y.OrderId == x.OrderId && y.Key == "MemberId" && y.Value == Member.CurrentMemberId().ToString()).Count() > 0 
                    && x.OrderStatusId == 1);
 
            if (order != null) return new Basket(order);
 
            return null;
        }
 
        private Basket CreateBasket()
        {
            var catalogId = 0;
            int.TryParse(CatalogContext.CurrentCatalogName, out catalogId);
 
            var catalog = ProductCatalog.SingleOrDefault(c => c.Name.Equals(CatalogContext.CurrentCatalogName)) ??
                ProductCatalog.SingleOrDefault(c => c.ProductCatalogId == catalogId);
 
            if (catalog == null)
                throw new InvalidOperationException("Cannot create basket when not in product catalog. Make sure that SiteContext.Current.CatalogContext.CurrentCatalogName contains the name of the current product catalog.");
 
            return CreateBasket(catalog.PriceGroups.First().Currency);
        }
 
        private Basket CreateBasket(Currency currency)
        {
            var catalogGroup = ProductCatalogGroup.SingleOrDefault(g => g.Name.Equals(CatalogContext.CurrentCatalogGroupName));
 
            if (catalogGroup == null)
                throw new InvalidOperationException("Cannot create basket without product catalog group. Make sure that SiteContext.Current.CatalogContext.CurrentCatalogGroupName contains the name of the current product catalog group.");
 
            PurchaseOrder order = new PurchaseOrder();
            order.OrderStatusId = 1;// (int)PurchaseOrder.StatusCode.Basket;
            order.ProductCatalogGroup = catalogGroup;
            order.CurrencyId = currency.CurrencyId;
            order.BasketId = Guid.NewGuid();
            order.CreatedDate = DateTime.Now;
            order.Save();
 
            // Set the member id on the order so we can retrieve it later on
            order["MemberId"] = Member.CurrentMemberId().ToString();
 
            return new Basket(order);
        }
    }
}

The thing that makes the code above tick is the used of dynamic order properties. Basically a way of setting custom data on the order or individual order lines. Whenever a new basket is created by MyOrderContext it will store the current member id on the order itself and use that to load the basket the next time around.

Registering MyOrderContext with uCommerce

To test our new context class we’ll have to let uCommerce know it exists. The way to do this is to edit the components.config file, which holds information about all the components of uCommerce. You’ll the file in /umbraco/ucommerce/configuration/components.config and this is what it looks like.

image

We’re looking for the IOrderContext registration.

image

A registration basically refers to a service, typically an interface like IOrderContext, a type, which is the actual implementation to use for that particular interface, and a lifestyle, which is how long the object will live. You can read more about lifestyle if you’re interested, but for now just leave that attribute alone.

We’ll have to put in our type and assembly for IOrderContext. For this example my code compiles to MyUCommerceApp.Library.dll and the type is called MyUCommerceApp.Library.MyOrderContext, so that’s what we’re going to swap in to replace the current order context.

<component id="OrderContext"
    service="UCommerce.Runtime.IOrderContext, UCommerce"
    type="MyUCommerceApp.Library.MyOrderContext, MyUCommerceApp.Library" lifestyle="PerWebRequest"/>

What that we’re ready to test our site. The behavior you’ll see is that you’ll get one basket when you’re not logged in, the default behavior, and another basket when you log in, our new custom behavior.

In Summary

As you can see overriding the default basket behavior of uCommerce is straightforward and you can achieve exactly the behavior you want. You saw a couple of interesting pieces put together to make it work: The IOrderContext and OrderContext, which were overridden to inject our custom behavor, the dynamic order property for storing our member if, and finally the component registration to tell uCommerce about our custom component.

Components in particular is a useful thing to know about as there are many opportunities to override the default behavior almost any aspect of uCommerce in there.

Other interesting examples for overriding GetBasket() might be to:

  • Do individual baskets between stores when working with a multiple store setup in the same uCommerce installation to replace the default shared baskets.
  • Work with multiple baskets per customer for wishlist and gift registry scenarios.
  • Support impersonation to enable a customer representative take over the customer basket to help her through checkout.

The sky’s the limit.

posted on Wednesday, 18 May 2011 10:33:33 (Romance Daylight Time, UTC+02:00)  #    Comments [0] Trackback
# Thursday, 10 March 2011

image

uCommerce 1.5 introduces nice URLs for catalogs, categories, and products. The basic idea is to provide keyword rich URLs for catalog items to increase page rank in search engines like Google and Bing. Really though, who are we kidding here? It’s just for Google  :)

Based on Existing Catalog Information

To keep maintenance low uCommerce generates URLs based on information already present in the catalog. To support multilingual sites display names are used when present otherwise standard internal names are used. This gives webshops built with uCommerce the ability to rank on search terms specific to the culture the online store services, e.g. English terms for English stores, Spanish terms for Spanish stores, etc..

URLs are structured in three parts:

  1. The domain name, which also determines the language to use as per Umbraco hostname
  2. The search engine friendly soft middle
  3. And finally the payload at the end, which enables uCommerce to figure which type of URL it’s dealing with

For a sample URL like www.myonlinestore.com/apparel/c-24 the three pieces are:

  1. “www.myonlinestore.com” – domain name of the store as set up in Umbraco
  2. “apparal” – search engine search term
  3. “c-24” – identifier of the catalog for uCommerce to use

Basically Umbraco and uCommerce only need the first and last pieces while the rest is all for Google.

Nice URLs from XSLT

To start using nice URLs in your own uCommerce solution you’ll need to use one of the following XSLT extensions:

GetNiceUrlForCatalog(string catalogName)
GetNiceUrlForCategory(string catalogName, string categoryName)
GetNiceUrlForProduct(string catalogName, string categoryName, string sku)
GetNiceUrlForProduct(string catalogName, string sku)
GetNiceUrlForVariant(string catalogName, string sku, string variantSku).

There are multiple extensions for each type of URL you’ll generate as they have slightly different needs for the final result. The method will generate the following URLs:

Catalog called “Apparel”

<xsl:variable name="catalogUrl" select="CommerceLibrary:GetNiceUrlForCatalog('Apparel')"/>

www.myonlinestore.com/apparel/c-24

Category called “T-shirts” nested in “Shirts” / “Men”

<xsl:variable name="categoryUrl" select="CommerceLibrary:GetNiceUrlForCategory('Apparel', 'TShirts')" />

www.myonlinestore.com/apparel/shirts/men/t-shirts/c-24/c-71

Product “Short sleeved green t-shirt

<xsl:variable name="categoryUrl" select="CommerceLibrary:GetNiceUrlForProduct('Apparel', 'TShirts', 'Green-TShirt')" />

www.myonlinestore.com/apparel/shirts/men/t-shirts/short-sleeved-green-t-shirt/c-24/c-71/p-107

<xsl:variable name="categoryUrl" select="CommerceLibrary:GetNiceUrlForProduct('Apparel', 'Green-TShirt')" />

www.myonlinestore.com/apparel/short-sleeved-green-t-shirt/c-24/p-107

Nice URLs from .NET

To generate those same URLs from .NET you’ll use the IUrlService. Using the ObjectFactory class you can resolve the configured instance for the interface. The default implementation is called UrlSerivce. More on that later.

IUrlService urlService = ObjectFactory.Instance.Resolve<IUrlService>();
 
ProductCatalog catalog = ProductCatalog.SingleOrDefault(x => x.Name == "Apparel");
string catalogUrl = urlService.GetUrl(catalog);
 
Category category = Category.SingleOrDefault(x => x.Name = "TShirts");
string categoryUrl = urlService.GetUrl(catalog, category);
 
Product product = Product.SingleOrDefault(x => x.Sku == "Green-TShirt" && x.ParentProductId == null);
string productIncludingCategoryInfoUrl = urlService.GetUrl(catalog, category, product);
string productUrl = urlService.GetUrl(catalog, product);

Building Your Own Nice URLs

image

If you wish to customize the default nice URLs you can go ahead and inherit the class UrlService and override any methods you’re not happy with. Should you need to replace the default nice URLs generated by uCommerce you can implement the IUrlService interface from scratch.

If for instance you need complete control over the keywords added to the URL your custom implementation might grab information not from the display name, but from a dedicated field on the category or product.

In any case you have to register your custom implementation via /umbraco/ucommerce/configuration/components.config. Just look for the existing registration of IUrlService.

URL Rewrite Rules

UrlRewriting.NET contains the set of rules, which define what URL the customer sees and what that URL should look like to the system.

You will not have to change the existing rules even if you implement your own UrlService as long as you keep the last part of the URL the same, i.e. the /c-xx/c-yy/c-zz part. This is the marker used for the rules to pick up a rewritten URL so you can include anything before that part. If you don’t want the marker as part of your URL you’ll have to modify the default rules.

Each rule is automatically deployed when uCommerce is installed and is found in /config/UrlRewriting.config in your website folder. If you wish to modify the default rules this is the place to do it.

Summary

Nice URLs help the search engine optimization process for webshops built with uCommerce and will make pages in your webshop rank higher. Any URL scheme is supported by overriding the default implementation found in UrlService.

posted on Thursday, 10 March 2011 22:32:35 (Romance Standard Time, UTC+01:00)  #    Comments [0] Trackback
# Thursday, 03 March 2011

Probably the most interesting new feature to come to Umbraco lately (for .NET developers anyway) is support for the Razor view engine. The Razor view engine was originally (sounds like it was year ago when in fact it only happened recently) introduced with MVC 3 to reduce friction when writing UI code.

XSLT, .NET, or Both

NET-logoXSLTOne of the first questions I’m asked when I demo uCommerce to new partners is, “should we use XSLT or .NET user control to build our uCommerce sites”.

My advice over the past couple of years has always been to use XSLT for static listings and roll out .NET for the more dynamic pieces like the check out flow or advanced product pickers.

It’s no secret that my background in .NET makes me whip out Visual Studio for almost everything, but XSLT does have some interesting attributes like the ability to build out a UI in no time and reskin existing UIs rapidly. That’s why we built the uCommerce Demo Store in XSLT exclusively and that’s why I originally invested some time in getting to know it.

Now, however, my advice might be about to change. Read on and find out why.

Introducing Razor, Macros on Steroids!

The answer to make .NET devs as efficient creating UIs as XSLT gurus is Razor. While it won’t make developers better designers it will enable them to roll out UIs very rapidly and in a more fluent manner to boot.

The Razor view engine is basically an advanced parser, which enables you to write code much more fluently than what was possible with the WebForms view engine. Gone are the days of <%%> replaced by @.

Basically you can now write code like this in your macros and it will render properly inside your templates.

@using umbraco.cms.businesslogic.member
 
@if (Member.GetCurrentMember() != null)
{
    @string.Format("Hello there, {0}, nice to see you again!", Member.GetCurrentMember().LoginName)
}

And this is what it looks like in Umbraco itself. Pretty straightforward, right? Create a new script file using CSHTML and then create a new macro, select the script you created previously, and you’re good to go.

image

image

uCommerce and Razor: Product Listing

So how does this work with uCommerce? As it turns out, quite well. The Active Record pattern combined with LINQ to uCommerce turns out to be a perfect fit for the Razor coding style. Lets see what it takes to get some products into the mix, shall we?

It’s very straightforward: Import the uCommerce entities and query away!

@using UCommerce.EntitiesV2
 
@foreach (var product in Product.All())
{
    <h1>@product.Name</h1>
}

image

Not surprisingly, the code produces the following result.

SNAGHTML1769ec5

But what’s with the 5, 10, and 15? Turns out that the list contains both product, product families, and variants. Lets expand on the query a bit and only display the top level products and families.

Notice how the following query now has a Where clause on the call. What we’re doing is filtering the result to only grab the products we want. See how easy that is? Common operations like filtering, grouping, and even joining is supported which opens up for some very interesting scenarios.

@using UCommerce.EntitiesV2
 
@foreach (var product in Product.All().Where(x => x.ParentProductId == null))
{
    <h1>@product.Name</h1>
}

SNAGHTML1704eb3

Simple Basket Page

How about another one just for kicks? What’s interesting here is that we’re leveraging the context aware API of uCommerce to determine the basket given the current customer. Because the API deals with context you don’t have to worry about getting the right data, it’s just there ready to be consumed.

@using UCommerce.Runtime
 
<table>
    <th>SKU</th><th>Name</th><th>Qty</th><th>Unit Price</th><th>Total</th>
    @foreach (var orderLine in SiteContext.Current.OrderContext.GetBasket().PurchaseOrder.OrderLines) 
    {
        <tr>
            <td>@orderLine.Sku</td>
            <td>@orderLine.ProductName</td>
            <td>@orderLine.Quantity</td>
            <td>@orderLine.Price</td>
            <td>@orderLine.Total</td>
        </tr>
    }
</table>

Again the code above is a full Razor macro in Umbraco, which is placed on a template to achieve the output below. With that we’ve got the beginnings of basket overview page. See how clean that is?

SNAGHTML30278e6

Summary

While Razor was introduced in Umbraco 4.6 it’s not really until 4.7 it’s become really usable. In testing uCommerce with Umbraco 4.7 I found the combination of Razor and LINQ to uCommerce to work surprisingly well. The flow inherent in Razor is carried over to the uCommerce API. As a result the code flows naturally just the way we like it.

With Razor .NET developers start to see the same level of productivity which has been exclusive to the XSLT gurus when creating UIs. Not only that but the UI code is very readable and the full .NET framework is available without having to resort to XSLT extensions as is the case with XSLT today.

posted on Thursday, 03 March 2011 22:05:36 (Romance Standard Time, UTC+01:00)  #    Comments [0] Trackback