Использование веб сервисов с Silverlight

При разработке приложений на 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, так что пока придется повременить с юзанием чужих служб или использовать прокси класс, находящийся в одном  домене с вашей программой, который возмет на себя вызов удаленной службы и возвратит данные клиенту. Об этом я еще напишу поподробнее. А пока можете скачать исходники для изучения.

Posted on 19.12.2007 16:58:49 by admin

Permalink | Комментарии (3) | Post RSSRSS comment feed |

Categories: Silverlight | Web Services

Tags: ,

Оценок нет

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Похожие записи

Комментарии

августа 26. 2008 00:46

Alexander

Александр, ссылка на архив исходников в конце статьи недоступна.. Поправьте пожалуйста.

Alexander

августа 26. 2008 12:51

Admin

Исправил

Admin ru

ноября 14. 2008 12:26

Антон

Статья отличная, но архив с исходниками кривой Smile

Антон

Добавить комментарий


(Отображает Gravatar)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Предпросмотр

ноября 21. 2008 01:05