Длительные операции в SharePoint. Изнутри
Часть 1. SPLongOperation снаружи
Часть 2. SPLongOperation изнутри
Часть 3. SPLongOperation. Request timed out
Часть 4. Длительные операции с обновляемым статусом
В продолжении поста об использовании SPLongOperation сегодня я постараюсь описать его внутреннее устройство.
Метод Begin()
Логично будет начать исследования с вызова метода Begin(). Для чего нам понадобиться сборка Microsoft.SahrePoint.dll, обработанная деобфускатором.
Вот код этого метода:
public void Begin()
{
this.Begin(true);
}
internal void Begin(bool closeGearPageDiv)
{
if (!this.m_bLongOperationStarted)
{
string s = GearFileContent.Replace("<%=System.Threading.Thread.CurrentThread.CurrentUICulture.LCID%>", Thread.CurrentThread.CurrentUICulture.LCID.ToString(CultureInfo.InvariantCulture));
this.m_srGearAspx = new StringReader(s);
this.WriteGearToSearchString(m_strTargetDots);
if (closeGearPageDiv)
{
this.WriteGearToSearchString("SPLongOperation.EndGearPageDiv");
this.m_bGearPageDivEnded = true;
}
CurrentLongOperation = this;
this.m_bLongOperationStarted = true;
}
}
GearFileContent
Это свойство возвращает содержимое файла [SharePoint Root]\TEMPLATE\LAYOUTS\gear.aspx в виде текста, предварительно заменив серверные комментарии на их HTML аналоги и "вырезав" серверные дерективы страницы. В методе Begin() происходит ещё одна манипуляция с полученным текстом - в текст подставляется идентификатор текущей локали. Таким образом сам файл gear.aspx не исполняется. Мне думается, что этот файл оставили .aspx для отладки. Можно было и просто .txt файл сделать.
В исходном коде gear.aspx есть ещё одна очень важная особенность. Там дважды объявлены javascript-методы gotoNextPage() и setGearPageFocus(). Оба этих метода указаны в событии onload тела страницы:
<body onload="setGearPageFocus();gotoNextPage();" class="s4-simple-gearpage">
Вывод данных пользователю
Вывод данных пользователю происходит в методе WriteGearToSearchString(), который принимает в качестве параметра текст, дойдя до которого при построчном переборе обработанного содержимого файла gear.aspx вывод прекратится. В нашем случае это "SPLongOperation.Dots":
private static string m_strTargetDots = "SPLongOperation.Dots";
Клиент получит в итоге незакрытый тег body. Который браузер и будет ожидать. А наша длительная операция в это время будет исполняться на сервере.
Метод End()
И вот наша операция завершена и мы смело вызываем метод End(). В теле которого формируется конечный скрипт, предназначенный для перенаправления пользователя на страницу, указанную, в моем случае в comeBackUrl.
Сформированный скрипт передается методу EndScript(), который завершает отрисовку страницы.