Sitecore Upgrade Assist Visual Studio Extension

Intro

After upgrading multiple Sitecore solutions, I noticed there are whole a lot of awfully slow tasks that can be automate. Hence, Sitecore Upgrade Assist is created to simplify important tasks including:

  1. Upgrading .NetFramework to the one matching the new Sitecore version
  2. Upgrade Nuget packages to match the new .NetFramework and Sitecore.
  3. Upgrade Sitecore packages.
  4. Upgrade GlassMapper.

The above tasks took me long hours to complete as I had to first discover what version of the Nuget package matches Sitecore and secondly go through each package one by one and upgrade them. I don’t think anyone should go through that pain again. Sitecore Upgrade Assist is an open source Visual Studio Extension for a better Sitecore upgrade experience.

Download the tool from Visual Studio Market place or check out the code on Github.

Sitecore Upgrade Assist Visual Studio Extension

The Sitecore Upgrade Assist is a toolbox every developer needs to upgrade a Sitecore solution. For starter, it consolidates all the Nuget package required for a Sitecore Version in a modifiable xml file.

Config File

This config file is what I have used to upgrade a Sitecore solution to version 9.3.0 and can be extended to update any common packages specific to your solution. These config files are stored in Visual Studio Extension folder for now and in Later versions, I will move them to a more accessible location.

 

Upgrade Framework

This feature is originally provided by TargetFrameworkMigrator and it is the first step for a Sitecore upgrade. To use this feature simply select all projects and click on Upgrade Framework. Note that the projects will not be automatically saved after upgrade. You should save all and build the project after this step. If everything is good and the build is successful, commit changes and move on the next step.

Package Upgrade

This feature uses NuGet.VisualStudio to upgrade all the necessary Nuget packages including Sitecore, Microsoft and other dependencies. It will first get the list of installed packages within the selected projects, check if the config file has specified a new version for the package ID and then install the given version. If the package does not have an equivalent within the config file, it will reinstall the same version for the new .NetFramework.

Microsoft packages

Since most of the Sitecore packages depend on MS packages, the tool starts first with them. Note that for this step, you must have a Nuget source named nuget.org in your solution and it must be enabled. Additionally, the installation is done with ignore dependency option to speedup the process and avoid conflicts.

Sitecore packages

After upgrading the MS packages, the tool moves on to upgrading Sitecore Nuget packages. They are detected by their prefix. Every package starting with Sitecore. will be considered and the corresponding version is set in SitecorePkgVersion node within the config file.

The package source used for Sitecore packages should be named Sitecore or Sitecore V2 and be enabled.

The tool is smart enough to understand that Sitecore packages before 9.1.0 had .NoReference suffix added to them. It will remove that package and install the equivalent for the new version.

Other dependencies

The final step for this feature is to upgrade all other packages except GlassMapper. This is where dependencies like Newtonsoft.Json, xunit, or System.xx are upgraded. Additionally, if you add any of your custom packages to the config file, it will be also updated here.

Once you have executed this feature on all your projects, you should certainly clean and rebuild the solution. This is where all the incompatible code surface and you will be spending a lot of time resolving those. This tool thrives to provide more assistance for this step.

Notes for upgrading packages

Glass Upgrade

The final step is to upgrade Glass Mapper if you are using it. I have separated this step as it can raise several errors during the build specially if you are upgrading from v4 to v5. For this step, the tool will prompt for the current package version. The version is what you see in the glass package id as highlighted in the screenshot below.

If there is no version within the package id, select the first combobox option “Empty” and press ok.

The tool will use the selected version ID to identify and match the glass version and install the right package.

Results

Future Features

Call for collaboration

I have made the tool accessible in github and It would be great if you guys could help out for the development and adding more features. Any suggestions and feedbacks are also welcome. May the force be with you during the upgrade.

Sitecore Upgrade – WFFM to Experience Forms

Intro

Sitecore Webform for Marketers (WFFM) has always been on the dark side of the CMS and maybe a nightmare during a Sitecore upgrade. Many developers avoided it as they find the entire approach redundant and they rather create the form from scratch and benefit the freedom that comes with it. On the other hand were the developers who have mastered the workflow and started creating forms seamlessly. They made the client happy with their short estimations and highly configurable solutions. Marketers also loved the fact that they could modify the form on their own. They also learned to deal with the technical limitation. During this never-ending dispute, Sitecore came in and render the entire thing obsolete and called it off from Sitecore 9.1. Isn’t it perfect? It was supposed to end the debate but instead it promoted us to the debate A league.

The Challenge

To put it short, New Sitecore form is nothing like WFFM and Sitecore has absolutely no migration guide.  All the WFFM forms should be converted into the equivalent version in Forms. Some kind hearted people have developed a tool to speed up the manual migration process which basically involves looking at the old form in one monitor and creating a new Forms in the other (that is only if you have two monitors, otherwise alt+tab is the way to go). Sitecore support does not recommend using the tool as if anything goes wrong during the migration, it will make theirs and your life difficult to figure what went wrong. We have used the tool and I can say it works for Simple forms using Simple field types. However, if you have custom field types and done some tricks in WFFM, this will not work.

The more sophisticated your WFFM forms are, the more complicated will be the migration process. All the custom fields and Save Actions must be converted to the equivalent one in Forms. This is not limited to customization but some of the OOTB WFFM Save Actions are also not shipped with Sitecore Forms and will never be. The image below illustrates the gap.

Field validations, parametrized save actions, form parameters, and all the other missing equivalent functionalities makes the form conversion the biggest challenge of a Sitecore upgrade.

How to estimate the effort?

If the content editor team are expert WFFM form designers and they create forms dynamically, this is great. Dev team can leave the job to them to recreate the forms and all you must do is analyze what they have been using so far and provide them a guideline on how to do the same on xForms.

You might think, the new forms save action is just a new class where you can copy the old save action code into and get the same logic working. The truth is many approaches that was used in the save action is no more supported in the new form save actions. For example, in the old forms, you could make the field names dynamic and pass the name through the save action configuration as described in this article. However, in Sitecore Experience Forms, it is not as easily available. For Forms, you must create Action Editor Item which has much higher abilities but not as easily available. Moreover, default values or prefilled forms are also not available out of the box but Sitecore has been kind enough to provide a good documentation for it. Look out for these pitfalls while estimating the upgrades effort.

Don’t forget the validations and Field types. Those too could be quite different to migrate and custom validations or fields must be estimated.

Summary

Sitecore Forms is the result of years of experience and feedbacks from WFFM users. I am very happy to see the end of WFFM as it was not made specifically for developers nor for the content editors. Now, xForms has the good distinction between developer’s workspace and the content editors. Despite all that the question remains; “Should we go with xForms or go custom?”

Sitecore Upgrade – a horrific torture or a god blessing?!

Intro 

If you are looking for a quick answer for the article title you are either a manager or in a wrong place. This article is set to help you understand what a Sitecore upgrade looks like, why should you do it, and how to go about it. If you are still reading; I suggest you grab a beverage and read this with an open mind. 

Why should you (or not) upgrade? 

The list below is not exhaustive, but it’s ordered in the most important reasons first   

If you are there, means you have not chosen the right version of Sitecore. Sitecore just like any other software product has good and bad releases and you should be able to tell that by the number of patches you have been given. Sitecore patches are developed by Sitecore Support engineers and released to you with absolutely 0 QA time (hotfixes are not patches and they go through a full cycle). So, don’t be surprised if they break on production. if you see most of the bugs in your solution is fixed in the new release, just go for it. 

As you may already know, Sitecore exits the main stream support 3 years after the version release date. That basically means you will have no more support for development. You might say “I am not developing anymore” but if you do, you might have to plan a big budget way  before the due date. 

If you are having releases every now and then, shipping new features constantly, you might want to spare a sprint only for Sitecore upgrade. This will keep your stack up to date and your team happy. In short; it will pay off in long term. 

Say you have a website which have been developed a few years ago and now you wish to extend/enhance it. An upgrade makes sense here for two reasons. One: you will not enter Sitecore extended support phase and two your team will get a better understanding of the solution before starting to add into it. 

Yes, you need the new feature and you want it as soon as possible. I think you should do it but bear in mind that every new feature can be buggy or not exactly meet your expectations. 

What are the upgrade methods? 

Sitecore officially has two upgrade methods: 

  1. Sitecore Upgrade wizard 

If you are the unluckiest person in this small world, this option is for you my poor friend. You should go with this method if you can’t really delete your old environment and create new one. It could be because you don’t have proper CI Stack, and everything would be ruined if you delete the existing environment; or you have been horribly modifying items in your productions without serializing the changes (shame). During my years of experience with Sitecore, I have seen so many unfinished upgrades and guzilian number of Godzilla bugs that appeared after such an upgrade. Of course, Sitecore has Improved the wizard through years but still there are many reasons that some items might not get updated and when that happens, any issues arises from that unfortunate incident can’t be easily identified. 

  1. Destroy and start fresh. 

This is probably the easiest and the safest way of doing a Sitecore upgraded. In this method, you delete your old environment (including databases, Site IIS settings, Files, etc) and spin up a fresh Sitecore instance with the target Sitecore version. Later you will deploy the upgraded version of your solution + the content on top of this fresh new environment. 

What to expect from a Sitecore Upgrade? 

Sitecore upgrade might or might not bring benefit to your solution. Firstly, your intention for an upgrade must be justified. If you possess an old solution which works perfectly but you want to make it better, you are right. Upgrade is the best way to keep a working solution in the train of helping your businessOf course, the task will introduce new bugs and there will be hiccups after the go live, but if you look at the big picture, it will pay off in the long run. Your now working solution will be tomorrow’s worst nightmare should you leave it untouched for years. Technology grows too fast and if you miss the train, there will be penalties to pay. To name some, it’s hard to find developers who are willing to work with an old technology. Your service provider will stop supporting your dinosaur website, and finally there might be a dangerous security hole discovered in your infrastructure that might bring your online business to a full halt or worst. 

On the other hand, if your business needs have changed over the years and the vision is no more matches the website initial design, upgrade might not be the best way to go. It is important to know new business logics should not be added to an upgrade scope. No new feature should be built or even an alteration in the logic can raise the complexity of an already complex process. The deprecation of old Sitecore APIs or other dependencies (such as glassmapper) might requires major refactoring in the code. The cost and effort associated with such change might even exceed brand-new solution. A Sitecore audit with a team of experts can shade some light on it. 

Where to Start? 

Sitecore upgrade involves lots of different activity. The first and the most annoying part is to upgrade the Sitecore nuget packages and all the dependencies to what matches your solution as well as Sitecore dllsThis is not an easy task as not all the required assemblies and their versions are written somewhere (as far as I know). Your best chance is to decompile Sitecore.kernel.dll to find most of the compatible references. You may use a higher version of the references, but it might introduce other issues and hard to find runtime errors. 

Once you have upgraded all the packages, you need to press ctr+shift+b and sit tight and brace yourself for the impact 😊. When you build the solution, you will realize how incompatible your solution is with the new references. This is probably the longest task of the process and after a few weeks of hard work you can only build the solution just to find out all your unit tests have stopped working and FakeDb is no more supported. That’s the real fun pat if you know what I mean. 

Building the solution is not the end. Once the solution is published, you will realize some great developers have thought, it is a great idea to write most of the business logic in a view where you don’t get proper build error. You will constantly visit the lovely YSOD until you finally load the home page. There, you deserve a cold beer. The hard part is over and now you can rely on your QAs (hopefully) to list out all the component that are not working anymore. 

Once all this is over, the final step will be content migration. This is where you might invest in a tool such as Sitecore Razl (formerly known as hedgehog Razl) to move content between the two databases or rely on the good old Sitecore packaging to bring the content over. If your media items are stored in DB, Sitecore package manager will not work perfectly as the Package size can get really large. Otherwise, moving items can be easily done using Sitecore package. Of course, there are some twitching to be done in order to speed up the package installation but need to be careful not to miss anything behind. 

What could go wrong? 

It’s mostly depends on the quality of the legacy solution. If it is well written and it is free of bugs, you can be sure that the new carefully upgraded code will perform just as good (regardless, a full QA cycle is recommended). However, garbage in equals garbage out. A Sitecore upgrade can coincide with technical consolidation. Means, with little more investment in the task, you can hire the right person who can revamp the code during the upgrade. It is worth noting that, such a change might introduce new bugs and loads of broken unit tests that should also be taken into consideration when estimating QA and developer effort. 

Conclusion 

A Sitecore upgrade will be a good investment should you make an informed decision. Latest Sitecore version does not necessarily means a more stable solution but it is certainly a step toward success. 

What Sitecore Helix Doesn’t tell you!

Sitecore Helix is there for a good reason. It tells you how to organize stuff such that it looks smart and it’s maintainable. You can see the sample implementation in Sitecore Habitat but you might miss a few things that I would like to emphasize here.

You will have a Taxonomy Foundation Project – Regardless!!!

If you like to be cool and all, you say, each feature should be Atomic and therefore holds it’s Templates, Modules, Logic, etc . Yes! right! Brilliant! But then Search happens. Take this scenario. You have a feature called Articles which obviously does lot’s of things and then client wants to make those Articles searchable. These are two different features and you don’t want to write Search related code in your Articles feature. Search needs access to your article Templates and if you are smart enough you are keeping your queries in the Foundation level. Since Foundation level shouldn’t reach out to Features, you have to relocate your templates down to Foundation where multiple features and/or foundation modules can access it.  Taxonomy project is the grave yard of atomic Features and the idea of reusable component. It’s ugly but can’t be avoided. If you have a work around this, buzz me.

Have one Item repository and STICK TO IT.

Ideally, in your Foundation Level you should have ItemRepository, DictionaryRepository, LogRepository, and Caching. These all are the single point of access to Sitecore. Your features should only use these foundation Modules to get Datasources, Items, Settings, and basically every data you need from DB. Having these classes centralized simplifies your life in the future. The best example that supports this approach is changes in Glass Maper. The new Glass Mapper (Sitecore 9.2+) uses IMVCContext and IRequestContext instead of ISitecoreContext. When you upgrade your solution to a new Sitecore, you will have to refactor only one place and that is the ItemRepository and no other feature needs refactoring (Voila). Additionally, your unit testing will be much easier.

DI could be simpler

If you wan to use Sitecore DI, you should create a config file or a class to register each service. This just doesn’t make sense to have extra class or extra files in every single project. Create a foundation class that is in charge of automatic registration of  all the services. Sitecore habitat has the right code.

Small but Important Tips

Sitecore Experience Forms Walk-through

With Sitecore 9.0 we have the release of the brand new Experience Forms which is quite different from good old Web Form for Marketers. I had a hands-on experience with this module and performed some investigation on its architecture. The video is a recording of the briefing session I conducted with my team members. Hope you find it useful as well.

Pre-requisites:

Key takeaways

WFFM and Long history of javascript issues

If you have ever used WFFM on your page, you know that it has its own set of scripts. The way these script injected to the page has evolved which confuses a lot of front-end developer whether they are upgrading their instance or developing new pages. In this article we are going to take a look at the journey WFFM went through (scripts only) Since Sitecore 7.2 to the latest release 8.2 and also discuss the common bugs faced with each version. The focus is on MVC pages which are widely used and has more known issues.

WFFM v2.4 rev.151103 and Sitecore 7.1 – 7.2

This version assembles RequireJS. The implementation is quite buggy and troublesome. Below are is some of the known bugs of this version.

Bug ID = #80478

Description: WFFM does not work with other JavaScript libraries which use define() function. Some JS libraries that use this function are Slick.js, jquery.cookie.js, and bodyBottom.min.js. error message is something like “Error: Mismatched anonymous define() module:”

This error can also cause misbehavior in page/experience editor. After adding a MVC form, page/experience editor will stop working.

Workaround : request Sitecore for a patch.

Resolution: Fixed in WFFM 8.1 Update 2

fixes include a number of JavaScript errors that appeared in multiple internet browsers and also a number of JS files that have been reviewed to ensure consistency. (80478, 78916, 82721, 85115, 83997)


Bug ID = (unknown)

Description: RequireJS is attached to global scope and does not let you add your own scripts to the page using this library.

Workaround: https://community.sitecore.net/developers/f/10/t/2050

WFFM 8.0 rev. 141217 (Update-1)

Since this release, requiredJS has been excluded from the module.

 
window.$scw = jQuery.noConflict(true);  

line is added to ~\Website\Views\Form\Index.cshtml so there should be no more conflict issue with your website jQuery

WFFM 8.1 rev. 151008 (initial release)

RequireJS is now back again without much improvement from the previous implementation in WFFM v2.4

In this version again there is no sign of jQuery.noConflict in WFFM implementation. So there should be conflict issue with your site specific jQuery library.

 

WFFM 8.1 rev. 160523 (Update 3)

Appearance of the following setting. This setting determins if bootstrap.min.css should be added to WFFM form rendering or not.

<setting name=”WFM.EnableBootstrapCssRendering” value=”false” />

$.noConflict(); is added to main.js file so there should be no issues with having two jQuery on a page.

 

There have not been much changes related to Javascripts in WFFM since 8.1 Update 3 release

DevCon 8 – MS Excel Beyond Formulas and Macros

Microsoft excel is a powerful tool used by billions of people around the word, programmer as well. Power users are able to perform arithmetic operations using macros and formulas. However, excel has a hidden gem that opens a new paradise for programmers. The ability to modify excel sheets using Visual Basic for Application (VBA) directly from Excel interface. In this post, I am going to share my experience using this tool with you all,

Enabling Developer Tab

  1. Click the File tab.
  2. Click Options.
  3. Click Customize Ribbon.
  4. Under Customize the Ribbon and under Main Tabs, select the Developer check box.

Writing the First Function

  1. Navigate to Developer tab and click on Visual Basic logo
  2. Right click on Microsoft Excel Objects folder in the left tree and navigate to Insert -> Module
  3. This is the playground, let’s write some hello word code. Copy past the following code to your module.
Public Sub HelloWorld()
    Columns("E:E").ColumnWidth = 65.29
    Rows("8:8").RowHeight = 210
    Range("E8").Select
    With Selection
        .FormulaR1C1 = "Hello World"
        .HorizontalAlignment = xlGeneral
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
        .VerticalAlignment = xlCenter
        .Font.Size = 70
    End With
    With Selection.Borders(xlEdgeTop)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
    With Selection.Borders(xlEdgeBottom)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
    Selection.Borders(xlInsideVertical).LineStyle = xlNone
    Selection.Borders(xlInsideHorizontal).LineStyle = xlNone
    ActiveWindow.DisplayGridlines = False
    Range("A1").Select
End Sub
  1. Now Press the run button or press F5 to execute the code

The beauty of VBA is that it does not require any explanation. It’s pretty self-explanatory and if you have programming background, you should be able to read and understand it. By coming this far, you already have what you need to start programming your excel sheet. Below is some of the techniques that I learned during my time working with excel that you might find it useful as well.

Macro is your best friend

When you record a Macro, Basically Excel will follow your every move and logs it as a VBA script. This is very useful when you are looking for a code to perform a certain action. For example, you want to create a pivot table and assign it a data source. Googling it will not help you much since there are very limited resources out there. So all you have to do is to perform the operation using Microsoft Excel UI while recording a Macro. After stopping the Macro, you can find the related code in the Excel Code editor (new module is automatically created for a new Macro).

Excel Objects

Basically, there are two types of objects in Excel

VBA Objects

VBA objects are built in the application and can be created using Dim and/or Set keyword. These objects consists of Event, Method, and property. To find out the full list of available objects press F2 in Visual Basic Editor. Here is a sample code and some of the useful objects that you can use.

 Dim wk As W&lt;code&gt;rkbook

Set wk = Workbooks.Open "C:\Docs\Accounts.xlsx"

wk.SaveAs "C:\Docs\Accounts_Archived.xlsx"


Dim collFruit As New Collection

' Add item to the collection

collFruit.Add "Apple"


Dim a As Worksheet

Set a = ActiveWorkbook.ActiveSheet

a.Cells(2, 2) = "Some text"

Note: You can use the Set keyword solely (without using dim to define the object). Despite the technical differences between two method, the biggest drawback of using Set alone is that you won’t be getting any intellisense since object type is unknown to the code editor.

You also can subscribe to an Object event by writing a procedures like the one below:

 Private Sub Worksheet_Activate()

MsgBox "Sheet1 has been activated."

End Sub 

COM objects

These object are not Excel native and derived from other applications. These include the Dictionary, Database objects, Outlook VBA objects, Word VBA objects and so on.

Set dict_Month = CreateObject("scripting.dictionary")
If Not dict_Month.exists(.Cells(i, 1).Value) Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dict_Month.Add .Cells(i, 1).Value, CreateObject("scripting.dictionary")
End If
 

Connecting to an Access database:

 Public Function RunQuery(ByVal strDBPath As String, _
                     ByVal strQueryName As String, _
                     Optional ByVal execOption As Integer = 4, _
                     Optional ByRef rowAffected As Long = 0, _
                     Optional ByVal showError As Boolean = True _
                     ) As Object
    Dim objCmd As Object
    Dim objRec As Object
    Dim varArgs() As Variant
    Set objCmd = CreateObject("ADODB.Command")
    With objCmd
        On Error Resume Next
        .ActiveConnection = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                             "Data Source=" & strDBPath & ";" & _
                             "Jet OLEDB:Engine Type=5;" & _
                             "Jet OLEDB:Database Password=""" & DBPassword & """;" & _
                             "Persist Security Info=False;"
        .CommandText = strQueryName
        'If UBound(parArgs) = -1 Then
            Set objRec = .Execute(RecordsAffected:=rowAffected, Options:=execOption)
            If Err.Number <> 0 And showError Then
            'Display an error message to the user.
                MsgBox "Ooops. There was an error while generating report! Please contact administrator if the problem persists", vbCritical, "Generation Error"
                Sheets("start").Range("A30").Value = Err.Description
                Sheets("start").Range("A31").Value = strQueryName
                Err.Clear
            End If
    End With

    Set RunQuery = objRec

    Set objRec = Nothing
End Function

Global Object and Events

You have the option of having workbook-wide variable or set some variable values at workbook start up. All you need is a procedure with the event name in the ThisWorkbook object. For example to perform some warm up activity when the sheet opens:

Private Sub Workbook_Activate()
   Worksheets(1).Cells(1, 1).Value = "I am here:)"
End Sub 

Full list of events:

https://msdn.microsoft.com/en-us/library/microsoft.office.tools.excel.workbook_events.aspx

It is also possible to have Workbook wide variable using Global Key word

 Global Const aSheetName = "Detail Report" 

However, I would recommend having a hidden sheet where you set your constant values. This is useful to save memory and also have the value saved for next usage.

TFS and Excel – The programmer heaven

Another hidden treasure of Excel is its ability to connect to TFS. You are able to bulk insert your TFS items into the Server or download everything from server and use Excel tools to perform some Analysis. The full tutorial on this can be found from the link below:

https://www.visualstudio.com/en-us/docs/work/office/bulk-add-modify-work-items-excel

Materials

You may download the Slide from here: DevCon8 – MS Excel

Financial Management Excel Sheet can be downloaded from here: ExcelFinancialManagement_v1

DevCon #5 Presentation on Reveres Engineering

This post is regarding my Tech talk on  Reverse engineering and debugging .Net applications conducted on Herbalife Malaysia Office as part of DevCon event. DevCon is a monthly gathering of Microsoft enthusiast to deliver and discuss advanced programming knowledge. I participated as a speaker for DevCon #5 and here is a brief explanation of the topic.

There are many cases, that we have to work with third-party assemblies in our solutions. It is all cool until we run into a exceptions, bottleneck or some random message in the log file. Usually, the first thing comes to our mind as a developer is a bunch of swear world for the developer of the component and finally contacting their customer support with a baggage of complaints. However, this is not always the best option as support usually take a long time to investigate the scenario and we all have deadlines (who doesn’t?). Things could be even worse. They might find that issue was with you and not the component and they might as well use some swear words.  Therefore, if you wish to save yourself from embarrassment or make your complaint baggage heavier, you have to do some detective work yourself. In this session, we will walk through the reverse engineering tools and use them to sneak peek into .Net assemblies.

Here is the link to download my slides

Reverse engineering and debugging

 

And here is a recording of my presentation.

Part 2

Pine Tree

Intro

Pine Tree (still not sure why is it called that!) is located at Fraser Hills, approximately 2.5 hours drive north of Kuala Lumpur. The place is known for it’s amazing weather and beautiful nature.

Background

It’s been a while since we were aiming for this hike. During the raining season it’s mostly closed so we had to wait until February. The trip from KL was quite long. 100 KM is a long way but we couldn’t give up on this hike.

We encounter very limited number of hikers during the hike. Mostly random people hiking without proper gears, using flip-flop or “Kampung Adidas”.

The Trail

It is a Moderate-hard hike. The hike was supposed to be 7 to 8 hours according to the sign board at the start point. To me it looked more like a warning than an information board. I think many non-hikers take that path without having any prior understanding of what lays before them. However, we mange to get to the the first high ground in 2 hours and conquer the twin peak (second summit) in 2.5 hours. 1 hour rest and 2.5 hours coming back. It is worth noting that we did not take a break (excluding short water breaks) and maintain a steady pace through-out the journey (no bragging here ok?). This hike is unique in a way. It takes you almost same time to going back due to it’s unsteady up and downs.

Path was very muddy during our trip but no leeches (thanks god for that). It’s clear that it has been altered for non-professional hikers. Some rope and concrete stairs along the way. However, land slide seems to damage the work they have done. Close to the first peak, there is a part that we had to climb up an almost horizontal ground. There is a rope but have to be careful there. It is a bit tricky.

Interesting part is that after the first peak, there is a noticeable change in the vegetation. We can see different type of trees and the nature feels more virgin. That’s probably something I can look up, or if you know about it, please share with me in the comments.

The Good

The Bad

Is it good for camping?

There are no many camping spot along the way. Officially, camping is not allowed but the twin peak would be an ideal spot. There are no source of water nearby so bring enough with you.

Hike Statistics

Click on the hiker icon to see more details.

Sitecore WFFM – Add a User to a List

Web Form For Marketers is one of the many Sitecore modules. This one specifically aims non-tech people and helps them create web forms. This module is very power-full and also inherits Sitecore legacy of being”Extensible and configurable”. We can modify form appearance, input types, validations, submit actions, etc. WFFM is regularly used to add comment section to a post, create user sign up form, feedback and contact us forms or anything of that sort. One of it’s common use is to add a person to an email subscriber list. Fair enough. Good move.  However, Sitecore Developer or Marketers seems to be getting it wrong. Here is how it must be done.

Prerequisite

Let’s Get down to business

O’right. this is very straight forward.

and we are done!?

However

The mistake we all make is:

We assume “Add Contact to Contact List” will get the form data and put that user in the specified list

What it actually does is:

It will add the current analytic contact form Tracker.Current.Contact property to the specified list.

This will not work because lot’s of time the user is not identified. Therefore, Analytics does not have proper contact information to send an email to. Even though this feature has been requested from Sitecore, there is no ETA on when it is going to be available. Meanwhile, there are 3 ways to make this work

  1. Only let authorized users access the form – Not ideal from a marketer perspective.
  2. Make sure the user is identified before triggering “Add Contact to Contact List” action – Requires communication with Sitecore developers and error prone
  3. Create a Custom save action that identifies the contact + add the contact to the list – What we are gonna do

You might be asking yourself why not just add the user to the list without identifying it? And the answer is: Sitecore List Managers uses Analytics contact in the variety of places and for the variety of reasons. If you find a way around it, you might never know where things might go wrong. So my advice is to leave the back door alone and stick to the front door. It’s safer that way 🙂

How to do it?

1. Create the visual Studio project and past this code to the project (or just clone the project from the repository). Build the DLL and place it in your bin folder (e.i C:\inetpub\wwwroot\hostname\Website\bin )

2. Create the patch file like the one below. You may change the value for “emialFieldName” and “firstNameFieldName” parameters according to your corresponding form’s field name.

3.  Copy the new config file to your website include folder (e.i C:\inetpub\wwwroot\hostname\Website\App_Config\Include\Wheelbarrowex)

4. Login to your Sitecore instance as admin and  navigate to /sitecore/system/Modules/Web Forms for Marketers/Settings/Actions/Save Actions

5. Right Click on “Add Contact to Contact List” action and click on Duplicate and give it a name in the pop-up message

6. Change the value for Factory Object Name to “/sitecore/wffm/actions/identifyAndAddContactToList” under Data section so the action knows where are the configuration.

7. Change the value for Display name to “Identify and Add Contact to List” under Appearance section. This will change the name in the tree so we can easily find the action later on.

Note: Appearance section is not displayed by default. Check the Standard Fields checkbox under View tab to enable it.

WFFM_Save_Action

8. Now open form designer and assign your form a new action.

9. Select the list you wish to add contacts to.

10. Save the form

11. Smart Publish the site.

Things to consider