Работа с API веб-сервисов
Рассмотрим приложение для выполнения поиска в Twitter, "Поиск в Twitter, пример использования бесконечной прокрутки в LongListSelector" (этот пример можно скачать здесь: http://code.msdn.microsoft.com/TwitterSearch-Windows-b7fc4e5e). Его особенность заключается в том, что оно взаимодействует с сервисом Twitter методами, не требующими авторизации, выполняя запросы к общедоступным механизмам службы. В частности, интересующая нас функциональность данного приложения (рис. 31.2.) реализована в файле TwitterViewModel.cs.
В целом, приложение реализовано с помощью уже известного вам MVVM-подхода, в файле TwitterModel.cs определена структура данных, которая используется при формировании отдельного элемента, полученного от сервиса, TwitterViewModel (Листинг 16.1) – это модель представления, с помощью механизма привязки данных связанная с MainPage.xaml, где, записи выводятся в списке, с реализацией загрузки дополнительного содержимого при достижении последней записи, присутствующей в настоящий момент в списке
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.ServiceModel.Syndication;
using System.Windows;
using System.Xml;
using TwitterSample.Model;
namespace TwitterSample.ViewModels
{
public class TwitterViewModel:INotifyPropertyChanged
{
const string SEARCH_URI = "http://search.twitter.com/search.atom?q={0}&page={1}";
private bool _isLoading = false;
public bool IsLoading
{
get
{
return _isLoading;
}
set
{
_isLoading = value;
NotifyPropertyChanged("IsLoading");
}
}
public TwitterViewModel()
{
this.TwitterCollection = new ObservableCollection<TwitterSearchResult>();
this.IsLoading = false;
}
public ObservableCollection<TwitterSearchResult> TwitterCollection
{
get;
private set;
}
public void LoadPage(string searchTerm, int pageNumber)
{
if (pageNumber == 1) this.TwitterCollection.Clear();
IsLoading = true;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri
(String.Format(SEARCH_URI, searchTerm, pageNumber)));
request.BeginGetResponse(new AsyncCallback(ReadCallback), request);
}
private void ReadCallback(IAsyncResult asynchronousResult)
{
try
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
//только для демонстрационных целей, не следует отправлять приложение
на сертификацию с этой строкой.
System.Threading.Thread.Sleep(700);
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("georss", "http://www.w3.org/2001/XMLSchema-instance");
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlReaderSettings xset = new XmlReaderSettings();
xset.ConformanceLevel = ConformanceLevel.Fragment;
XmlReader rdr = XmlReader.Create(reader, xset, context);
SyndicationFeed feed = SyndicationFeed.Load(rdr);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
foreach (var item in feed.Items)
{
this.TwitterCollection.Add(new TwitterSearchResult()
{
Author = item.Authors[0].Name,
ID = GetTweetId(item.Id),
Tweet = item.Title.Text,
PublishDate = item.PublishDate.DateTime.ToLocalTime(),
AvatarUrl = item.Links[1].Uri.AbsoluteUri
});
}
IsLoading = false;
});
}
}
catch (Exception e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Network error occured " + e.Message);
});
}
}
private string GetTweetId(string twitterId)
{
string[] parts = twitterId.Split(":".ToCharArray());
return parts[2].ToString();
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
Листинг
31.1.
Файл TwitterViewModel.cs
Для выполнения запросов к службе используется URI следующего вида: http://search.twitter.com/search.atom?q={0}&page={1} (подробности о поиске в Twitter можно найти здесь: https://dev.twitter.com/docs/api/1.1/get/search/tweets, нужно учесть, что API как этого сервиса, так и других периодически обновляется, в частности, в API Twitter наблюдается переход от формата ATOM, который используется в данном примере для поиска, к формату JSON, в частности, для вызова операции поиска будет применятся ссылка следующего вида: https://api.twitter.com/1.1/search/tweets.json, дополнительные подробности можно найти здесь: https://dev.twitter.com/docs/using-search).
Вышеозначенная ссылка для доступа к службе используется при построении запроса для HttpWebRequest, который находится в методе LoadPage(), вызываемом из кода страницы MainPage.xaml. Разбор результатов запроса осуществляется в методе ReadCallBack().
