uCommerce How To: Create A Product Using The API

7. January 2010

If you want to create a product using the API, here’s how.

The class diagram for products looks like this:

Product

This might seem a bit verbose, but it’s all in favor of the flexible pricing and localization of products.

The data access is based on Active Record. If you haven’t already heart of that, check out the description on Wikipedia before reading any further.

Because localized descriptions, category placement and pricing information references the concrete product, we need to create the product itself first.

Before that, a short note on how to query the database for entites. If you want to find a specific entity, you can use the static SingleOrDefault<T>(Func<T, bool>) method. This will work for all entities:

var product = Product.SingleOrDefault(x => x.ProductId == 42);

If you want a collection of entities, use the Find<T>(Func<T, bool>) method. For example, to find all products modified within the last week:

var products = Product.Find(x => x.ModifiedOn >= DateTime.Now.AddDays(-7));

You can also use more advanced Linq queries. Getting products modified within the last week can be retrieved like this:

var products = from p in Product.All()
               where p.ModifiedOn >= DateTime.Now.AddDays(-7)
               select p;

You can also do joins and so on.

The Product

The create the product, simply create a new instance of the UCommerce.Entites.Product class, set the properties, and finally call the save method.

var product = new Product
                  {
                      Sku = "SKU-123456",
                      Name = "My Product",
                      AllowOrdering = true,
                      DisplayOnSite = true,
                      ProductDefinitionId = 1,  // Set to an existing defintion
                      ThumbnailImageMediaId = 1 // ID from Umbraco (nullable int)
                  };
product.Save();

After calling the save method, the ProductId property will return the ID of the new product.

Localized Product Description

To add a localized description for the product, create a new instance of the UCommerce.Entities.ProductDescription class.

var description = new ProductDescription
                      {
                          ProductId = product.ProductId,
                          CultureCode = "en-US", // or en-GB, da-DK etc.
                          DisplayName = "My display name",
                          ShortDescription = "My short description",
                          LongDescription = "My long description"
                      };
description.Save();

Like with the product, the ProductDescriptionId will return the new ID of the description after calling the save method.

Pricing Information

The save a price for a product, you find the ID of the price group you want the price to belong to. After that, you can create a new price using the PriceGroupPrice class (yes, I know).

var priceGroup = PriceGroup.SingleOrDefault(x => x.Name == "DKK");
var productPrice = new PriceGroupPrice
                       {
                           ProductId = product.ProductId,
                           PriceGroupId = priceGroup.PriceGroupId,
                           Price = 499.95m
                       };
productPrice.Save();

As of now, you have probably guess what the PriceGroupPriceId property will return.

Category Association

Last, but not least, you probably want to add the product to one or more categories. This is done using the CategoryProductRelation class.

var category = Category.SingleOrDefault(x => x.Name == "Software");
var relation = new CategoryProductRelation
                   {
                       ProductId = product.ProductId,
                       CategoryId = category.CategoryId
                   };
relation.Save();

That’s it, the new product is ready to be sold!

Let me know if you have any issues or questions.

Updated – How To Set Custom Properties

If you have added custom properties to a product using product definitions, you can access the properties simply by using the indexer on the product. Note that properties are always stored as strings (nvarchar), so you need to do your own casting, depending on the type of the property.

var property = product["MyProperty"];
property.Value = "New value";
property.Save();

uCommerce ,

Setting Up Simple URL Rewriting In uCommerce

1. December 2009

With uCommerce comes a simple sample implementation of a complete store, which you can use as inspiration for getting started. image

The sample store uses the query string to pass catalog-, category-, and product names when redirecting to other pages where this information is needed, for example when browsing the catalog.

If you want search engine friendly URLs instead, you can configure Umbraco’s URL rewriting to include your uCommerce content too, and here is how.

Open the file UrlRewriting.config placed in the /config folder in the root of your Umbraco installation, and add the following elements to the <rewrites> element:

<add name="ProductRewrite"
     virtualUrl="^/shop/(.*)/(.*)/(.*).aspx"
     rewriteUrlParameter="ExcludeFromClientQueryString"
     destinationUrl="~/shop/product.aspx?catalog=$1&amp;category=$2&amp;product=$3"
     ignoreCase="true"/>

<add name="CategoryRewrite"
     virtualUrl="^/shop/(.*)/(.*).aspx"
     rewriteUrlParameter="ExcludeFromClientQueryString"
     destinationUrl="~/shop/catalog.aspx?catalog=$1&amp;category=$2"
     ignoreCase="true"/>

<add name="CatalogRewrite"
     virtualUrl="^/shop/(.*).aspx"
     rewriteUrlParameter="ExcludeFromClientQueryString"
     destinationUrl="~/shop/catalog.aspx?catalog=$1"
     ignoreCase="true"/>

This gives you pretty URLs, like these for example:

Page Sample URL
uCommerce catalog /shop/ucommerce.aspx
Software category /shop/ucommerce/software.aspx
Product with SKU 100-000-001 /shop/ucommerce/software/100-000-001.aspx

Note that you still need to modify the links in the XSLT files for the sample store to generate these URLs.

The examples above are simple examples, which you probably need to adjust to your client’s needs, and your site structure. For a more comprehensive documentation on how to configure rewriting, check out the documentation for the UrlRewrite.net component that Umbraco uses.

uCommerce

Extending uCommerce Admin

30. November 2009

imageWhen working with the different entities in uCommerce admin, you have the option to add additional tabs to each view, so that you can integrate your own user controls in uCommerce admin.

Configuring Tabs

To add more tabs to a view, you need to go to the database, and add your tab to the ucommerce_admintab table. To find out which view (page) the tab is related to, take a look at the ucommerce_adminpage table.

The following table contains the columns in ucommerce_admintab which should be of interest to you:

Column Description
VirtualPath The virtual path of your user control (.ascx). The path is relative to the page you want the tab to appear on. Note that you can use both ~/ and ../.
AdminPageId The page where the tab should be placed on, defined in ucommerce_adminpage.
SortOrder Defines how the tabs for the page should be ordered.
Multilingual If set to true, one tab of the type is added per language configured in Umbraco.
Note: Multilinual tabs should implement the IMultilingual interface – more about this later.
ResourceKey Put the text on your tab here. This will be overriden by the language name if you specify your tab to be multilingual.
HasSaveButton If set to true, the save button will be visible on the toolbar for this tab.
HasDeleteButton The same as HasSaveButton, only for a delete button.
Enabled Yes, you can both enable and disable tabs.

Implementing User Controls For Use On Tabs

To create the user control you want on your new tab, simply create a new project in Visual Studio, create a reference to UCommerce.Presentation.dll, create a new user control, and make that user control inherit from UCommerce.Presentation.Web.ViewEnabledControl<T>. The generic parameter T must be the type of the view you want your control to appear on. This is necessary so that they can interact.

You’ll find a list of the most commonly used view here:

View Interface
Edit product catalog group IEditProductCatalogGroupView
Edit product catalog IEditProductCatalogView
Edit category IEditCategory
Edit product IEditProduct
View order IViewOrderGroupView

There are one for each view in uCommerce, and should be pretty easy to find. Let me know if there is one you can’t find.

From your user control, there are two events that is of interest to subscribe to:

event EventHandler<EntityCommandEventArgs<T>> Saving;
event EventHandler<EntityCommandEventArgs<T>> Saved;

The Saving event is raised before the main entity (e.g. Product on IEditProductView) is saved, and the Saved event is raised after the main entity has been saved. If you want to modify the main entity before it is saved, do it at the Saving event. The EntityCommandEventArgs<T> will pass you a reference to the main entity.

For some views, you can also subscribe to these two events, which are raised when deleting the entity – they are handy for doing some cleanup:

event EventHandler<EntityCommandEventArgs<T>> Deleting;
event EventHandler<EntityCommandEventArgs<T>> Deleted;

From your user control, you also have access to the view itself using the View-property on the ViewEnabledControl<T> you inherit from.

Creating Mutlilingual Tabs

As previously mentioned, you can make your tabs multilingual by implementing the IMultilingual interface. By doing this, one tab containing your user contorl will appear for each language configured in Umbraco. The CultureCode property will automatically be set to the culture code of the language for the tab.

/// <summary>
/// Contains definition for a multi lingual class.
/// </summary>
public interface IMultiLingual
{
    /// <summary>
    /// The culture code.
    /// </summary>
    /// <example>
    /// da-DK for Denmark, en-GB for Great Britian etc.
    /// </example>
    string CultureCode { get; set; }
}
Custom Initialization On Tabs

If you want custom initialization on your tab, you can implement the IHasTabPage interface.

/// <summary>
/// Defines if an user control exists on a tab page.
/// </summary>
public interface IHasTabPage
{
    /// <summary>
    /// Initializes the tab page.
    /// </summary>
    /// <remarks>
    /// This is where the menu should be initialized.
    /// </remarks>
    /// <param name="tabPage"></param>
    void InitializeTabPage(TabPage tabPage);

    /// <summary>
    /// Gets a value indicating whether or not this tab should be displayed.
    /// </summary>
    bool ShowTab { get; }
}

If, for example, you want to add your own custom button to the toolbar, you can do it like this:

public void InitializeTabPage(TabPage tabPage)
{
    var myButton = tabPage.Menu.NewImageButton();
    myButton.AlternateText = "This is the tool tip";
    myButton.ImageUrl = "/images/MyToolbarButton.png";
    myButton.Click += MyButton_OnClick;
}

When you are done with your user control, copy the .ascx to the path you have specified in ucommerce_admintab, copy the dll to the /bin folder, and your new tab should be ready for use.

Extending the admin UI is not something you would for every solution, but if you have the need, it can add great value for your client.

As always, let me know if you have any questions.

uCommerce ,

Understanding uCommerce Order Statuses

25. November 2009

When implementing an e-commerce solution, you might need to adapt your solution to either your own, or your client’s order fulfillment process. To support a flexible workflow around this process, uCommerce supports configurable order statuses.  

imageOut of the box, uCommerce comes with 5 statuses preconfigured.

  • New order
  • Completed order
  • Invoiced
  • Paid
  • Cancelled

Each status can be configured as being part of the fulfillment process.

To edit each status, you need to start the developer’s swiss army knife of configuration, and open the ucommerce_orderstatus table.

image

Note that there are a 6th status – Basket. This is used to handle baskets on the public facing site, so please do not delete it.

You should note the following columns:

Column Description
OrderStatusId The primary key of the order status.
Name The name of the status, displayed under the Orders-node in uCommerce admin.
Sort The sort order in uCommerce admin.
RenderChildren Defines whether or not orders should be rendered in the tree for this status. Handy for the final order status, where you hopefully will have a lot of orders.
NextOrderStatusId Defines which status (referenced by OrderStatusId) is the next in the order process. For example, a new order can only be promoted to a completed order.
IncludeInAuditTrail If set to true, the audit trail will be updated when an order’s status is set to this status.
AllowUpdate If set to false, no more status changes can be made to orders with this status.
AlwaysAvailable If set to true, this status is always available from any order status, except for those where AllowUpdate is set to false. Handy for a cancelled-status.
Pipeline Here you can put the name of a pipeline you would like executed when an order is set to this status. For example, when an order is set to Invoiced, you might want to capture an online payment, or if an order is returned, you want to put the products back in stock and debit the customer’s account.

When viewing an order in uCommerce admin, you can change an order’s status by clicking the “Change Status” button in the toolbar. 

In the Update Order Status popup, the rules you set up in the ucommerce_orderstatus table is followed, and the user cannot bypass the defined order flow.

imageimage

If you want to know more about pipelines, take a look at my previous post.

That’s all there is to it – let me know if you have any questions.

uCommerce ,

uCommerce Pipelines Explained

10. November 2009

One of the things you will need when building complex sites with uCommerce is the pipeline system.

A pipeline is a series of tasks, which will execute in a sequental order. You can use these tasks to execute whatever business logic you want, when working with baskets or orders. Currently, the pipeline system only applies to baskets and orders.

The Bits and Pieces of a Pipeline

A pipeline consists of three things:

  • The pipeline configuration file itself (an XML file)
  • An optional pipeline implementation (written in your favorite .net language)
  • One or more pipeline tasks (also written in anything .net-ish)

The configuration file contains the type of the pipeline, each registered pipeline task and the order of which the tasks will be executed.

The file must be located in the /umbraco/ucommerce/pipelines folder. As you can see in the folder, uCommerce comes with a pipeline out-of-the-box – the basket pipeline. Take a look at basket.config to see how it is configured.

The Configuration File

The first component section contains the type of the pipeline, which is a generic type. As mentioned earlier, only baskets and orders are currently supported, which means that the generic type should be UCommerce.Entities.PurchaseOrder (which also applies to baskets). The pipeline type used in the basket pipeline is UCommerce.Pipelines.Basket.BasketPipeline. If you want to implement your own pipeline, you can use the generic type UCommerce.Pipelines.Generic.PurchaseOrderPipeline defined in the UCommerce.Pipelines assembly.image

After the pipeline type, each pipeline step is defined, each in it’s own component section with an id. The id is then used in the <tasks> section under the pipeline type to add the task the pipeline, which will then execute the task.

Note: The order of which each task is registered in the <task> section, is the same as the order as they will be executed in.

Writing Pipeline Tasks

Ok, so enough with the XML for now.

To create your own pipeline task, simply implement the IPipelineTask<T> interface.

    /// <summary>
    /// Contains definition for a pipeline task.
    /// </summary>
    /// <typeparam name="T">The type on which the task operates on.</typeparam>
    public interface IPipelineTask<T>
    {
        /// <summary>
        /// Executes the task.
        /// </summary>
        /// <param name="subject">The subject for the task.</param>
        /// <returns></returns>
        PipelineExecutionResult Execute(T subject);

The task must return a member of the PipelineExecution Result enum.

    /// <summary>
    /// Result returned when executing a pipeline or a pipeline task.
    /// </summary>
    public enum PipelineExecutionResult
    {
        /// <summary>
        /// The pipeline or task executed sucessfully.
        /// </summary>
        Success,
        /// <summary>
        /// The pipeline or task has been executed, but with warnings.
        /// </summary>
        Warning,
        /// <summary>
        /// The pipeline or task generated an error.
        /// </summary>
        Error
    }

If the task returns Success, the execution of the pipeline will continue. If you return Warning, the execution will continue, but the overall execution result for the entire pipeline will be set to Warning. If the task returns Error, the pipeline execution will stop, and no additional tasks will be executed. If any exceptions is thrown in a pipeline task, to execution will stop with a PipelineException, with the exception from the task as the inner exception.

Executing Pipelines

There are two ways to execute your pipelines:

  • From code
  • From XSLT

 

Executing Pipelines From Code

Executing the pipeline from code using the PipelineFactory is pretty simple:

public PipelineExecutionResult ExecutePipeline(string pipelineName, 
PurchaseOrder order) { var basketPipeline = PipelineFactory.Create<PurchaseOrder>(pipelineName); var result = basketPipeline.Execute(order); return result; }
Executing Pipelines From XSLT

To execute a custom pipeline from XSLT, call the ExecuteOrderPipeline(string pipelineName) method on the uCommerce XSLT library.

<xsl:value-of select="CommerceLibrary:ExecuteOrderPipeline('MyPipeline')">
</xsl:value-of>

If you want to execute the basket pipeline, you can call this nifty method instead:

<xsl:value-of select="CommerceLibrary:ExecuteBasketPipeline()"></xsl:value-of>

Both of the above methods will return the pipeline execution result as XML. If an exception has occured, the exception message will be included in the XML.

So What’s Up With That Basket Pipeline?

The basket pipeline is a built-in pipeline used by the uCommerce runtime. The pipeline will make sure that all e.g. all totals are recalculated. Please do not delete it, but feel free to add your own tasks, if there’s anything you need on recalculating the basket.

A Short Note On Order Statuses And Pipelines

Customization of order statuses is the topic for an upcoming post, but you should know that you can execute pipelines after order status changes. Order statuses are configured in the uCommerce_OrderStatus table. To run a pipeline when an order has been set to a given status, simply but your pipeline name in the “Pipeline” column. If you e.g. want to capture an online payment, this would be a great place to do it.

That’s it for the pipelines. Feel free to contact me if you need more info on the pipeline system.

uCommerce ,

New blog, not a completly new blogger

27. June 2009

I have been blogging on weblogs.asp.net/lasse for a while, but since we started the beta for uCommerce, I have decided to move my blog here instead. Anytime soon I will be moving my old posts to this blog.

Stay tuned.

uCommerce, Blog