Content

I have been developing and delivering Sitefinity Solutions to large international companies for over 8 years, some of the previous projects I delivered was for Kapersky, Symantec, Alvarion, HP, Nuance, Cisco and other large companies. In fact the product I developed and delivered those previous projects on was last year recognized by Forrester.

I have also been creating and architecting software solutions for over 15 years, in the Travel Industry and Marketing Industry.

For the last 8 years I have been developing PRM Applications ( Partner Relationship Management ) and MOM Applications( Marketing Operations Management ) Platforms.

For those 2 applications I used my combined skills of Sitefinity and Konfigure platforms.

Some of my core professional specialities at the moment are ( Sitefinity - www.sitefinity.com , Sitecore - www.sitecore.net and Konfigure - www.konfigure.com )

Wednesday 28 May 2014

Visual Dynamic Module Builder for Sitefinity 7.0

Good Evening All.

I'm currently working on a plug in/tool for Sitefinity 7 that will allow you to visualize relationships of the Dynamic Modules, Taxonomy, News, Events and to interact with the properties of the same.  This tool will be ideal for Sitefinity 7 and above.  The tool will allow you to visualize and relate data across different areas of the system.

Currently there is no easy visualization of this, so when you have many Dynamic Modules, this tool comes to hand.

I decided to do this because when you work on projects of say 10 or more Dynamic Modules, unless you have done an ERD diagram is difficult to visualize where things are and how its related, not every company or project will give you the privilege to plan a good ERD, that is a fact.

The tool will show in real time all the relationships. The end goal is for a user to design it in an ERD environment and press a button to generate all the dynamic modules for you.

I'm looking forward to listening to some of your feedback, please use the link below to register for a beta version in a very near future.

Register for a Beta Version:

https://docs.google.com/forms/d/1qyZ7qXUZhHHFES23gwVugcuselJSui80_tc8sxCsel4/viewform?usp=send_form

Please note the picture attached is an early beta version of the software.


Saturday 24 May 2014

Setting Up Sitefinity 7 and Amazon RDS Instance ( SQL Server )

Recently I had the need to setup a new Sitefinity 7.0 Instance, but I decided to use the Amazon RDS, just so it could be more cost effective to the client. I must say I'm very happy with the results so far.  I'm quite sure there is a certain degree of caching at Amazon Level, because the results I'm having in delivering pages from Sitefinity are quite superb.

What is Amazon Relational Database Service

Amazon Relational Database Service or Amazon RDS is a distributed relational database service by Amazon.com. It is a web service running "in the cloud" and provides a relational database for use in applications. It is aimed at simplifying the set up, operation, and scaling a relational database. Complex administration processes like patching the database software, backing up databases and enabling point-in-time recovery are managed automatically. Scaling storage and compute resources can be performed by a single API call. Amazon RDS was first released on 22 October 2009 supporting MySQL databases. This was followed by Oracle Database in June 2011, Microsoft SQL Server in May 2012 and PostgreSQL in November 2013.

Assumptions
  1. I'm going to assume you have a WebServer EC2 already setup.
  2. I'm also going to assume that you have create and RDS Instance, in our case we are using the SQL Server engine.

The Setup I'm using its EC2 with RDS
  • So we have to create New RDS Instance
  • We have to Setup the relevant Firewall Settings, including opening the port 1433.

Now you will need to try the connection, to do this you connect to your database Instance EndPoint as you would normally connect to your Local DB but with the appropriate credentials, using the SQL Server management studio ( if you cannot connect make sure you have opened the port in the security group ).
  • Migrate The Data, With the SQLAzure Tool
So here is where things start to be different.  You cannot just do a restore of SQL Server database at this moment in time ( a bit of a shame ), however there is a tool called SQLAzureMW which works wonderfully.

So just follow the wizard to move data from Server A to the New RDS, the tool will move most or all the Data and Tables across nicely, if you you don't encounter any problem.  In our case we encountered a problem which I'm going to explain.

  • SF_CHUNKS PROBLEM
In my scenario I moved an existing website,  in our case the images were being stored in the DB, so this created a problem for me, as the sf_Chunks table failed to copy across, so it felt as if  there was a bit of data corruption.

So I devised a way to migrate the chunks From Server A to the New RDS, 
  • THE SOLUTION
The solution is devised into 2 parts.  Because we are working with 2 different SQL Enviroments you need to Setup a Linked Server, below is the code I used to create this
    • 1) SETUP LINKED SERVERS

SQL: Create Linked Servers

EXEC sp_addlinkedserver
@server = 'TempDB',
@srvproduct = '',
@provider = 'MSDASQL',
@provstr = 'DRIVER={SQL Server};SERVER=myinstance.us-east-1.rds.amazonaws.com;UID=myuser;PWD=mypassword;'

  • 2) CHUNKS_MIGRATION_SCRIPT
Now that we have created a Linked Server, this means from your local database you can query your remote database instance, it is at this point that you will be running this script below.

The way I managed to solve my problem was to move 1000 records at the time, so all you got to do is change the following line BETWEEN 1 AND 1000, so if you have 10000, I moved 1000 records at the time.

SQL: Chunk Migration
---------------------------------------------------------------------------------------------------------
SET NOCOUNT ON
DECLARE
    
        @RANDOM_GEN_NO        AS VARCHAR(50),
        @TEMP                                                AS VARCHAR(50),
        @sze    int ,
        @ordinal    int,
        @file_id    uniqueidentifier ,
        @dta    varbinary(max) ,
       @voa_version    smallint



DECLARE EMP_CURSOR CURSOR FOR

WITH sf_chunks AS
(
        SELECT sze,ordinal,file_id,dta,voa_version,
        ROW_NUMBER() OVER (ORDER BY sze) AS 'RowNumber'
        FROM HANCOCK_LIVE.dbo.sf_chunks
)


SELECTFROM sf_chunks WHERE RowNumber BETWEEN 10001 AND 10197;

OPEN EMP_CURSOR
FETCH NEXT FROM EMP_CURSOR
    INTO @sze,@ordinal,@file_id,@dta,@voa_version,@TEMP
WHILE (@@FETCH_STATUS = 0)
BEGIN
     
INSERT INTO [TempDB].[LIVEDB].[dbo].[sf_chunks]
                     ([sze]
                     ,[ordinal]
                     ,[file_id]
                     ,[dta]
                     ,[voa_version])
         VALUES
                     (
        
                 @sze
                 ,@ordinal
                 ,@file_id
                 ,@dta
                 ,@voa_version

             )

        FETCH NEXT FROM EMP_CURSOR
        INTO @sze,@ordinal,@file_id,@dta,@voa_version,@TEMP
END

CLOSE EMP_CURSOR
DEALLOCATE EMP_CURSOR

SET NOCOUNT OFF
---------------------------------------------------------------------------------------------------------
       

So far I'm very pleased with the end result, its fast and easy to backup, using the RDS tools, and comes across as a cost effective solution.

Saturday 10 May 2014

Sitefinity Forms - Add Data Encryption Facility

Data encryption is quite an important thing now a days for most companies and websites. Now and then you may need to encrypt certain data and be able to delivery it in a safe manner to the other end.

On this blog entry I'm going to explain what you need to do to be able to encrypt data when using Sitefinity Forms.

When I was looking at this area, the documentation on this was very limited.

Setup a Sitefinity Form

  1. Lets assume you know how to create a form and you have created your Sitefinity Form.  In my case, I have a simple form with 2 Fields; NAME and SURNAME.  One key element to take note at this stage is the [Developers code  name] for the form and fields.  So my form is called TEST, therefore the developers name is sf_test for the form, and the fields names are txtNAME are txtSURNAME.  
    1. I have used a TextBox field to store my data, please note that there are scenarios where you need limitations eg. max amount of characters, I used the TextBox limitations on the Form Field Properties. 

Setup Sitefinity To Encrypt Form Data

  1. Create New Class Called [ CustomFormsControl.cs ] with the code below

Code:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Telerik.Sitefinity.Configuration;
using Telerik.Sitefinity.Modules.Forms;
using Telerik.Sitefinity.Modules.Forms.Web.UI;
using Telerik.Sitefinity.Services;
using Telerik.Sitefinity.Web.Mail;
using Telerik.Sitefinity.Model;
using System.ComponentModel;
 

namespace SitefinityWebApp.Forms.CustomFormsControl
{
    public class CustomFormsControl : FormsControl
    { 
        protected override void InitializeControls(Telerik.Sitefinity.Web.UI.GenericContainer container)
        {
            base.InitializeControls(container);
            this.BeforeFormAction += new EventHandler<System.ComponentModel.CancelEventArgs>(CustomFormsControl_BeforeFormAction);
        }

        private void CustomFormsControl_BeforeFormAction(object sender, CancelEventArgs e)
        {

            try
            {
                if (FormData.Name == "sf_test")
                {
                    FormsManager manager = FormsManager.GetManager();

                    var formResponse = manager.GetFormEntries(FormData).Where(fE => fE.ReferralCode == FormData.FormEntriesSeed.ToString()).SingleOrDefault();

                    if (formResponse.GetValue<string>("txtNAME") != null)
                    {
                        formResponse.SetValue("txtNAME", SitefinityWebApp.Crypto.EncryptStringAES(formResponse.GetValue<string>("txtNAME"), formResponse.Id.ToString()));
                    }
                    
                    
      if (formResponse.GetValue<string>("txtNAME") != null)
                          {
          formResponse.SetValue("txtNAME", SitefinityWebApp.Crypto.EncryptStringAES(formResponse.GetValue<string>("txtNAME"), formResponse.Id.ToString()));
                    }
 
                    manager.SaveChanges();

                    this.FormData.SubmitAction = Telerik.Sitefinity.Forms.Model.SubmitAction.PageRedirect;
                    this.FormData.RedirectPageUrl = Page.ResolveUrl("~/yourthankyoupage");
   
                }
                 


            }
            catch (Exception ex)
            {
                throw new Exception("Error" + ex.InnerException);
            }

         


        }
    }
}

So in the sample above our logic is very simple, we are checking if the form name is called sf_test and if it is then we will be getting our form data like so; formResponse.GetValue<string>("txtNAME") and then we are calling our encryption class Crypto, this will encrypt the Field Values to be saved into our Sitefinity.

Please note if you have a custom page and you wish to redirect the user to it, then you need to do the following:


this.FormData.SubmitAction = Telerik.Sitefinity.Forms.Model.SubmitAction.PageRedirect;
this.FormData.RedirectPageUrl = Page.ResolveUrl("~/yourthankyoupage");
   


2. Registering the custom Forms control

After the class being  implemented we have to substitute the built in one, with the custom one. To do this, go to Administration -> Settings -> Advanced -> Toolboxes -> PageControls ->  Sections -> ContentToolboxSection -> Tools -> FormsControl. There edit the Control CLR Type or Virtual Path property. Substitute the original value with the CLR Type of the custom control. Now, whenever a user adds the Forms control to pages the custom one will be used instead of the built-in one.

Setup Sitefinity To Decrypt Your Data

So now that we have created a Form, and we have encrypted the data, we will need to export it in a encrypted manned. The following steps are going to show you what you have to do to override the Export Button functionality in the form responses action with our own custom logic

  1. Override the Export Button 

    1. So you need to Create a Class called CustomExcelExporter  which you need to inherit from ExcelExporter.  Inside our Class the method we are using is ExportToStream on this method we are getting the instance of that form we are on  then we loop through all the responses one by one, as we are looping we are de-crypting the relevant fields back using our Crypto class.
    2. Please note you need to setup the relevant Override of the Export button by using the BootStrap like so inside theGlobal.asax
ObjectFactory.Container.RegisterType<IDataItemExporter, CustomExcelExporter>(new InjectionConstructor()); 

What to Setup in the Global.asax

Code:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using Telerik.Microsoft.Practices.Unity;
using Telerik.Sitefinity.Abstractions;
using Telerik.Sitefinity.Data.Utilities.Exporters;
using Telerik.Sitefinity.Modules.Forms;
using Telerik.Sitefinity.Model;
using Telerik.Sitefinity.Modules.Forms.Web.UI;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Web.Http;
using System.Web.Routing;

namespace SitefinityWebApp
{

    public class CustomExcelExporter : ExcelExporter
    {
        public override void ExportToStream(System.IO.Stream streamToExportTo, IEnumerable<Telerik.Sitefinity.Model.IDataItem> itemsToExport, System.Text.Encoding encoding)
        {
            FormsManager formsManager = FormsManager.GetManager();

            var form = formsManager.GetFormByName("sf_YOUR_FORM");
            var entries = formsManager.GetFormEntries(form).ToList();

            int intRowCounter = 0;

            foreach (var item in entries)
            {
   entries[intRowCounter].SetValue("YOUR_FIELD", SitefinityWebApp.Crypto.DecryptStringAES(item.GetValue<string>("YOUR_FIELD"), item.Id.ToString()));
               
                intRowCounter++;
            }


            base.ExportToStream(streamToExportTo, (IEnumerable<Telerik.Sitefinity.Model.IDataItem>)entries, encoding);
        }


    }

    public static class Crypto
    {       
        public static string EncryptString(string plainText, string sharedSecret)
        {           
      // YOUR LOGIC HERE

            return "";
        }
  
 public static string DecryptStringAES(string cipherText, string sharedSecret)
        {
             // YOUR LOGIC HERE

            return "";
        }

         
    }


    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            Bootstrapper.Initialized += Bootstrapper_Initialized;
        }

        void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
        {
            if (e.CommandName == "Bootstrapped")
            {
                ObjectFactory.Container.RegisterType<IDataItemExporter, CustomExcelExporter>(new InjectionConstructor()); 
            }
        }
 
    }
}


Setup Sitefinity To Export The Excel File Over SSL

Now that we can Encrypt and Decrypt information using the forms, the last touch to this functionality, which is optional,  we need to make sure the stream will go over SSL, to do this you need to do the following:

Administration > Back End Pages > Sitefinity->Content->Types of Content -> Forms -> FormResponses

On the FormResponses you will need to go to edit Title and Properties and you must enable SSL.

NOTES: Would like to thank your for the support team to help me to put this solution together.

EXTERNAL RESOURCES:

  1. http://www.sitefinity.com/blogs/radoslav-georgievs-blog/2011/12/23/how_to_implement_notifications_for_incoming_forms_responses

Joaquim Ferreira - Sitefinity 7 Developer

Joaquim Ferreira - Sitefinity 7 Developer
Joaquim Ferreira - Sitefinity 7 Developer

Joaquim Ferreira - Sitecore 8 Developer

Joaquim Ferreira - Sitecore 8 Developer
Joaquim Ferreira - Sitecore 8 Developer