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

Thursday, April 9, 2015

Auto submit/skip items into different workflow states depending on language/condition

Scenario:

Auto submit/Skip workflow states to specific language items

Solution:

Add "Auto Submit Lang Items Action" of type "Auto Submit Action"inside the __OnSave command.
Then, I have choosen to skip/auto submit "en" language items directly into "Approved" state.




Code :
public class AutoSubmitLangItemsAction
{
    public void Process(WorkflowPipelineArgs args)
    {
        Assert.ArgumentNotNull(args, "args");
       
        ProcessorItem processorItem = args.ProcessorItem;
        if (processorItem == null || args.DataItem == null)
        {
            return;
        }
           
        Item innerItem = processorItem.InnerItem;
 

        string langName = innerItem["role name"];
        if (!langName.Equals(args.DataItem.Language.Name, StringComparison.CurrentCultureIgnoreCase))
        {
            return;
        }

        ID iD = MainUtil.GetID(innerItem["next state"], null);
        if (iD.IsNull)
        {
            return;
        }

        args.NextStateId = iD;
    }
}



Possible Improvements : 

I have used the "Role Name" field to specify the language. But, one can create a custom template with "Auto Submit Language" field of type "TreelistEx" with DataSource pointing to language items



Update : I have make this into a Sitecore Marketplace Module. 




Wednesday, April 1, 2015

How to Populate WFFM form Fields using QueryString Parameters

Sometimes you might need to populate a Sitecore WFFM form fields by using Query String parameter values comes from URL. 





Following is the process or configuration to do that.

When you try to add a WFFM form using default WFFM "Form" webcontrol, you will see a checkbox with name "ReadQueryString" (refer below image). 

If you have this checkbox is clicked, and if you pass any url parameters with a name of a fields in the WFFM form, sitecore will automatically populate that value (as you see in the above image)


Tuesday, March 31, 2015

Evaluation of condition failed for rule item error on Log files in Sitecore 8.0

Sitecore Version :

Sitecore 8.0 rev. 150223

Error :

Following error repeated in the error logs

ManagedPoolThread #1 07:41:22 ERROR Evaluation of condition failed. Rule item ID: {871B4104-9CFA-4DE3-AF38-DF1E144B3DF0}, condition item ID: {4640D86A-9B01-4B04-9BEB-03E06E5AC722}
Exception: System.InvalidOperationException
Message: Tracker.Current.Session.Interaction is not initialized
Source: Sitecore.Kernel
   at Sitecore.Diagnostics.Assert.IsNotNull(Object value, String message)
   at Sitecore.Analytics.Rules.Conditions.EngagementValuePointsCondition`1.Execute(T ruleContext)
   at Sitecore.Rules.Conditions.WhenCondition`1.Evaluate(T ruleContext, RuleStack stack)
   at Sitecore.Rules.RuleList`1.Run(T ruleContext, Boolean stopOnFirstMatching, Int32& executedRulesCount)

Reason :

When an Engagement plan condition has a timeout value set, this error occrs
Quote : Sitecore SupportWhen the state processing is performed by timeout, the interaction does not exist. That's why the excepion occurs in you log files, additionaly the contact does not move to the next state even if the condition was satisfied.

Solution :

Remove the timeout value from the Engagement plan Condition

Note : This has been registered as a bug (ref. 430511)

Quick Search Index Rebuild Error due to Large Item Names

Environment Summary: Sitecore 8.0 rev. 150223 (Update-2)

Issue : Quick Search Index Rebuilding error

When we try to run the "Quick Search Index" rebuild, we get the following error

Job started: RebuildSearchIndex|System.ArgumentException: it doesn't make sense to have a field that is neither indexed nor stored
   at Lucene.Net.Documents.Field..ctor(String name, Boolean internName, String value_Renamed, Store store, Index index, TermVector termVector)
   at Sitecore.Search.Crawlers.BaseCrawler.CreateDataField(String name, String value)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddSpecialFields(Document document, Item item)
   at Sitecore.Search.Crawlers.DatabaseCrawler.IndexVersion(Item item, Item latestVersion, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddItem(Item item, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Crawlers.DatabaseCrawler.AddTree(Item root, IndexUpdateContext context)
   at Sitecore.Search.Index.Rebuild()
   at Sitecore.Shell.Applications.Search.RebuildSearchIndex.RebuildSearchIndexForm.Builder.Build()|Job ended: RebuildSearchIndex (units processed: 5802)



Reason :

Quote : Sitecore Support 
When an item name length exceeds 128 characters this issue occurs. You can use the following SQL script in order to perform the check of your Core, Master databases:
SELECT [ID]
      ,[Name]
      ,[TemplateID]
      ,[MasterID]
      ,[ParentID]
      ,[Created]
      ,[Updated]
  FROM [dbo].[Items]
  WHERE LEN([NAME]) > 120 
 

Temporarily Fix :

Rename the items with name length greater than 120 characters to within 120 characters