Работаем с ошибкой "Отсутствуют зависимости на стороне сервера" (Missing server side dependencies)
В данном посте я привожу свою методологию решения проблемы "Отсутствуют зависимости на стороне сервера" (Missing server side dependencies).
В данном примере используется SharePoint 2010, но принцип остается тем же самым и в новых версиях (хотя честно говоря, на SP2016 я не проверял). Важно отметить, что в данном решении нам необходим доступ непосредственно в базу.
В анализаторе SharePoint
ошибка выглядит так:
На секунду задумаемся о том, что же это за ошибка и откуда она берется?
Допустим, у нас имеется серверное решение. В решении есть артефакт - ghosted file, или может быть веб часть. Веб часть могла быть установлена в галерею веб частей, или может быть добавлена на страницу. После чего по разным причинам веб часть удалили (обычно ее переименовывает кто нибудь). Но в базе SharePoint остается запись о старой веб части.
Что же делать?
Сначала нужно найти, где же на нашем сайте ссылка на "отсутствующий" компонент.
Обычно я делаю это с помощью SQL.
Возьмем скрипт, который пройдет по всем таблицам базы данных контента , и найдет там указанную строчку (в нашем случае ИМЯФАЙЛАВЕБЧАСТИ.webpart)
(В своей практике я несколько раз создавал и терял данный скрипт, так что пора его указать в блоге).
Скрипт взят отсюда и слегка модифицирован.
--
use WSS_Content -- could be your database name here
DECLARE
@search_string VARCHAR(100),
@table_name SYSNAME,
@table_schema SYSNAME,
@column_name SYSNAME,
@sql_string VARCHAR(2000)
SET @search_string = 'yourwebpart.webpart'
DECLARE tables_cur CURSOR FOR SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO @table_schema, @table_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
DECLARE columns_cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = @table_schema AND TABLE_NAME = @table_name AND COLLATION_NAME IS NOT NULL -- Only strings have this and they always have it
OPEN columns_cur
FETCH NEXT FROM columns_cur INTO @column_name
WHILE (@@FETCH_STATUS = 0)
BEGIN
-- SET @sql_string = 'IF EXISTS (SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'') PRINT ''' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ', ' + QUOTENAME(@column_name) + ''''
SET @sql_string = 'IF EXISTS (SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'') SELECT * FROM ' + QUOTENAME(@table_schema) + '.' + QUOTENAME(@table_name) + ' WHERE ' + QUOTENAME(@column_name) + ' LIKE ''%' + @search_string + '%'''
EXECUTE(@sql_string)
FETCH NEXT FROM columns_cur INTO @column_name
END
CLOSE columns_cur
DEALLOCATE columns_cur
FETCH NEXT FROM tables_cur INTO @table_schema, @table_name
END
CLOSE tables_cur
DEALLOCATE tables_cur
--
Вот что получилось после запуска скрипта :
Итак, мы знаем, что сайт с идентификатором 089D94D0-7BF4-4A51-9E29-2BACABC30DF4 содержит запись об отсутствующей веб части в галерее, и мы можем решить данную проблему с помощью PowerShell или вручную .
Вот пример другой веб части. В данном случае у нас некорректная веб часть находится в двух местах - на основном сайте и на личном сайте администратора.
К сожалению, нам понадобится еще один скрипт. Скрипт выше отлично решает проблему веб части в галерее или отсутствующего файла, но не решает проблему веб части , расположенной на странице.
Вот еще один скрипт, который находит все веб части на всех страницах. Если раскоментировать последнюю строчку, то найдется нужная веб часть.
SELECT Webs.FullUrl, Webs.Title, AllDocs.DirName, AllDocs.LeafName, AllWebParts.tp_DisplayName, AllWebParts.tp_ID
FROM AllDocs, Sites, AllWebParts, Webs
WHERE Webs.Id = Sites.RootWebId AND AllDocs.Id = AllWebParts.tp_PageUrlID
AND Sites.Id = AllDocs.SiteId AND tp_WebPartTypeId IN (
SELECT DISTINCT tp_WebPartTypeId FROM AllWebParts (NOLOCK)
WHERE tp_WebPartTypeId IS NOT NULL AND tp_Assembly IS NULL AND tp_Class IS NULL)
-- if you add this line, the script will find your specific web part instead of giving you all web parts on all pages
--AND (AllWebParts.tp_DisplayName = 'yourwebpartname')
Вот что я получил при запуске скрипта:
Pic4.
Теперь, в зависимости от количества проблем, можно вручную или с помощью скрипта пройтись по указанным страницам и убрать Вашу веб часть.
Правда, однажды, я столкнулся с ситуацией, которую долго не смог разрешить.
Дело в том, что несколько пользователей добавили веб часть в свою личную копию страницы. Найти того, кто конкретно добавил, было невозможно (несколько тысяч пользователей).
К счастью, я вспомнил про еще один хороший прием. Дело в том, что если к любой странице ?contents=1
Вот таким образом можно сбросить все "личные" копии страницы.
А вот так - удалить "некорректную" веб часть.