Adding shipping methods to a Commerce Server Basket

Posted 11 May 2009, 23:26 | by | | Perma-link

This week, I have mostly been using Commerce Server. Well, to be honest it’s more like this month, but there we go. Seeing as I've only really ever managed other developers using Commerce Server, and we stuck pretty much to the "Let's try and make our business requirements line up with the starter site", this has been a fairly steep learning curve - as we're currently building a system with no inventory, nothing to deliver, and we're using a form building solution to create a heavily designed site - it's going to look great, but it might be painful getting there.

As you may have noticed from twitter, there are some things about this experience that I really don't appreciate in this day and age - most notably the whole magic string setup - although I guess that's partly due to the "extensible" nature of the system. But then there's the mixing of types - most things a user creates, such as catalogues, products, variants, discounts, etc have a string identifier, or possibly an integer if you're lucky, but then we got on to shipping methods - there aren't any, it's an online subscription, we have no stock (but for the last week all our products have been "out of stock"), so we have nothing to deliver, but I'm still getting pipeline errors because there's no shipping method associated with the basket.

So to the meat of this post: How do I associate a shipping method with a basket? I don't. I associate a shipping method with a Line Item - each and every one in the basket - and no way to say "apply this setting to all line items" - how often do you think to yourself on Amazon, "Oh, I'd like that CD to arrive tomorrow, but I don't mind if that one doesn't turn up for 5 days on their Super Saver Delivery™ option"? I know I don't, I just order stuff and have it turn up when it does, which pretty much ends up like that, as I order books that aren't out yet.

All I can say is thank you Microsoft for Object Initializers - they mean that I can at least do this:

// Get the current line items from the Commerce Sever basket
LineItemCollection currentItems = orderform.LineItems;
// Loop over the line items from the webservice call
foreach (wsLineItem wsItem in basketDetails.LineItems) {
  // See if we can find a line item in the basket that
  // matches the one from the web service
  csLineItem csItem = findLineItem(currentItems,
                                   wsItem.Catalogue,
                                   wsItem.Id,
                                   wsItem.VariationId);
  if (csItem == null) {
    /* We didn't find one, so add a new line item to the basket.
     * Here's where the magic happens - create a new line item with all
     * the properties we can set in the constructor, then add the remainder
     * through object initializers. */
     currentItems.Add(
              new csLineItem(wsItem.Catalogue,
                             wsItem.Id,
                             wsItem.VariationId,
                             wsItem.Quantity)
                             {ShippingMethodId = basketDetails.ShippingMethod});
  } else {
    // We found a match
    if (wsItem.Quantity == 0) {
      // The web service had 0 in the quantity - remove the item
      currentItems.Remove(csItem);
    } else {
      // The web service might have an updated quantity - update.
      csItem.Quantity = wsItem.Quantity;
    }
  }
}

Filed under: ASP.NET, Commerce Server