SharePoint 2010 и SilverLight: REST
Когда мы рассматривали общий обзор возможностей интеграции Silverlight и SharePoint 2010, то упоминали о поддержке REST. Действительно, если Вы планируете наладить взаимодействие со списком с фиксированной схемой, то можете получить доступные списки на заданном сайте, обратившись к службе по следующему адресу (аналогичному): http://localhost/_vti_bin/ListData.svc/. Получить данные из конкретного списка (например, Media), можно, используя следующую ссылку: http://sbaydach64/_vti_bin/ListData.svc/Media. Если Вы хотите получить конкретный элемент из списка, то ссылка будет выглядеть аналогично этой: http://sbaydach64/_vti_bin/ListData.svc/Media(1). Во всех случаях, данные возвращаются в формате Atom, а, следовательно, базируются на XML.
Попробуем переписать предыдущий пример так, чтобы Web-часть, отображающая видео, позволяла задавать имя библиотеки (а не файла), содержащей видеоматериалы. При этом, изменим Silverlight-приложение таким образом, чтобы оно позволяло выбрать любой видео файл из библиотеки, в режиме реального времени. То есть, попробуем реализовать примитивную видео библиотеку.
Для начала, реализуем новый интерфейс для Silverlight-приложения:
<UserControl x:Class="SharePointMediaWebPart.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="UserControl_Loaded">
<StackPanel x:Name="LayoutRoot" Background="White"
Orientation="Horizontal">
<ListBox Name="myList" SelectionChanged="myList_SelectionChanged">
</ListBox>
<MediaElement Name="myMedia" AutoPlay="True"></MediaElement>
</StackPanel>
</UserControl>
Тут мы изменили главный контейнер, в который добавили ListBox, необходимый для выдачи списка файлов. Кроме того, мы определили два обработчика для событий Load и SelectionChanged. Первый обработчик будет выбирать данные из указанного списка, и заполнять ListBox. Второй обработчик позволит устанавливать новый источник для медиа элемента.
Перейдем к реализации кода.
Внесем изменения в конструктор класса MainPage, добавив код, выбирающий параметр с именем списка из коллекции параметров для встраиваемого компонента (удалите аналогичный код из Application_Startup – в этом примере его там держать не удобно).
private String curList="";
public MainPage()
{
InitializeComponent();
if (App.Current.Host.InitParams.ContainsKey("media"))
{
curList = App.Current.Host.InitParams["media"];
}
}
Реализация обработчика события SelectionChanged также будет простой:
private void myList_SelectionChanged(
object sender, SelectionChangedEventArgs e)
{
myMedia.Source = new
Uri(String.Format("http://localhost/{0}/{1}",
curList, myList.SelectedValue.ToString()),
UriKind.Absolute);
}
(можно было использовать контекст, чтобы выбрать адрес сайта из коллекции)
Тут мы формируем ссылку на файл, лежащий в нашей библиотеке, и устанавливаем источник для MediaElement.
Давайте рассмотрим код последнего обработчика:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (curList.Length>0)
{
WebClient client = new WebClient();
client.OpenReadCompleted +=
new OpenReadCompletedEventHandler(
client_OpenReadCompleted);
client.OpenReadAsync(
new Uri(string.Format(
"http://sbaydach64/_vti_bin/ListData.svc/{0}",
curList),
UriKind.Absolute));
}
}
Тут мы устанавливаем асинхронное соединение со службой, используя имя списка, передаваемого в параметрах. Как только данные будут получены, вызовется метод client_OpenReadCompleted, который и будет реализовывать всю работу по обработке XML и заполнению ListBox.
Прежде, чем перейти к написанию кода client_OpenReadCompleted, создайте в SharePoint библиотеку с любым именем (например, Media), и загрузите в нее несколько медиа файлов. После этого, выполните команду, аналогичную этой:
http://localhost/_vti_bin/ListData.svc/Media
Ниже я привожу часть XML, который я получил, выполняя команду выше:
<entry m:etag="W/"4"">
<id>http://sbaydach64/_vti_bin/ListData.svc/Media(1)</id>
<title type="text">Test 1</title>
<updated>2010-02-10T16:12:06+02:00</updated>
. . . . . .
<d:ContentTypeID>0x0101009110D2200BDC0F429ED6372AF0A68C01</d:ContentTypeID>
<d:ContentType>Document</d:ContentType>
<d:Created m:type="Edm.DateTime">2010-02-10T16:10:13</d:Created>
<d:CreatedByID m:type="Edm.Int32">1073741823</d:CreatedByID>
<d:Modified m:type="Edm.DateTime">2010-02-10T16:12:06</d:Modified>
<d:ModifiedByID m:type="Edm.Int32">1073741823</d:ModifiedByID>
<d:CopySource m:null="true"></d:CopySource>
<d:ApprovalStatus>0</d:ApprovalStatus>
<d:Path>/Media</d:Path>
<d:CheckedOutToID m:type="Edm.Int32" m:null="true"></d:CheckedOutToID>
<d:Name>Test 1.wmv</d:Name>
<d:VirusStatus>26246026</d:VirusStatus>
<d:IsCurrentVersion m:type="Edm.Boolean">true</d:IsCurrentVersion>
<d:Owshiddenversion m:type="Edm.Int32">4</d:Owshiddenversion>
<d:Version>1.0</d:Version>
<d:Title>Test 1</d:Title>
</m:properties>
</entry>
Как видно, имя файла содержится в поле d:Name. Поскольку, в данном случае, нам другие данные и не нужны, воспользуемся простым объектом XmlReader, для выбора нужной информации. Вот как будет выглядеть наш код:
void client_OpenReadCompleted(object sender,
OpenReadCompletedEventArgs e)
{
XmlReader reader = XmlReader.Create(e.Result);
while (reader.Read())
{
if (reader.NodeType==XmlNodeType.Element)
{
if (reader.Name.Contains("Name"))
{
reader.Read();
myList.Items.Add(reader.Value);
}
break;
}
}
myList.SelectedIndex = 0;
}
Получая XML документ в качестве потока, мы используем XmlReader, для поиска нужного элемента, у которого выбираем значение.
Теперь можно откомпилировать и развернуть данный пример. Указав в качестве параметров Web-части, имя созданного списка с видео, Вы сможете увидеть работу приложения:
@10 Результат работы приложения
Если Вы разрабатываете более сложный компонент, то для взаимодействия с XML данными можно использовать один из следующих подходов:
· Используйте прокси классы, созданные Visual Studio – для этого добавьте ссылку на службу с помощью Add Service Reference. Прокси классы будут сгенерированы автоматически. В нашем примере они не очень помогут, так как мы не знаем имя списка;
· Используйте механизмы сериализации (уж не знаю, как это правильно пишется по-русски) – сложно, но эффективно. Зная, что в нашем списке есть определенные поля, мы могли бы не делать привязку к конкретному списку;
· Используйте XLinq – нужно подключать библиотеки из SDK, а в данном случае это не имеет смысла;
· Используйте специальный класс из SDK (SyndicationFeed). Опять же, нужно подключать дополнительную библиотеку. Кроме того, этот класс отказался работать с контентом, возвращаемым SharePoint (хотя должен работать с Atom).
