Assembly redirect not working?

22. December 2010

I spent the evening troubleshooting an issue, where we needed redirect some assemblies from one version to another – something that might happen to you, if you use Fluent NHibernate and the Castle Project in the same assembly.

The project had a reference to Castle.Core.dll version 2.2.0.0, but Fluent NHibernate requires version 2.1.0.0 of the same file. We set up the redirect in web.config, but still got an exception at runtime, telling us that we needed version 2.1.0.0 of the file.

The cause: We had forgotten the ever so important namespace for the assemblyBinding element in web.config!

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity name="Castle.Core" 
                        publicKeyToken="407dd0808d44fbdc"></assemblyIdentity>
      <bindingRedirect  oldVersion="1.1.0.0" 
                        newVersion="1.2.0.0"></bindingRedirect>
    </dependentAssembly>
    <dependentAssembly>
      <assemblyIdentity name="Castle.DynamicProxy2" 
                        publicKeyToken="407dd0808d44fbdc"></assemblyIdentity>
      <bindingRedirect  oldVersion="2.1.0.0" 
                        newVersion="2.2.0.0"></bindingRedirect>
    </dependentAssembly>
  </assemblyBinding>
</runtime>
Do’h.

.NET, ASP.NET ,

A sneak peak on exporting orders from uCommerce

15. December 2010

For the last couple of weeks, I have been working on the newest addition to uCommerce, called uCommerce Connector.

The purpose of the Connector is to, well, connect uCommerce to your backend systems, like your ERP system, inventory management, order fulfilment and so on. The connection goes both ways. For example, you might want to import products into uCommerce, and export orders back into your ERP system.

This blog post is an example on how to manually export orders from within uCommerce. Please note that the Connector is not yet released, and the API’s are subject to change.

The basics of uCommerce Connector

The Connector is able to handle all imports and exports to and from uCommerce. All entites can be used – even your own.

Each import or export are created using a workflow, which is a series of steps, defined in an XML file. Each step can be either a source, a transformation or a destination. These steps can be easily implemented using your favorite .NET language. A workflow can be hosted either in the site, or in a Windows service, ie. for automatically exporting orders whenever they are recieved or changed to a certain status.

An example: Exporting orders

The purpose of this example is to show how the default orders export is implemented. This will be a default feature in uCommerce, once released.

I have added a new export action for a single order. ExportOrderWhen exporting an order, the user should be able to select a format, and then download the order from a dialog.

ExportOrderDialog

Step 0: Interfaces and the XML file

Each workflow is contained in an XML file, listed below (click to enlarge). This XML file contains the steps created in remainder of this post.

image

The components section contains the components for the workflow, and the workflow section contains the order in which the components will be executed. Note that there will be more steps available in a later version, such as a conditional step, and a much nicer UI for editing workflows, so you don’t have to mess around with the XML. But now you know it’s there.

The component for the first step must be a source, by implementing the IConnectorSource<T> interface:

public interface IConnectorSource<T> : IConnectorSource
{
    T Get();
}

And the last step must be a destination, by implementing the IConnectorDestination<T> interface:

public interface IConnectorDestination<T> : IConnectorDestination
{
    void Persist(T value);
}

It is important to note, that the output of each step, must match the input of the next step. That’s why you can add transformations in between the source and the destination.

Transformations must implement the ITransformation<TFrom, TTo> interface (more types will be added):

public interface ITransformation<TFrom, TTo> : ITransformation
{
    TTo Transform(TFrom from);
}

Step 1: Getting the currently selected order

The ID for the current order can be found in the query string for the dialog, and since we have access to the current HTTP context from within our workflow, we can grab the value from here and return the order from the database, using the sample code below:

public class BackEndSelectedPurchaseOrderSource : IConnectorSource<PurchaseOrder>
{
    public PurchaseOrder Get()
    {
        var orderIdString = HttpContext.Current.Request.QueryString["id"]
            .Replace("Order_", string.Empty);
        var orderId = int.Parse(orderIdString);

        return PurchaseOrder.SingleOrDefault(x => x.OrderId == orderId);
    }
}

Step 2: Transforming the order to XML

Next up, we would like to transform the order into XML, so the user can download it, and import it elsewhere. Since uCommerce already supports rendering all entities as XML, to be used via the XSLT API, we can just reuse these renderes:

public class PurchaseOrderToXmlDocumentTransformation 
    : ITransformation<PurchaseOrder, XmlDocument>
{
    public XmlDocument Transform(PurchaseOrder from)
    {
        var renderer = CreateRenderer();
        return renderer.RenderDocument(from);
    }

    private static PurchaseOrderRenderer CreateRenderer()
    {
        return PurchaseOrderRenderer.Create();
} }

Step 3: Downloading the file

Last but not least, we put the XML in a stream and send it to the user, which will open the browser’s standard file download dialog box:

public class PurchaseOrderDownloadStreamDestination 
    : IConnectorDestination<XmlDocument>
{
    public void Persist(XmlDocument value)
    {
        var stream = new MemoryStream();
        var streamWriter = new StreamWriter(stream) { AutoFlush = true };

        streamWriter.Write(value.InnerXml);
        stream.Position = 0;

        Download(stream, Guid.NewGuid() + ".xml");
    }

    private static void Download(Stream stream, string fileName)
    {
        var response = HttpContext.Current.Response;

        byte[] buffer = new byte[(int)stream.Length];
        stream.Read(buffer, 0, (int)stream.Length);

        response.Clear();
        response.AddHeader("Content-Disposition", 
            string.Format("attachment; filename={0}", fileName));
        response.AddHeader("Content-Length", stream.Length.ToString());
        response.ContentType = "application/octet-stream";
        response.BinaryWrite(buffer);
        response.End();
    }
}

Step 4: Registering the new workflow

The workflow created above can be added to the web site’s web.config, in the Commerce section, and will now be accesible from the export dialog:

<integration>
  <workflows>
    <add name="XmlDownload" 
          filePath="~/umbraco/ucommerce/integrations/exportcurrentorder.xml" 
          displayName="XML download" 
          supportedEntity="PurchaseOrder" />
  </workflows>
</integration>

Other usages

The example above is a pretty simple one. In other scenarios, you could replace the download destination with a web service destination, to put the order directly into an ERP system. It is important to remember, that the Connector and the workflows are all about customizing and adjusting uCommerce to your clients individual needs.sam

Your feedback is greatly appreciated!

As mentioned earlier, the Connector is still under development, so if you have any feature requests, questions, ideas or anything else, please let us know, so that we can make sure that you can benefit from the Connector.

Until next time…

.NET, ASP.NET, uCommerce , ,

Internet Caching Must Reads

11. November 2009

Usually, when people (developer-people, that is) think about caching, they think of the local cache, which will hold cached data from the database, for example.

Lucky for us, and little known to others, there are a lot more to caching than HttpContext.Current.Cache and Enterprise Library. This article explains all the Internet caching intermediates out there, and reading it is time well spent: http://www.mnot.net/cache_docs/.

.NET, ASP.NET , ,