Pull to refresh

SharePoint + WCF + jqGrid + jQueryUI. Создание справочника на сайте SharePoint

Reading time 7 min
Views 3.6K
Этот пост посвящен описанию создания справочника на сайте SharePoint с использованием WCF-сервиса, библиотеки jQuery и плагинов к ней.

image



Введение


В рамках запуска нового сайта ИНГГ СО РАН, который построен на SharePoint Server 2007, было решено разработать новую версию телефонного справочника сотрудников. Для клиентской части был выбран jqGrid в качестве элемента для таблицы сотрудников и jQueryUI для отображения подробной информации о сотруднике. Данные клиентская часть получает от RESTful веб-сервиса, реализованного на WCF, который развернут тут же, на сайте SharePoint.

Пара картинок того, что получилось:

image
image


WCF-сервис и PhoneBookWebpart


Справочник сотрудников отображается на странице веб-частей на сайте SharePoint в виде веб-части, содержимое которой загружается из ascx-контрола.
protected override void CreateChildControls()
{
  if (!_error)
  {
    try
    {
      base.CreateChildControls();

      if (!this.WebPartManager.DisplayMode.AllowPageDesign)
      {
        var gridControl =
          (JqGridPhoneBookControl)Page.LoadControl(
                   "~/_controltemplates/IPGG.IntegrationSystem/PhoneBook/JqGridPhoneBookControl.ascx");
        gridControl.DivisionNumber = DivisionNumber;
        Controls.Add(gridControl);
      }
    }
    catch (Exception ex)
    {
      HandleException(ex);
    }
  }
}


* This source code was highlighted with Source Code Highlighter.

Контрол JqGridPhoneBookControl.ascx практически не содержит серверного кода, за исключением значения скрытого тега <input>, с помощью которого через свойства веб-части передается номер подразделения для начальной фильтации.
<input type="hidden" id="divisionNumberFromWebpart" value='<%=DivisionNumber %>'/>
<table id="phoneBookGrid"></table>
<div id="phoneBookPager"></div>
<div id="employeeInfoContainer">
  ...
</div>


* This source code was highlighted with Source Code Highlighter.

Сервис, предоставляющий данные, имеет следующий интерфейс.
[ServiceContract]
public interface IPhoneBookService
{
  [OperationContract]
  [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
  JqGridResult<Employee> GetAllRecordsForJqGrid();

  [OperationContract]
  [WebInvoke(Method = "GET")]
  Stream GetPhoto(int employeeId);

  [OperationContract]
  [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
  Employee GetRecord(int employeeId);
}


* This source code was highlighted with Source Code Highlighter.

JqGridResult – класс, возвращаемый методом GetAllRecordsForJqGrid и принимаемый reader’ом jqGrid.
[DataContract]
public class JqGridResult<T>
{
  [DataMember]
  public int CurrentPage { get; set; }
  [DataMember]
  public int TotalPages { get; set; }
  [DataMember]
  public int TotalRecords { get; set; }
  [DataMember]
  public List<T> Records { get; set; }
}


* This source code was highlighted with Source Code Highlighter.

Код сервиса разворачивается в GAC вместе с остальными сборками wsp-решения для SharePoint, svc-файл веб-сервиса помещается в подпапке папки c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS\ вместе с файлом web.config, в котором необходимо указать webHttpBinding
<?xml version="1.0"?>
<configuration>
 <system.serviceModel>
  <behaviors>
   <serviceBehaviors>
    <behavior name="serviceBehavior">
     <serviceMetadata httpGetEnabled="true"/>
     <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
   </serviceBehaviors>
   <endpointBehaviors>
    <behavior name="endpointBehavior">
     <webHttp/>
    </behavior>
   </endpointBehaviors>
  </behaviors>
  <services>
   <service name="IPGG.IntegrationSystem.Web.Services.PhoneBookService" behaviorConfiguration="serviceBehavior">
    <endpoint address="" binding="webHttpBinding" contract="IPGG.IntegrationSystem.Web.Services.IPhoneBookService" behaviorConfiguration="endpointBehavior"/>
   </service>
  </services>
 </system.serviceModel>
</configuration>


* This source code was highlighted with Source Code Highlighter.

Для корректной работы WCF-сервисов в приложении SharePoint, необходимо установить SPWCFSupport, либо реализовать подобный код у себя в решении. Подробности зачем это нужно – здесь.

jqGrid и jQueryUI


Содержимое таблицы phoneBookGrid (см. JqGridPhoneBookControl.ascx) формируется с помощью jqGrid, плагина к jQuery, который берет данные из WCF-сервиса, описанного выше, посредством ajax-запроса, в формате json.
$("#phoneBookGrid").jqGrid({
  url: "/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetAllRecordsForJqGrid",
  datatype: "json",
  jsonReader: gridJsonReader,
  colNames: columnNames,
  colModel: columns,
  width: 850,
  height: 460,
  shrinkToFit: false,
  pager: "#phoneBookPager",
  rowList: [20, 50, 100, 1000],
  onSelectRow: GetEmployeeDetails,
  loadComplete: gridLoaded
}).navGrid("#phoneBookPager", { add: false, edit: false, del: false, search: false, refresh: true }).filterToolbar();

$("#phoneBookGrid").jqGrid("navButtonAdd", "#phoneBookPager", {
  caption: "Отобразить/Скрыть столбцы",
  title: "Изменить порядок столбцов",
  onClickButton: function() {
    $("#phoneBookGrid").jqGrid("columnChooser");
  }
});

$("#employeeInfoContainer").dialog({
  bgiframe: true,
  modal: true,
  autoOpen: false,
  width: 550,
  resizable: false,
  close: ClearDialog,
  buttons: {
    Ok: function() {
      $(this).dialog('close');
    }
  }
});


* This source code was highlighted with Source Code Highlighter.

jqGrid принимает json-объект с определенными именами свойств, однако можно настроить jsonReader и передавать какой угодно json-объект. В нашем случае – это JqGridResult.
var gridJsonReader = {
  root: "Records",
  page: "CurrentPage",
  total: "TotalPages",
  records: "TotalRecords",
  repeatitems: false,
  id: "Id"
};


* This source code was highlighted with Source Code Highlighter.

При щелчке по строке таблицы вызывается функция GetEmployeeDetails, которая отправляет еще один ajax-запрос к веб-сервису и отображает данные в модальном диалоге jQueryUI
function GetEmployeeDetails(id) {
  $("#employeeInfoContainer").dialog("open");
  $.ajax({
    url: "/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetRecord",
    data: "employeeId=" + id,
    success: ProcessInfo,
    error: ProcessError
  });
  GetImage(id);
  ...      
}


* This source code was highlighted with Source Code Highlighter.

Фотография сотрудника берется из веб-сервиса с помощью GET-запроса
function GetImage(employeeId) {
    $("#employeeImage").attr("src", "/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetPhoto?employeeId=" + employeeId);
  }


* This source code was highlighted with Source Code Highlighter.


Вместо заключения


В данной статье не приведен код, реализующий доступ к данным. Могу лишь сказать, что это простая реализация паттерна Репозиторий на Linq To SQL. Для фильтрации, поиска и постраничного вывода использован интерфейс IQueryable<T>.
Как оказалось, нет ничего сложного в реализации и развертывании решений на jQuery иWCF под SharePoint.
Однако, если SharePoint  работает на IIS7, то может возникнуть проблема, на решение которой мне пришлось потратить некоторое время.
После развертывания решения на production-сервере, выдавалась 404 ошибка при запросах на URL типа “~/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetRecord”.
Решение состоит в том, что необходимо зарегистрировать обработчник запросов для .svc. По умолчанию, в IIS7 для SharePoint-сайта этого не сделано.

image

P.S. Спасибо хабраюзерам Atreides07 и Atv за помощь в освоении Хабра.

UPD: Перенес в блог «Веб-разработка».
UPD2: Пост в моем блоге
Tags:
Hubs:
+23
Comments 11
Comments Comments 11

Articles