вторник, 10 мая 2011 г.

Item ModerationInformation and SPListItem.UpdateInternal()

Столкнулся с необходимостью изменить значения нескольких полей включая Approval Status у ряда Item'ов, причем так, чтобы не изменились время модификации, Editor и не создалась дополнительная версия.

Первый способ был весьма прост:

var url = @"http://server/Lists/ContentApList";
var web = new SPSite(url).OpenWeb();
var list = web.GetList(url);
var item = list.GetItemById(1);
item["MyCheck"] = "test";
item[SPBuiltInFieldId._ModerationStatus] = 0;
item[SPBuiltInFieldId._ModerationComments] = "my coment";
item.SystemUpdate();
 
Но увы этот код просто валился с ошибкой Item does not exist. The page you selected contains an item that does not exist. It may have been deleted by another user.. Замена метода на UpdateOverwriteVersion() и Update() так же не помогла.

Вот такой вот вариант работает ,но :

var url = @"http://server/Lists/ContentApList";
var web = new SPSite(url).OpenWeb();
var list = web.GetList(url);
var item = list.GetItemById(1);
item["MyCheck"] = "test23";
item.ModerationInformation.Status = SPModerationStatusType.Pending;
item.ModerationInformation.Comment = "my coment";
item.SystemUpdate();
 
Но увы только для итемов. Похожий код для работы с файлами выдает исключение "You cannot change moderation status and set other item properties at that same time."

Попытка делать обновление в два этапа, увы так же не работает т.к. SystemUpdate, похоже, просто игнорирует обновление полей Moderation Information.

var url = @"http://server/Lists/ContentApList";
var web = new SPSite(url).OpenWeb();
var file = web.GetFile("CheckDocLib/logo.gif");
var item = file.ListItemAllFields;
item["MyComments"] = "test23";
item.SystemUpdate();

item.ModerationInformation.Status = SPModerationStatusType.Denied;
item.ModerationInformation.Comment = "my coment";
item.SystemUpdate();
 
Замена же на UpdateOverwriteVersion() приводит к тому что меняется время модификации.

Казалось бы приплыли, решения нет. Но пока еще бесплатный Reflector при просмотре ф-ии Update(), UpdateOverwriteVersion() и SystemUpdate() выдает что все они вызывают один и тот же метод:

internal void UpdateInternal(bool bSystem, bool bPreserveItemVersion, Guid newGuidOnAdd, bool bMigration, bool bPublish, bool bNoVersion, bool bCheckOut, bool bCheckin, bool suppressAfterEvents, string filename)

 

Табличка параметров вызова UpdateInternal из каждой ф-и.

Method bSystem bPreserveItemVersion newGuidOnAdd bMigration bPublish bNoVersion bCheckOut bCheckin suppressAfterEvents
Update() false false Empty false false false false false false
SystemUpdate() true false Empty false false false false false false
UpdateOverwriteVersion() false false Empty false false true false false false
MySystemUpdate() true false Empty true false false false false false

Немного поэсперементировав оказалось, что если выставлять флаги bSystem и bMigrate обновление ModerationInformation работает и при этом не происходит создания дополнительных версии. Вот итоговый код:

static void UpdateInternal(SPListItem item , bool bSystem, bool bPreserveItemVersion, Guid newGuidOnAdd, bool bMigration, bool bPublish, bool bNoVersion, bool bCheckOut, bool bCheckin, bool suppressAfterEvents)
{
    Type type = typeof(SPListItem);
    MethodInfo method = type.GetMethod("UpdateInternal",
                                        BindingFlags.Instance | BindingFlags.NonPublic,
                                        null,
                                        new Type[] { typeof(bool), typeof(bool), typeof(Guid), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool) },
                                        null
        );

    var parameters = new object[] {
            bSystem,
            bPreserveItemVersion,
            newGuidOnAdd,
            bMigration,
            bPublish,
            bNoVersion,
            bCheckOut, bCheckin,
            suppressAfterEvents };

    object obj = method.Invoke(item, parameters);
}

static void UpdateMigrate(SPListItem item)
{
    UpdateInternal(item, true, false, Guid.Empty, true, false,false, false, false, false);
}

static void CheckList5()
{
    var url = @"http://server/Lists/ContentApList";
    var web = new SPSite(url).OpenWeb();
    var file = web.GetFile("CheckDocLib/logo.gif");
    var item = file.ListItemAllFields;
    item["MyComments"] = "test23ddd";
    item.ModerationInformation.Status = SPModerationStatusType.Approved;
    item.ModerationInformation.Comment = "my coment";
    UpdateMigrate(item);
}
 

Буду рад если кому пригодится.

Комментариев нет: