Показаны сообщения с ярлыком event receiver. Показать все сообщения
Показаны сообщения с ярлыком event receiver. Показать все сообщения

пятница, 30 марта 2012 г.

Redirect из EventReceiver’а

Как оказалось, это довольно частая задача. Но практически нигде не разрешённая.
Итак, у нас есть обработчик события создания элемента списка (ItemAdding); и нам необходимо сразу после создания перейти на другую страницу.

На первый взгляд задача простая: у нас есть и «Page.Response.Redirect(…)» и «SPUtility.Redirect(…)».
Но… Для первого случая у нас нет объекта Page! А второй метод требует указания HttpContext, который в обработчиках события пуст.

Решение!
Как всегда хак! :)

Как известно, создание элементов списка можно отменять (для этого обработчики событий видимо изначально и создавались). При этом, отменяя, мы можем указать адрес, на который нам следует перейти (чтобы посмотреть причину отмены) (доступно только в SharePoint 2010).
То есть, мы можем отменить создание элемента, и сделать искомый редирект на нужную страницу. Нам нужно только пересоздать отменённый элемент. Вот тут и кроется ограничение этого метода – у нас нет доступа к вложениям элемента при его создании.

Пример кода реализации данного метода:

public override void ItemAdding(SPItemEventProperties properties)
{
    base.ItemAdding(properties);

    //Отключаем сам обработчик, чтобы избежать зацикливания
    EventFiringEnabled = false;

    var list = properties.List;

    //Создаём элемент списка и заполняем его свойствами из только что созданного пользователем элемента
    var ni = list.Items.Add();

    //Выбираем все созданные пользователем свойства доступные для редактирования, а также свойство Title (Название)
    foreach (var ff in list.Fields.Cast<SPField>().Where(spf => !spf.ReadOnlyField && (spf.FromBaseType == false || spf.InternalName == "Title")))
        ni[ff.InternalName] = properties.AfterProperties[ff.InternalName];
    ni.SystemUpdate();

    //Включаем обработчик
    EventFiringEnabled = true;

    //Отменяем создание элемента созданного пользователем
    properties.Cancel = true;
    //Устанавливаем действие при отмене - переход на другую страницу
    properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
    //Устанавливаем адрес страницы, на которую делаем переход. В данном случае - страница редактирования только что созданного элемента
    properties.RedirectUrl = string.Format("/{0}?ID={1}", properties.List.Forms[PAGETYPE.PAGE_EDITFORM].Url, ni.ID);
}

Событие ItemAdded для этого метода не подходит, т.к. там элемент списка уже создан и отменить это действие уже нельзя.