Error On SaveDocument

Alonso Gonzalez asked on November 1, 2017 00:36

Hi there,

I have a working kentico website running with a bunch of pages but from a client request I was asked to change on of my existing page's "Page name:*" and I got an error after cliking save. I don't know what It's wrong here.

Here is the information of the error:

EventID: 20379

EventType: E

EventTime: 10/31/2017 11:28:56 PM

Source: Content

EventCode: SaveDocument

UserID: 77

UserName: xxxx

IPAddress: xxxx

EventDescription: An error occurred when saving data. Please see event log for more details. Message:

Proc_CMS_Document_UpdateDocumentNamePath

Caused exception: Could not find stored procedure 'Proc_CMS_Document_UpdateDocumentNamePath'.

Exception type: System.Exception Stack trace: at CMS.DataEngine.AbstractDataConnection.HandleError(String queryText, Exception ex) at CMS.DataEngine.AbstractDataConnection.ExecuteQuery(String queryText, QueryDataParameters queryParams, QueryTypeEnum queryType, Boolean requiresTransaction) at CMS.DataEngine.AbstractDataConnection.CMS.DataEngine.IDataConnection.ExecuteQuery(String queryText, QueryDataParameters queryParams, QueryTypeEnum queryType, Boolean requiresTransaction) at CMS.DataEngine.GeneralConnection.RunQuery(QueryParameters query) at CMS.DataEngine.GeneralConnection.RunQueryWithRetry(QueryParameters query, Int32 retryCount) at CMS.DataEngine.GeneralConnection.ExecuteQuery(QueryParameters query) at CMS.DataEngine.GeneralConnection.ExecuteQuery(QueryParameters query, Int32& totalRecords) at CMS.DataEngine.DataQueryBase1.GetDataFromDBInternal() at CMS.DataEngine.DataQueryBase1.GetDataFromDB() at CMS.DataEngine.DataQueryBase1.GetData() at CMS.DataEngine.DataQueryBase1.get_Result() at CMS.DataEngine.ConnectionHelper.ExecuteQuery(String queryName, QueryDataParameters parameters, String where, String orderBy, Int32 topN, String columns, Int32 offset, Int32 maxRecords, Int32& totalRecords) at CMS.DocumentEngine.DocumentPathsUpdater.ExecuteUpdateDocumentPath(DocumentPathPrefixes prefixes, Boolean allCultureVersions) at CMS.DocumentEngine.DocumentPathsUpdater.<>c__DisplayClass4.b__3() at CMS.DocumentEngine.DocumentContinuousIntegrationHelper.HandleBulkUpdate(Boolean allowContinuousIntegrationActions, IWhereCondition bulkWhere, Action bulkUpdate) at CMS.DocumentEngine.DocumentPathsUpdater.UpdateDocumentPaths(DocumentPathPrefixes prefixes, Boolean allCultureVersions) at CMS.DocumentEngine.DocumentPathsUpdater.UpdateOtherCultureVersionsAndDescendantsAllPaths() at CMS.DocumentEngine.DocumentPathsUpdater.UpdateOtherCultureVersionsAndDescendantsPathsForUpdate() at CMS.DocumentEngine.TreeNode.UpdateInternal() at CMS.DocumentEngine.TreeNode.Update(Boolean useDocumentHelper) at CMS.DocumentEngine.DocumentHelper.UpdateDocument(TreeNode node, TreeProvider tree, String updateColumns) at CMS.DocumentEngine.TreeNode.Update(Boolean useDocumentHelper) at CMS.FormEngine.Web.UI.CMSDocumentManager.UpdateDocumentInternal(Boolean useDocumentHelper) at CMS.FormEngine.Web.UI.CMSDocumentManager.UpdateDocument(Boolean useDocumentHelper) at CMS.FormEngine.Web.UI.CMSForm.SaveDataInternal() at CMS.FormEngine.Web.UI.BasicForm.SaveData(String redirectUrlAfterSave, Boolean showChangesSaved) at CMS.FormEngine.Web.UI.CMSForm.DocumentManager_OnSaveData(Object sender, DocumentManagerEventArgs e) at CMS.FormEngine.Web.UI.CMSAbstractManager`2.RaiseSaveData(EventArgsType args) at CMS.FormEngine.Web.UI.CMSDocumentManager.SaveDocumentInternal(String actionContext)

Message: Could not find stored procedure 'Proc_CMS_Document_UpdateDocumentNamePath'.

Exception type: System.Data.SqlClient.SqlException Stack trace: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 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.SqlDataReader.TryConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet) at CMS.DataEngine.AbstractDataConnection.ExecuteQuery(String queryText, QueryDataParameters queryParams, QueryTypeEnum queryType, Boolean requiresTransaction)

Site: xxx

EventUrl: /CMSModules/Content/CMSDesk/Edit/edit.aspx?nodeid=12&culture=en-US

EventMachineName: RD0004FF9DCE4C

EventUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36

EventUrlReferrer: xxx

Correct Answer

Mariia Hrytsai answered on November 1, 2017 09:50

Please make sure that stored procedure with name [Proc_CMS_Document_UpdateDocumentNamePath] exsists in your database. If no, you can create it by running sql query (for Kentico 10):

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[Proc_CMS_Document_UpdateDocumentNamePath]
     @NodeID int,
     @DocumentID int,
     @PrefixesXML nvarchar(max),
     @DefaultCultureCode nvarchar(10),
     @UpdateUrlPath bit,
     @GenerateAliases bit,
     @CurrentDate datetime2(7)
    AS
    BEGIN

    -- Get XML from the string representation
    DECLARE @Prefixes xml = CAST(@PrefixesXML as XML);

    -- Prepare temp table for the results
    DECLARE @Documents TABLE
    (
      NodeID int, 
      DocumentID int, 
      OriginalNamePrefix nvarchar(1500), 
      NamePrefix nvarchar(1500), 
      OriginalUrlPrefix nvarchar(450), 
      UrlPrefix nvarchar(450)
    );

    WITH 
    Prefixes AS
    (
        SELECT 
            ref.value('Culture[1]', 'nvarchar(10)') AS DocumentCulture, 
            ref.value('(NamePath/Original)[1]', 'nvarchar(1500)') AS OriginalNamePrefix, 
            ref.value('(NamePath/Current)[1]', 'nvarchar(1500)') AS NamePrefix, 
            ref.value('(UrlPath/Original)[1]', 'nvarchar(450)') AS OriginalUrlPrefix, 
            ref.value('(UrlPath/Current)[1]', 'nvarchar(450)') AS UrlPrefix 
        FROM @Prefixes.nodes('/Prefixes/Prefix') xmlData(ref)
    ),
    Base AS
    (
        SELECT DocumentID, NodeID, NodeLinkedNodeID, TopDocumentCulture, OriginalNamePrefix, NamePrefix, OriginalUrlPrefix, UrlPrefix 
        FROM
        (
            SELECT 
                V.DocumentID, V.NodeID, V.NodeLinkedNodeID,
                V.DocumentCulture AS TopDocumentCulture,
                OriginalNamePrefix, NamePrefix, OriginalUrlPrefix, UrlPrefix,
                -- Prefer parent data in culture of the document, than in default culture, any other culture at least 
                ROW_NUMBER() OVER (PARTITION BY V.DocumentID, V.NodeID ORDER BY CASE WHEN P.DocumentCulture = V.DocumentCulture THEN 1 WHEN P.DocumentCulture = @DefaultCultureCode THEN 2 ELSE 3 END, P.DocumentCulture) AS CMS_C
            FROM View_CMS_Tree_Joined AS V WITH (NOLOCK)
                    -- Get original and current prefix
                    INNER JOIN Prefixes ON V.DocumentCulture = Prefixes.DocumentCulture
                    -- Get parent values
                    INNER JOIN View_CMS_Tree_Joined as P WITH (NOLOCK) ON (SELECT NodeParentID FROM CMS_Tree AS T WITH (NOLOCK) WHERE T.NodeID = V.NodeOriginalNodeID) = P.NodeID
            -- Get either all culture versions or just the one based on DocumentID
            WHERE (@NodeID <> 0 AND V.NodeOriginalNodeID = @NodeID) OR (@DocumentID <> 0 AND V.DocumentID = @DocumentID)
        ) AS B
        -- Get data with best matching parent data
        WHERE CMS_C = 1
    ),
    Candidates AS
    (
        SELECT * FROM Base

        UNION ALL

        SELECT DocumentID, NodeID, NodeLinkedNodeID, TopDocumentCulture, OriginalNamePrefix, NamePrefix, OriginalUrlPrefix, UrlPrefix FROM
        (
            SELECT 
                V.DocumentID, V.NodeID, V.NodeLinkedNodeID, 
                Candidates.TopDocumentCulture, Candidates.DocumentID AS CandidatesParentDocumentID,
                P.DocumentID AS ParentDocumentID,
                Prefixes.OriginalNamePrefix, Prefixes.NamePrefix, Prefixes.OriginalUrlPrefix, Prefixes.UrlPrefix,
                -- Prefer parent data in culture of the document, than in default culture, any other culture at least 
                ROW_NUMBER() OVER (PARTITION BY V.DocumentID, V.NodeID ORDER BY CASE WHEN P.DocumentCulture = V.DocumentCulture THEN 1 WHEN P.DocumentCulture = @DefaultCultureCode THEN 2 ELSE 3 END, P.DocumentCulture) AS CMS_C
            FROM Candidates
                -- Get original and current prefix
                INNER JOIN Prefixes ON Candidates.TopDocumentCulture = Prefixes.DocumentCulture
                -- Get all child documents (for links get the originals) of the current one having the original prefix
                INNER JOIN View_CMS_Tree_Joined V WITH (NOLOCK) ON (SELECT NodeParentID FROM CMS_Tree AS T WHERE T.NodeID = V.NodeOriginalNodeID) = Candidates.NodeID AND V.DocumentNamePath LIKE Prefixes.OriginalNamePrefix + '%'
                -- Get all combinations with their parents
                INNER JOIN View_CMS_Tree_Joined as P WITH (NOLOCK) ON (SELECT NodeParentID FROM CMS_Tree AS T WHERE T.NodeID = V.NodeOriginalNodeID) = P.NodeID
        ) AS LevelCandidates
        -- Include only those whose primary parents are included in the current scope
        WHERE CandidatesParentDocumentID = ParentDocumentID AND LevelCandidates.CMS_C = 1 AND LevelCandidates.DocumentID NOT IN (SELECT DocumentID FROM Base)
    ),
    Items AS
    (
        -- Filter links since the originals are incldued as well
        SELECT DISTINCT NodeID, DocumentID, OriginalNamePrefix, NamePrefix, OriginalUrlPrefix, UrlPrefix 
        FROM Candidates
        WHERE NodeLinkedNodeID IS NULL
    )

    -- Get the final result set
    INSERT INTO @Documents SELECT NodeID, DocumentID, OriginalNamePrefix, NamePrefix, OriginalUrlPrefix, UrlPrefix FROM Items

    DECLARE @AliasesPKTable TABLE (AliasID INT)

    -- Generate document aliases
    IF (@UpdateUrlPath = 1 AND @GenerateAliases = 1)
    BEGIN
        -- Insert alias for all child documents where original URL path differs from the new one and the alias with same URL path doesn't exist
        INSERT INTO CMS_DocumentAlias 
        (
            AliasNodeID, 
            AliasCulture, 
            AliasURLPath, 
            AliasExtensions, 
            AliasWildcardRule, 
            AliasPriority, 
            AliasGUID, 
            AliasLastModified, 
            AliasSiteID
        )
        OUTPUT INSERTED.AliasID INTO @AliasesPKTable
        SELECT 
            D.NodeID AS AliasNodeID, 
            DocumentCulture AS AliasCulture, 
            DocumentURLPath AS AliasURLPath, 
            '' AS AliasExtensions, 
            '' AS AliasWildcardRule, 
            LEN(DocumentURLPath) - LEN(REPLACE(DocumentURLPath,'/','')) AS AliasPriority, 
            NEWID() AS AliasGUID, 
            @CurrentDate AS AliasLastModified, 
            NodeSiteID AS AliasSiteID
        FROM @Documents AS D INNER JOIN View_CMS_Tree_Joined AS V ON D.DocumentID = V.DocumentID
        WHERE 
            -- Aliases were already generated for updated culture version
            -- Do not include links since the aliases are same as for originals included in the results
            D.DocumentID <> @DocumentID  AND NodeLinkedNodeID IS NULL
            -- Do not generate aliases for content-only pages
            AND NodeIsContentOnly = 0
            -- URL path is generated and differs from the original one
            AND DocumentUrlPath <> 
                (
                CASE WHEN DocumentUseNamePathForUrlPath = 1 AND (ISNULL(DocumentUrlPath, '') <> '')
                THEN
                    -- Path starts with original URL path prefix
                    CASE WHEN LEFT(DocumentUrlPath, LEN(OriginalUrlPrefix)) = OriginalUrlPrefix 
                    THEN
                        -- Replace original URL prefix with new URL path prefix
                        UrlPrefix + SUBSTRING(DocumentUrlPath, LEN(OriginalUrlPrefix) + 1, LEN(DocumentUrlPath)) 
                    -- Path starts with original name path prefix
                    WHEN LEFT(DocumentUrlPath, LEN(OriginalNamePrefix)) = OriginalNamePrefix 
                    THEN
                        -- Replace original Name prefix with new URL path prefix (when new document is created, DocumentNamePath of the parent is used to build the URL path)
                        UrlPrefix + SUBSTRING(DocumentUrlPath, LEN(OriginalNamePrefix) + 1, LEN(DocumentUrlPath)) 
                    ELSE
                        DocumentUrlPath
                    END
                ELSE DocumentUrlPath END
                )
            -- There is no alias with the same URL path
            AND NOT EXISTS (SELECT AliasID FROM CMS_DocumentAlias WHERE AliasURLPath = DocumentUrlPath AND AliasNodeID = D.NodeID AND (AliasCulture = DocumentCulture OR ISNULL(AliasCulture, '') = ''))
    END

    -- Propagate new prefixes to all child documents
    -- Currently modified document is not udpated since the paths were already udpated by API
    UPDATE CMS_Document SET
    DocumentNamePath = 
        (
        -- Path starts with original name prefix
        CASE WHEN LEFT(DocumentNamePath, LEN(OriginalNamePrefix)) = OriginalNamePrefix
        THEN
            NamePrefix + SUBSTRING(DocumentNamePath, LEN(OriginalNamePrefix) + 1, LEN(DocumentNamePath))
        ELSE DocumentNamePath END
        ),
    DocumentUrlPath = 
        (
        CASE WHEN @UpdateUrlPath = 1 AND DocumentUseNamePathForUrlPath = 1 AND (ISNULL(DocumentUrlPath, '') <> '')
        THEN
            -- Path starts with original URL path prefix
            CASE WHEN LEFT(DocumentUrlPath, LEN(OriginalUrlPrefix)) = OriginalUrlPrefix 
            THEN
                -- Replace original URL prefix with new URL path prefix
                UrlPrefix + SUBSTRING(DocumentUrlPath, LEN(OriginalUrlPrefix) + 1, LEN(DocumentUrlPath)) 
            -- Path starts with original name path prefix
            WHEN LEFT(DocumentUrlPath, LEN(OriginalNamePrefix)) = OriginalNamePrefix 
            THEN
                -- Replace original Name prefix with new URL path prefix (when new document is created, DocumentNamePath of the parent is used to build the URL path)
                UrlPrefix + SUBSTRING(DocumentUrlPath, LEN(OriginalNamePrefix) + 1, LEN(DocumentUrlPath)) 
            ELSE
                DocumentUrlPath
            END
        ELSE DocumentUrlPath END
        )
    FROM CMS_Document AS D INNER JOIN @Documents AS R ON D.DocumentID = R.DocumentID
    WHERE R.DocumentID <> @DocumentID

    SELECT * FROM @AliasesPKTable
    END

GO
0 votesVote for this answer Unmark Correct answer

Recent Answers


Chetan Sharma answered on November 1, 2017 09:32

Is this "Page name:" the page name? If yes, then I am sure you can't use asterisk "" in the page name because that will be passed on to the query causing problem or may be you will have to escape it. That is just a clue.

0 votesVote for this answer Mark as a Correct answer

Peter Mogilnitski answered on November 1, 2017 14:54

Run this to see in Kentico DB to see that the stored procedure really exists

SELECT * FROM sys.objects WHERE type = 'P' AND OBJECT_ID = OBJECT_ID('[dbo].[Proc_CMS_Document_UpdateDocumentNamePath]')

0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.