Category Archives: Dynamic Data Store

NullReferenceException from TinyMCESettings, InputTinyOptions.GetActiveToolsHTML() and ToolbarRow in EPiServer 7

I’m upgrading a quite old EPiServer CMS website that has been alive since about 2007 from EPiServer CMS 6 to EPiServer 7 CMS.

Among the first things after using EPiServer Deployment Center to upgrade from CMS 6 R2 to 7 CMS is that I can’t use the new shiny Editor Mode.

Not being able to edit First Page

It looks good but no reaction when I click to edit a property or trying to enter Forms Editing.

A quick look in my browser’s Developer Network  gives me a HTTP Error 500 from the following url:
/secure/shell/Stores/metadata/?type=EPiServer.Core.ContentData&modelAccessor=%7B”contentLink”%3A”3_35644″%7D&dojo.preventCache=1362601343237

secure-shell-stores-metadata

I also had some strange errors when trying to edit TinyMCE Property Settings:

edit xhtmlstring settings

After some Reflecting, Debugging and some hints from http://world.episerver.com/Modules/Forum/Pages/thread.aspx?id=64169 I found that in the upgrade from 6R2 to 7, the Upgrade Tool moves some DDS-items such as Property Configuration from tblBigTable to tblSystemBigTable.

But the View VW_EPiServer.Editor.TinyMCE.ToolbarRow nor the Stored Procedure Save_EPiServer.Editor.TinyMCE.ToolbarRow are not updated to load or save from the correct Big Table causing the DDS to be able to find the TinyMCESettings correctly but when the nested entities ToolbarRow are loaded, no such data is found. Hence TinyMCESettings.Toolbar returns a list but all items in the list are NULL.

The correct procedure seems to be to change the design of the View to

SELECT CAST(R01.pkId AS varchar(50)) + ':' + UPPER(CAST([Identity].Guid AS varchar(50))) AS Id, R01.pkId AS StoreId, [Identity].Guid AS ExternalId, R01.ItemType
FROM dbo.tblSystemBigTable AS R01 INNER JOIN
 dbo.tblBigTableIdentity AS [Identity] ON R01.pkId = [Identity].pkId
WHERE (R01.StoreName = 'EPiServer.Editor.TinyMCE.ToolbarRow') AND (R01.Row = 1)

and the Stored Procedure to

USE [dbStockholmPrideDev_EPi7]
GO
/****** Object: StoredProcedure [dbo].[Save_EPiServer.Editor.TinyMCE.ToolbarRow] Script Date: 03/04/2013 09:45:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[Save_EPiServer.Editor.TinyMCE.ToolbarRow]
@Id bigint output,
@UniqueId uniqueidentifier,
@ItemType nvarchar(2048)
as
begin
declare @pkId bigint
 select @pkId = pkId from tblBigTableIdentity where [Guid] = @UniqueId
 if @pkId IS NULL
 begin
 begin transaction
 insert into [tblBigTableIdentity]([Guid], [StoreName]) values(@UniqueId, 'EPiServer.Editor.TinyMCE.ToolbarRow')
select @Id = SCOPE_IDENTITY()
 insert into [tblSystemBigTable] (pkId, StoreName, Row, ItemType)
 values(@Id, 'EPiServer.Editor.TinyMCE.ToolbarRow', 1, @ItemType )
commit transaction
 end
 else
 begin
 begin transaction
 select @Id = @pkId
 DECLARE @rows int
 select @rows = count(*) from [tblSystemBigTable] where pkId = @Id
 if(@rows < 1) begin
 insert into [tblSystemBigTable] (pkId, StoreName, Row, ItemType)
 values(@Id, 'EPiServer.Editor.TinyMCE.ToolbarRow', 1, @ItemType )
end
 commit transaction
 end
end

EPiServer DDS + Enum

We found a problem when having Nullable Enum values in our DDS objects. We got an error “Invalid cast from ‘System.Int32’ to ‘RoleData.MyEnum’.” when we tried to iterate through our repository.

Others seem to have the same problem as well.

According to Paul Smith there seems to be some problems, I didn’t get the e-mail response myself so I must get back with more details.

This is my solution, using a TypeHandler, had totally forgotten about that part in the DDS Example Package.

    public class EnumTypeHandler : ITypeHandler
    {
        //From int to enum
        public object FromDatabaseFormat(string propertyName,
                                         object propertyValue,
                                         Type targetType, Type ownerType)
        {
            if (propertyValue == null)
                return null;

            Type valueType = targetType;
            if (IsNullable(targetType))
            {
                valueType = Nullable.GetUnderlyingType(targetType);
            }
            if (valueType.IsEnum)
            {
                string stringValue = Convert.ToString(propertyValue);
                return Enum.Parse(valueType, propertyValue.ToString());
            }
            return propertyValue;
        }

        //returns int type
        public Type MapToDatabaseType(Type type)
        {
            if (type.IsEnum)
            {
                if(IsNullable(type))
                    return typeof(int?);
                return typeof(int);
            }
            return type;
        }

        //convert enum to int
        public object ToDatabaseFormat(string propertyName,
                                       object propertyValue,
                                       Type ownerType)
        {
            if (propertyValue == null)
                return null;
            if (propertyValue is Enum)
                return Convert.ToInt32(propertyValue);
            return propertyValue;
        }

        private bool IsNullable(Type type)
        {
            return (type.IsGenericType && type.GetGenericTypeDefinition()
                                              .Equals(typeof(Nullable<>)));
        }
    }

It only takes care of int Enums at the moment but it’ll do.

And in EPiServer FirstBeginRequest I added the Handler by adding:

if (!GlobalTypeHandlers.Instance.ContainsKey(enumType))
    GlobalTypeHandlers.Instance.Add(enumType, new EnumTypeHandler());

Where enumType is each Enum I need to handle in my DDS object.