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

Wednesday, 24 February 2010 16:00 ivanoff

Этот пост будет посвящен описанию создания справочника на сайте SharePoint с использованием WCF-сервиса, библиотеки jQuery и плагинов к ней.

Введение

В рамках запуска нового сайта ИНГГ СО РАН, который построен на 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);
                }
            }
        }

Контрол JqGridPhoneBookControl.ascx практически не содержит серверного кода, за исключением значения скрытого тега <input>, с помощью которого через свойства веб-части передается номер подразделения для начальной фильтации.

<input type="hidden" id="divisionNumberFromWebpart" value='<%=DivisionNumber %>'/>
<table id="phoneBookGrid"></table>
<div id="phoneBookPager"></div>
<div id="employeeInfoContainer">
    ...
</div> 

Сервис, предоставляющий данные, имеет следующий интерфейс.

    [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);
    }

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; }
    }

Код сервиса разворачивается в 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>

Для корректной работы 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');
                }
            }
        });

jqGrid принимает json-объект с определенными именами свойств, однако можно настроить jsonReader и передавать какой угодно json-объект. В нашем случае – это JqGridResult.

        var gridJsonReader = {
            root: "Records",
            page: "CurrentPage",
            total: "TotalPages",
            records: "TotalRecords",
            repeatitems: false,
            id: "Id"
        };

При щелчке по строке таблицы вызывается функция 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);
            ...            
        }

Фотография сотрудника берется из веб-сервиса с помощью GET-запроса

function GetImage(employeeId) {
        $("#employeeImage").attr("src", "/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetPhoto?employeeId=" + employeeId);
    }

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

В данной статье не приведен код, реализующий доступ к данным. Могу лишь сказать, что это простая реализация паттерна Репозиторий на Linq To SQL. Для фильтрации, поиска и постраничного вывода использован интерфейс IQueryable<T>.

Как оказалось, нет ничего сложного в реализации и развертывании решений на jQuery и WCF под SharePoint.

Однако, если SharePoint  работает на IIS7, то может возникнуть проблема, на решение которой мне пришлось потратить некоторое время.

После развертывания решения на production-сервере, выдавалась 404 ошибка при запросах на URL типа “~/_layouts/IPGG.IntegrationSystem/PhoneBookService.svc/GetRecord”.

Решение состоит в том, что необходимо зарегистрировать обработчник запросов для .svc. По умолчанию, в IIS7 для SharePoint-сайта этого не сделано.

image

Tags:   , , ,
Categories:   .NET | jQuery | SharePoint | Web
Действия:   E-mail | Permalink | Comments (0) | RSS комментариевRSS comment feed


Денис Иванов

Занимаюсь разработкой приложений для веб на платформе .NET