Tuesday, 15 July 2014

Amazon daily trends report - information, XML and tips

If you are an Amazon Associates it is possible to view a report over the Daily Trend for your account. This gives you the following information:

Amazon Daily Trend report in XML format

  • AMZUnits (Items Ordered (Amazon) - how many products have been ordered, where Amazon is the seller
  • Clicks (Clicks) - how many total visitors you have generated
  • Conversion (Conversion)- how much did you sell compared to how many visitors you have. Note that it uses the total units sold, so if you have one customer that buys two products you have a Conversion rate of 200%
  • Date (Date (yyyy/mm/dd)) - the day of the visit (Only in the Day structure)
  • Units (Total Items Ordered) - the total amount of products that have been sold both with Amazon as the seller and 3rd party seller that uses Amazons platform.
  • Visitors (Unique Visitors)- the unique number of visitors. If you refer the same customer twice it only counts as one unique visitor
In the above list the first name is the name in the XML file and the name in parents is the name of the column in the web page report.
Amazon daily trend report in diagram format
So what can you use this data for? You can use this information to see how many you refer to Amazon on a daily basic. If you use the Unique Visitors and compare it to the same measure in Goggle Analytics you will be able to see what you conversion rate is to Amazon. How many of your users uses a link/ad/widget to go to Amazon to consider to buy a product. 

You should use this information to find out where on your pages you have the most success to add links to Amazon that send users to Amazon. Try to place you links/ads/widgets on different locations on your pages to find the optimal way to send customers to Amazon and get a nice referral rate.

Monday, 14 January 2013

Delay activity in Workflow foundation

The Delay activity in Workflow Foundation can be used in many scenarios, but the most likely use is in a composite operation, where you want the execution to wait for a response and cast a failure if the response isn't received in proper time.

The Delay activity has just one parameter, which is call Duration. It expects a Timespan variable or expression. If you want the same duration in every place it would be wise to create a variable to hold the value and use it at the right spots or a better option would be to create a custom activity:

  1. Add a new file
  2. Add the delay activity
  3. Set the Duration on the delay activity
  4. Rebuild the project
  5. Add the custom activity to your workflow

In Visual Basic Workflow projects this is how you configure it in the expression:

In Visual C# Workflow project there is a difference based on the edition of Visual Studio you are using. If it is .Net Framework 4 then you have to use Visual Basic syntax and if it is .Net Framework 4.5 you can use C# language in the expression:


Random posts:
Help me, help you. You know how ;-) (click, click, click...) Or buy anything at Amazon. You get the same price, and I get a little bit of money. Follow the Photospots site on Facebook

Thursday, 10 January 2013

Change expression language in Workflow Foundation 4.5

In Workflow Foundation 4.5 in the .Net Framework 4.5 it is possible to use C# as your expression lanugage, but how do you change it for a workflow that has been upgraded from .Net Framework 4.0?

There are two ways. One is to create a new workflow in your project (this assumes that your project is based on the C# project template) and copy the shapes/recreate over to the new workflow and afterwards you have to change each expression to the C# language.

Another option is to open the file in XML mode and add the following attribute to the root element: sap2010:ExpressionActivityEditor.ExpressionActivityEditor="C#".

You still have to go into each expression to change from C# to Visual Basic code. You don't even get any compiler errors. It would be nice if this were better in the next version, but most likely not.

Random posts:
Help me, help you. You know how ;-) (click, click, click...) Or buy anything at Amazon. You get the same price, and I get a little bit of money. Follow the Photospots site on Facebook

Wednesday, 9 January 2013

Use the BizTalk 2010 mapper in Visual Studio 2012 Workflow Foundations

With BizTalk Server 2010 the mapper got updated to a new version and one of the features was the possibility to use the mapper in Workflow Foundation. What happens if you try to use the mapper in Visual Studio 2012?

In Visual Studio 2012 there are some really nice new features for Workflow Foundation like annotations, C# in expressions and a lot more. Coming from a BizTalk world you might want to use the BizTalk mapper to map between two different types and now that it also is an activity the logical choice would try to use the BizTalk mapper in Workflows. This will most likely be fixed in BizTalk Server 2013, but then you have to wait for that upgrade and you might not want to upgrade your BizTalk just because you use a newer version of Workflow Foundation.

First part is to add the activity to the toolbox. It isn't available just be choose items like you normally would, but if you browse the GAC you should find a DLL called Microsoft.ServiceModel.Channels.MapperActivy.

You can now add it to your Workflow, but when you click the BizTalkMapClass you get the following error:

Now to the workaround. Use Visual Studio 2010 to create a simple project where you use the mapper with the same input and output parameters and create the map you need. This should create a folder with the schema files, map file and a C# file. This folder you need to include in your Visual Studio 2012 project.

If you like you can change the namespace in the C# class file. Next you need to edit your Workflow in XAML mode (view code) and find the activity. Here you will find an attribute BizTalkMapClass and change that to the namespace and class in the C# from the Visual Studio 2010 folder:

<mscm:Mapper x:TypeArguments="x:String, x:String" BizTalkMapClass="HelpForUsingBizTalkMapperInVS2012.MapString"

The last thing you need is to create a reference to the assembly Microsoft.XLANGs.BaseTypes which are located at "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\Microsoft.XLANGs.BaseTypes.dll".

You project is now ready to go and should compile and run without any problems.

If you look closer at the items in the map created folder you will see that runtime it is actually only the C# code that is used. It contains the method to serialize the objects to XML and it contains the XSLT from the map. The map and the schemas are just there so that you can use the mapper in design time.

Random posts:
Help me, help you. You know how ;-) (click, click, click...) Or buy anything at Amazon. You get the same price, and I get a little bit of money.

Tuesday, 8 January 2013

Workflow foundation annotations and upgrade problems

One of the cool new features of the Workflow Foundation in the .Net framework 4.5 is the annotations. This gives you the option to at nice comments to your workflows.

In the designer you just have to right click your activity and choose the annotations menu item to add, edit or delete annotations.

If you upgrade your Visual Studio project from Visual Studio 2010 you can't see these menu options. The problem is that the upgrade wizard doesn't change the target framework, so if you go into properties window of your project and change the Target framework to .Net Framework 4.5 or newer, then you will have the option to add annotations to your workflow.
Random posts:
Help me, help you. You know how ;-) (click, click, click...) Or buy anything at Amazon. You get the same price, and I get a little bit of money.

Thursday, 3 January 2013

Simple autogenerated facade WCF service with T4

If you don't want to use a lot of money on service virtualization tools you can create a simple autogenerated WCF facade service that does a little bit of the things the big service virtualization tools does.

This gives you the option to hide service between one common service. The services behind this service could be a service from your backend system, a service from your CRM system and it might even be some external services.

You could do it manually, but then you would have to update it each time one of the backend services changes and with the human factor as an error source. Visual Studio gives you the option to use text templates which can be used to generate code.

Start by creating a WCF Service Application in Visual Studio and add a text template to this project, which will give you a *.tt file. This is the file that you will edit to create the autogenerated code. You might want to read a bit about it at MSDN before reading on. Here is the link.

Working with tt files is like going back in time. Back to the time with ASP and where you don't have intellisense. I stongly recommend to use Visual Studio 2012 that at least gives you a good debug option.

The first part of the tt file is the part where you specify which .Net namespace you want to use. The tt files knows nothing about the references that you have in your project, which I found out the hard way. My initial thoughts were to use reflection to get information about the services that I was going to work with, but I got into problems when I wanted to work with service references. So I ended up using the EnvDTE namespace, where you work with the FileCodeModel in Visual Studio. So this gives me this first part of the tt file:

<#@ template debug="true" hostspecific="true" #>
<#@ output extension="cs" #>
<#@ assembly name="EnvDTE" #>
<#@ assembly name="System.Xml" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Collections.Generic" #>

I wanted to control which services got autogenerated in an XML file, so I at a *.mapping file to the solution where I created a structure with the name of the service I wanted.

Based on this I could load the FileCodeModel and find the CodeFunctions that needed to be exposed.

 <#   
    
 EnvDTE.DTE dte = GetEnvDTE();
 string myFile = this.Host.ResolvePath("AutoGeneratedFacade.Mapping");
 XmlDocument xdoc = new XmlDocument();
 xdoc.Load(myFile);
 foreach (XmlNode node in xdoc.SelectNodes(@"//class/name"))
 {
      string sourceFileName = node.InnerText;
      sourceFileName = @"Service References\" + sourceFileName + @"\Reference.cs";
      ProjectItem enumProjectItem = dte.Solution.FindProjectItem(sourceFileName);
      FileCodeModel codeModel = enumProjectItem.FileCodeModel;

      CodeNamespace codeNamespace = FindNamespace(codeModel.CodeElements);
      CodeInterface codeInterface = FindInterface(codeModel.CodeElements);
      List<CodeFunction> codeFunctions = FindMethods(codeInterface.Children);
 #>

In the above code there are a couple of utility functions:

<#+
    
    private CodeNamespace FindNamespace(CodeElements elements)
     {
         foreach (CodeElement element in elements)
         {
             CodeNamespace ns = element as CodeNamespace;
        
            if (ns != null)
                 return ns;
         }
    
        return null;
     }
    
    private CodeInterface FindInterface(CodeElements elements)
     {
         foreach (CodeElement element in elements)
         {
             CodeInterface codeInterface = element as CodeInterface;
        
            if (codeInterface != null)
                 return codeInterface;
    
            codeInterface = FindInterface(element.Children);
    
            if (codeInterface != null)
                 return codeInterface;
         }
    
        return null;
     }
    
    private List<CodeFunction> FindMethods(CodeElements elements)
     {
         List<CodeFunction> methods = new List<CodeFunction>();
        
        foreach (CodeElement element in elements)
         {
             CodeFunction method = element as CodeFunction;
        
            if (method != null)
                 methods.Add(method);           
        }
    
        return methods;
     }
    
    private EnvDTE.DTE GetEnvDTE()
     {
         IServiceProvider hostServiceProvider = (IServiceProvider)Host;
        
        if (hostServiceProvider == null)
                throw new Exception("Host property returned unexpected value (null)");
        
        EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
        
        if (dte == null)
                throw new Exception("Unable to retrieve EnvDTE.DTE");
    
        return dte;
     }
 #>

With the CodeFunctions in hand I am now able to create the new interface and class implementation for the autogenerated WCF facade service:

<#+
private void WriteInterface(CodeFunction method)
{
    foreach(CodeElement element in method.Attributes)
    {
         string at = "";
         CodeAttribute att = element as CodeAttribute;
        
         if (att != null)
         {
              at = at + "[";
              at = at + att.Name;
              at = at + "(";
              at = at + att.Value;
              at = at + ")]";
              WriteLine(at);
         }
    }
        
    Write(method.Type.AsString);
    Write(" ");
    Write(method.Name);
    Write("(");
    string sparameter = "";        
    foreach(CodeElement element in method.Parameters)
    {
        int count = 0;           
        CodeParameter parameter = element as CodeParameter;
        
        if (parameter != null)
        {
            sparameter =sparameter + parameter.Type.AsString + " ";
            sparameter = sparameter + parameter.Name;
                
            if(count < method.Parameters.Count)
                sparameter = sparameter + ", ";
                
            count++;
        }
    }
    sparameter = sparameter.Substring(0,sparameter.Length -2);
    Write(sparameter);
    Write(");");
}
#>

And with the interface I am able to create the class the implements the interface:

<#+
private void WriteServiceClass(CodeFunction method, string servicename)
{
     Write("public ");
     Write(method.Type.AsString);
     Write(" ");
     Write(method.Name);
     Write("(");
     string sparameter = "";
     string sparameternames = "";        
     foreach(CodeElement element in method.Parameters)
     {
         int count = 0;           
         CodeParameter parameter = element as CodeParameter;
        
         if (parameter != null)
         {
             sparameter =sparameter + parameter.Type.AsString + " ";
             sparameter = sparameter + parameter.Name;
             sparameternames = sparameternames + parameter.Name;
             if(count < method.Parameters.Count)
             {
                 sparameter = sparameter + ", ";
                 sparameternames = sparameternames + ", ";
              }  
              count++;
         }
     }
     sparameter = sparameter.Substring(0,sparameter.Length -2);
     Write(sparameter);
     Write(")");
     WriteLine(String.Empty);
     WriteLine("{");
     PushIndent("        ");
     Write("FacadeService.");
     Write(servicename);
     Write(".");
     Write(servicename);
     Write("Client service = new FacadeService.");
     Write(servicename);
     Write(".");
     Write(servicename);
     Write("Client();");
     WriteLine(String.Empty);
     Write("return service.");
     Write(method.Name);
     sparameternames = sparameternames.Substring(0,sparameternames.Length -2);
     Write("(");
     Write(sparameternames);
     Write(");");
     WriteLine(String.Empty);
     ClearIndent();
     PushIndent("        ");
    WriteLine("}")  
}
#>

The final piece is to change the SVC file to point to the autogenerated class with changes to the Service and Codebehind attributes.

I used this article as inspiration and borrowed some lines of code from it.

With this I just have to update the service proxy and save the tt file to update my facade service and I don't have to write copy paste code.

Random posts:
Help me, help you. You know how ;-) (click, click, click...)