Как добавить файла кода ( codefile ) для страницы SharePoint, котораяего не поддерживает, а также – Обход невозможности добавленияобработчика серверного события в разметке страницы SharePoint, неподдерживающей файл кода.

Решаемая проблема: Страницы сайта SharePoint храняться в базе и не поддерживает раздельный файл кода. При добавлении в <%@ Page … CodeFile="Default.aspx.cs" %> атрибута CodeFile SharePoint ругнется с ошибкой Parser Error.
Надеюсь данная статья сэкономит ваше время. Ничего подобного в сети я пока не нашел.
Как добавить раздельный файл кода? Я применяю два подхода:
  1. Добавить на страницу ваш кастомный элемент управления, который подключается к нужным событиям страницы и элементам управления через <%@ Register %>.
  2. Создать вашу страницу, наследующую Microsoft.SharePoint.WebPartPages.WebPartPage и прописать ее в атрибуте inherits в <%@ Page … inherits="Company.MyItems.MySpPage" %>
На словах, решается это так:
  1. Добавляем в семейство сайтов нашу сборку с нужными классами.
    Обычно в C:\inetpub\wwwroot\wss\VirtualDirectories\80\bin.
  2. Прописываем в файле разметки элемент управления или полностью переопределяем класс страницы.
Инструменты:
  1. Visual Studio для правки кода.
  2. SharePoint Designer для правки страниц, хранящихся в базе данных SharePoint.
Опционально: Очень удобно в Visual Studio 2008 использовать VSeWSS 1.3, но, по опыту, первый раз вам придется потратить нервы, чтобы его настроить, так что если вам срочно, то совсем не стоит заморачиваться. Если не срочно, то читайте у меня здесь или погуглите хорошенько.
Нюансы: Я не сторонник класть сборку в GAC и кладу ее в папку bin семейства сайтов (обычно C:\inetpub\wwwroot\wss\VirtualDirectories\80\bin), что требует небольшого изменения web.config семейства сайтов.
В web.config ‘е сайта находим
<SharePoint>
<SafeControls>
и добавляем запись
<SafeControl Assembly="MyItems" Namespace="Company.MyItems" TypeName="*" Safe="True" />
Вот для этого удобен VSeWSS 1.3, хотя можно и ручками.
Особенности написания кода:
* SharePoint на даст вам переопределять обработчики событий, например OnInit, поэтому используйте прикрепление ваших обработчиков в конструкторе, например
public MySpPage()
{
    Init += new EventHandler(mySpPage_Init);
}
* Нахождение контролов страниццы по их ID часто не работает. Это обходиться при помощи самописного контрола-посредника, который предоставляет нужный вам контрол. Для этого целевой контрол может класться внутрь посредника (наследуйте в этом случае посредника от Panel), но поскольку SharePoint Designer не переваривает эту ситуацию, то я размещаю посредника сразу перед целевым контролом.
Не забудте в коде нахождения игнорировать LiteralControl, который создается парсером разметки HTML / ASP.NET.
У меня посредники часто сами содержат логику, добавляющую новые действия в целевой контрол. В этом случае я их называю “Экстендерами”.
Часто перед целевым контролом может стоять подряд несколько экстендеров и я учитываю в коде нахождения, что помимо литералов могут попасться другие посредники перед целевым контролом.
Примеры использования экстендеров: редирект после удачного сохранения в SqlDataSource, добавление пустого айтема в начало списка DropDownList и тд и тп.
Прикрепление серверного обработчика в разметке страницы, не поддерживающей раздельный файл кода :
SharePoint нам не даст задать серверный обработчик в разметке. Он нам выдаст ошибку
Parser Error
Parser Error Message: The event handler 'OnUpdating' is not allowed in this page.
Ну и напрасно. Давайте использовать описанные выше выше экстендеры для задания обработчиков нужных серверных событий.
Это даже лучше из-за предоставляемой ими инкапсуляции и замечательной гибкости.
Хотя мне кажется, что всетаки, какие-то серверные события я в разметке присоединял. Попробую если опять появиться какой-то проект по SharePoint.
Важные замечания по кодированию экстендера или простого контрола-посредника:
  • Найти корректно целевой контрол. Нюансы описаны чуть выше. Это игнорирование LiteralControl и других экстендеров.
  • Нужна правильная точка прикрепления логики экстендера в целевом контроле.
    Я предлагаю в конструкторе экстендера прекреплять обработчик к событию Init родительского контрола:
    this.Parent.Init += new EventHandler(Parent_Init);
    Это подайдет в 98% случаев.
    Среда гарантирует, что событие Init родителя, в отличии от события Load всегда сработает позже события Init потомка в дереве контролов.
    Можно использовать удобное событие Page.InitComplete, но тогда вы не сможете подцепиться к контролам, которые находяться внутри шаблона, шаблонного элемента управления, например внутри
    <asp:FormView … >
        <InsertItemTemplate>…
    А вот в обработчике Parent_Init мы уже вольны с целевым контролом делать все что захотим. Прекреплять события, изменять свойства и тд.
На этом все :
Экономлю время, поэтому…
Теперь давайте я буду добавлять в статью информацию по необходимости, тк подозреваю, что заинтересованных лиц в моей стране не много :).
Примеры кода подготовлю, если будут непонятки.
Самому мне нужно некоторое время, чтобы забыть статью и прочитать ее, как бы со стороны, чтобы увидеть что в ней изложено не слишком доступно.

Комментарии

Популярные сообщения из этого блога

A4tech. Мышь не найдена. Пожалуйста, подсоедините мышь.

Вывод в cmd или bat пустой строки.

Ускорение компиляции Visual Studio Solution методом "Copy Local = False".