Saturday, May 23, 2015

Sitecore Marketplace Module - Lang Item State Change Workflow Action

I have converted one of my earlier blog posts into Sitecore Marketplace module.

Marketplace Module Link :
https://marketplace.sitecore.net/en/Modules/L/Lang_Item_State_Change_Workflow_Action.aspx

This is a simple workflow action which can be used to take only defined language item to a defined workflow state.

Just installed this and Workflow action will be available in Templates/User Defined section
/sitecore/templates/User Defined/WorkflowAction/Lang Item State Change Action



This action can be added inside Workflow states to execute.




Hope this will be useful for someone!!

Monday, May 18, 2015

Importance of Case-sensitivity of hostName attribute of Sites config node

Today, we faced a strange issue, which questioned my knowledge of Site Definition configurations in Sitecore :-D

One of my colleague had a Sitecore instance with site definition had hostnames defined.

Ex:

<site name="website" hostname="abc.xxx.local" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" ... />


But, he had his IIS site defined with "xxx.local".

Even though hostname attribute is "abc.xxx.local", request to "xxx.local" works fine and match to the "website" site definition.

This made me confused as my knowledge said only request that should map to "website" site defition is request with same value as hostname attribute value.

I had a quick google search and found my thinking was correct.
https://sdn.sitecore.net/SDN5/Articles/Administration/Configuring%20Multiple%20Sites/Configuring%20Sites%20in%20web,-d-,config%20File.aspx

So, when Sitecore it self saying this, how is this not working accordingly is my next question.

Then, I found Jon West's following blog post about hostName setting, which explained the real issue with our setting.
https://www.sitecore.net/learn/blogs/technical-blogs/john-west-sitecore-blog/posts/2013/08/mapping-hostnames-to-sites-with-the-sitecore-aspnet-cms.aspx

Quote :
As a word of caution, in several cases I have seen where device resolution did not work as a developer expected, the issue was that their configuration used hostname (with a lowercase n in the attribute name) rather than hostName (with an uppercase N). Be sure to capitalize the N.

 After changing "hostname" to "hostName", everything started to work accordingly. :-)

Sunday, May 10, 2015

Languages.AutoRemoveItemData Setting - Sitecore Setting of the Day

While I'm looking through the web.config settings, I saw an interesting setting which took my mind to past.

Few months back, one of my previous workplace colleague told me that a trouble he went through while trying to delete an language in Sitecore. After he had deleted a language in Sitecore and looking into the items in content editor, item versions related to that language has also been deleted from Sitecore. They had to work hard to make everything Okay in the system.

The setting which remind me the above scenario is,

<!-- LANGUAGES AUTO REMOVE ITEM DATA
       Indicates if item data is automatically removed from a database when a language is deleted.
       Default value: true
-->
<setting name="Languages.AutoRemoveItemData" value="true" />


So, if you have set the above property to false, and then deleted the language, items will remain with Sitecore.

But, off-course, there should be steps taken to make this removal sensible, since there is no point of having items of Non-existing language :-D

Thursday, May 7, 2015

Weekly Blogging Challenge of our Team - Week 1

To grow our self together, our team has started a weekly blogging challenge.

So, following are the our come of first week. (I know these blog posts are not in expert level. But, I am sure our team will grow and provide more advance blogs in the future)


All about Sitecore Instance Manager (SIM 1.3) by Udara Rajarathna

How to access Sitecore Items and Languages using API by Prageeth Roshane (Sitecore Labs Blog)

How to setup WFFM module by Pasan Samarakoon (PS Solutions Blog)

Contact not adding to Contact List in Sitecore 8 update-2 and Ways to access Template builder by Chaturanga Ranatunga (Sitecore Footsteps Blog)

see you in our new Blogging challenge. :-)


Thursday, April 30, 2015

Ways to Access Template Builder

Requirement :
You need to change/edit the template of an item. So, to change the template, you need to access that related template and go to "Builder" tab of that template.

As an example, we will take "Home" item and try to access Template Builder for that item's template. i.e. /sitecore/templates/Sample/Sample Item


Option 1: Directly access Template section
















Option 2: Click on the item's Template field value link














Option 3: Click "Edit" button in "Configure" tab





Contact not adding to Contact Lists in Sitecore 8 Update-2

We faced another issue with our Sitecore 8 update-2 upgrade process.

This time, when a user submit a WFFM form, "Add contact to contact list" WFFM save action does not add the user to the relevant contact list.



Error 1:

When we submit the form from front-end, user was not added to the Contact List. Following error was in the error logs.

19576 13:25:26 ERROR Error during aggregation.
Exception: System.Data.SqlClient.SqlException
Message: T-SQL ERROR 242, SEVERITY 16, STATE 3, PROCEDURE (null), LINE 219, MESSAGE: The conversion of a datetime data type to a smalldatetime data type resulted in an out-of-range value.
Source: .Net SqlClient Data Provider
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Sitecore.Data.DataProviders.Sql.DataProviderTransaction.Dispose()
   at Sitecore.Analytics.Aggregation.SqlReportingStorageProvider.<>c__DisplayClass5.<Store>b__2()
   at Sitecore.Data.DataProviders.NullRetryer.ExecuteNoResult(Action action, Action recover)
   at Sitecore.Analytics.Aggregation.SqlReportingStorageProvider.Store(Guid id, AggregationDataSet data)
   at Sitecore.ExperienceAnalytics.Client.Platform.SwitchingReportingStorageProvider.Store(Guid id, AggregationDataSet data)
   at Sitecore.Analytics.Aggregation.InteractionAggregator.Aggregate(Byte[] recordKey, IAggregationContext context)
   at Sitecore.Analytics.Aggregation.Aggregator.Execute()

Solution 1:

So, we contacted sitecore support and they provide us with following fix. (ref: 434923)

* Add the highlighted lines to the /App_Config/Include/Sitecore.Analytics.Processing.Aggregation.config file:

             <!-- Facts -->             
            <SqlMappingEntity type="Sitecore.Analytics.Aggregation.SqlMappingEntity, Sitecore.Analytics.Sql">
              <Table>Fact_FormStatisticsByContact</Table>
              <Routine>Add_FormStatisticsByContact</Routine>
            </SqlMappingEntity>          
            <SqlMappingEntity type="Sitecore.Analytics.Aggregation.SqlMappingEntity, Sitecore.Analytics.Sql">
              <Table>Fact_Conversions</Table>
              <Routine>Add_Conversions</Routine>
            </SqlMappingEntity>
 
* Rebuild the reporting database

Error 2 :

After that fix, when submit the wffm form, we received following error on logs

1104 13:35:55 ERROR Error during aggregation.
Exception: System.Data.SqlClient.SqlException
Message: Could not find stored procedure 'Add_FormStatisticsByContact'.
Source: .Net SqlClient Data Provider
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Sitecore.Data.DataProviders.Sql.DataProviderTransaction.Dispose()
   at Sitecore.Analytics.Aggregation.SqlReportingStorageProvider.<>c__DisplayClass5.<Store>b__2()
   at Sitecore.Data.DataProviders.NullRetryer.ExecuteNoResult(Action action, Action recover)
   at Sitecore.Analytics.Aggregation.SqlReportingStorageProvider.Store(Guid id, AggregationDataSet data)
   at Sitecore.ExperienceAnalytics.Client.Platform.SwitchingReportingStorageProvider.Store(Guid id, AggregationDataSet data)
   at Sitecore.Analytics.Aggregation.InteractionAggregator.Aggregate(Byte[] recordKey, IAggregationContext context)
   at Sitecore.Analytics.Aggregation.Aggregator.Execute()


Solution 2:

again, sitecore support came to our help and provided us with an sql and asked to run it on "reporting" database (ref : 434923)

 CREATE PROCEDURE [dbo].[Add_FormStatisticsByContact]
  @ContactId [uniqueidentifier],
  @FormId [uniqueidentifier],
  @LastInteractionDate [datetime],
  @Submits [int],
  @Success [int],
  @Dropouts [int],
  @Failures [int],
  @Visits [int],
  @Value [int],
  @FinalResult [int]
AS
BEGIN

SET NOCOUNT ON;

  BEGIN TRY

    MERGE [dbo].[Fact_FormStatisticsByContact] AS t
    USING
    (
      VALUES
      (
        @ContactId,
        @FormId,
        @LastInteractionDate,
        @Submits,
        @Success,
        @Dropouts,
        @Failures,
        @Visits,
        @Value,
        @FinalResult
      )
    )
    as s
    (
      [ContactId],
      [FormId],
      [LastInteractionDate],
        [Submits],
        [Success],
        [Dropouts],
        [Failures],
        [Visits],
        [Value],
        [FinalResult]
    )
    ON
    (
      t.[ContactId] = s.[ContactId] AND
      t.[FormId] = s.[FormId]
    )

    WHEN MATCHED and (t.[LastInteractionDate] < s.[LastInteractionDate]) THEN UPDATE SET
      t.[LastInteractionDate] = s.[LastInteractionDate],
      t.[Submits] = s.[Submits],
      t.[Success] = s.[Success],
      t.[Dropouts] = s.[Dropouts],
      t.[Failures] = s.[Failures],
      t.[Visits] = s.[Visits],
      t.[Value] = s.[Value],
      t.[FinalResult] = s.[FinalResult]

    WHEN NOT MATCHED THEN
      INSERT(
      [ContactId],
      [FormId],
      [LastInteractionDate],
        [Submits],
        [Success],
        [Dropouts],
        [Failures],
        [Visits],
        [Value],
        [FinalResult]
        )
      VALUES(
      s.[ContactId],
      s.[FormId],
      s.[LastInteractionDate],
        s.[Submits],
        s.[Success],
        s.[Dropouts],
        s.[Failures],
        s.[Visits],
        s.[Value],
        s.[FinalResult]
        );

  END TRY
  BEGIN CATCH

    DECLARE @error_number INTEGER = ERROR_NUMBER();
    DECLARE @error_severity INTEGER = ERROR_SEVERITY();
    DECLARE @error_state INTEGER = ERROR_STATE();
    DECLARE @error_message NVARCHAR(4000) = ERROR_MESSAGE();
    DECLARE @error_procedure SYSNAME = ERROR_PROCEDURE();
    DECLARE @error_line INTEGER = ERROR_LINE();


      RAISERROR( N'T-SQL ERROR %d, SEVERITY %d, STATE %d, PROCEDURE %s, LINE %d, MESSAGE: %s', @error_severity, 1, @error_number, @error_severity, @error_state, @error_procedure, @error_line, @error_message ) WITH NOWAIT;

  END CATCH;
END;
GO

Error 3:

After the above fix, errors went off from the logs. But, still contacts are not added to contact lists.

Solution 3:

So, finally, a fix will be provided for this issue.
But, solution will be coming with the Sitecore 8 Update-3 and related WFFM 8.0
So, be patient.. :-)

Growing the Sitecore Community in Sri Lanka - April Meetup - SUGSL

Now, it was time to provide an opportunity to host Sitecore User Group Sri Lanka events, to new beginning IT companies to Sitecore development in Sri Lanka.

Our SUGSL members from Virtusa (one of the biggest IT companies in Sri Lanka) took the challenge/opportunity of host SUGSL April Meetup.



Event was a huge success with more than 40 participants attended.

You can read the event report from www.sugsl.com

 Big thank for our members at Virtusa, for organizing the event.

On our next meetup on May, we are planning to focus on few new areas in development. Stay tuned... :-)

Some snaps from Facebook Event Album : https://www.facebook.com/media/set/?set=a.825328490835941.1073741833.740037979364993&type=1&l=7a1dba576f