При разработке приложений на Silverlight, рано или поздно встает вопрос о доступе к данным, которые, как известно, в большинстве случаев хранятся в базе данных. Вообще в наши дни ни один крупный проект не обходится без хранилища определенных данных, значит уметь получать и записывать информацию просто необходимо. Так как SL - клиентская платформа, то о прямом доступе к базе данных речи не идет - любой более-менее опытный хакер сможет взломать протокол аутенфикации и тем самым получить прямой доступ к БД! Как же быть?! Ответ прост: Веб сервисы.
Веб сервисы уже достаточно давно используются в бизнес-решениях, потому что хорошо себя зарекомендовали как платформенно-независымый посредник между данными и _любыми_ программами, способными анализировать XML. Итак, перейдем к делу.
Для начала необходимо создать веб службу на .NET 3.5. Именно с этой версии фреймворка пользователи получили возможность получать данные не только в формате XML, а еще и JSON. Обо всех преимуществах JSON я сейчас говорить не буду, но поверьте наслово, это намного удобнее. Как создать веб службу, пригодную для использования с Silverlight, читайте здесь.
Итак, создаем новый SL проект, или открываем уже созданный. Необходимо создать прокси-класс
для вызова веб службы, для этого щелкаем на References -> Add Web Reference -> Вводим адрес *.asmx файла (URL вашего сервиса) и щелкаем Go.

Также можно провести поиск на локальной машине или в текущем решении (Solution). В любом случае, должен отобразиться список всех найденных сервисов, выбираем нужный, вводим любое пространство имен и жмем OK. Все это проделывается в VS Orcas, если таковой не имеется, то используйте slwsdl.exe для генерации прокси-класса.

Перейдем к коду. Добавляем в Page.xaml.cs пространство имен: using WebService.services; - здесь WebService это название проекта, а services - имя пространство, которое вы указали при добавлении ссылки на службу. Т.к. я использую свою кнопку, то добавляю ссылку и на нее - using SP.SLControls;. Добавляем в Page.xaml два текстовых элемента: первый будет отображать статус, а второй - результат вызова веб сервиса. У меня это tbStatus и tbResult соответственно. Вот как выглядит Page_Loaded:
public void Page_Loaded(object o, EventArgs e) {
// Required to initialize variables
InitializeComponent();
Button btn = new Button();
btn.ButtonText = "Тест веб сервиса";
btn.MouseLeftButtonDown +=
new MouseEventHandler(btn_MouseLeftButtonDown);
//Плейсхолдер для удобства размещения
//кнопки; не обязательно
plaсeholder.Children.Add(btn);
}
Итак, понятно, что щелчок на кнопке вызовет btn_MouseLeftButtonDown, в котором
мы вызываем службу; я использую свою службу, которая возвращает массив из 6
строк в формате JSON:
void btn_MouseLeftButtonDown(object sender, MouseEventArgs e) {
//Создаем экземпляр прокси класса службы
QuestionService qs = new QuestionService();
try {
tbStatus.Text = string.Format("Вызов {0}\r\n",
qs.Url);
//Используем метод для асинхроннго
//вызова службы;
//Назначаем функцию, которая будет
//обрабатывать ответ
IAsyncResult iar =
qs.BeginGetQuestionLevel1(
new AsyncCallback(OnJsonDownload), qs);
if (!iar.IsCompleted) tbStatus.Text +=
"Ожидание ответа от сервера...";
} catch (Exception ex) {
tbStatus.Text += ex.ToString();
}
}
И, наконец, реализуем функцию, отвечающую за обработку ответа:
public void OnJsonDownload(IAsyncResult iar) {
try {
//С помощью свойства AsyncState
//извлекаем объект веб службы
//и получаем возвращенные данные
string[] questions =
((QuestionService)iar.AsyncState).EndGetQuestionLevel1(iar);
//Отображаем результат
tbResult.Text += "Вопрос: \n" + questions[0];
tbResult.Text += "\nОтвет 1: " + questions[1];
tbResult.Text += "\nОтвет 2:" + questions[2];
tbResult.Text += "\nОтвет 3" + questions[3];
tbResult.Text += "\nОтвет 4" + questions[4];
tbResult.Text += "\nПравильный ответ:" +
questions[5];
} catch (Exception ex) {
tbStatus.Text += ex.Message.ToString();
} finally {
tbStatus.Text += "Готово";
}
}


Как видите, напрямую посылать SOAP-сообщение нам нигде не пришлось, использовался только объектно-ориентированный подход, это намного упрощает использование веб служб в Silverlight, да и в .NET вообще.
Как было отмечено, метод вызывался асинхроно, для синхронного вызова нам понадобиться только 1 функция, т.е. функции-обработчика не будет:
void btn_MouseLeftButtonDown(object sender, MouseEventArgs e) {
//Создаем экземпляр прокси класса службы
QuestionService qs = new QuestionService();
try {
string[] questions = qs.GetQuestionLevel1();
tbResult.Text += "Вопрос: \n" + questions[0];
tbResult.Text += "\nОтвет 1: " + questions[1];
tbResult.Text += "\nОтвет 2:" + questions[2];
tbResult.Text += "\nОтвет 3" + questions[3];
tbResult.Text += "\nОтвет 4" + questions[4];
tbResult.Text += "\nПравильный ответ:" +
questions[5];
} catch (Exception ex) {
tbStatus.Text += ex.ToString();
}
}
На первый взгляд кажется, что такой подход проще и короче, но при синхронном вызове ваше приложение становиться недоступным для взаимодействия с пользователем, да и вообще оно "зависает" до получения ответа - даже анимация проигрываться не будет! Какой метод использовать - решать вам, но асинхронный вызов действительно более удобный и гибкий, и именно его я советую использовать в проектах.
Стоит сказать, что веб служба должна находиться в том же домене, что и SL-приложение, т.к. СЛ не поддерживает кроссдоменный вызов. Это ограничение планируют снять уже в первой бэте Silverlight 2.0, так что пока придется повременить с юзанием чужих служб или использовать прокси класс, находящийся в одном домене с вашей программой, который возмет на себя вызов удаленной службы и возвратит данные клиенту. Об этом я еще напишу поподробнее. А пока можете скачать исходники для изучения.