Работа с 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().