Использование веб сервисов с 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 | Комментарии (2) | Post RSSRSS comment feed |

Categories: Silverlight | Web Services

Tags: ,

Оценок нет

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

Создание веб сервисов

Вашему Silverlight приложению требуется доступ к данным? Тогда веб сервисы! Сегодня я расскажу о создании Silverlight-совместимого сервиса. Все действия будем выполнять в VS 2008.

Итак, приступим. File - > ASP.NET Web Service Application -> вводим имя проекта и открываем файл кода сервиса (что-то вроде Service1.asmx.cs):

using System;
using System.Data;
using System.Linq;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Xml.Linq;

namespace WebServices {
    /// <summary>
    /// Summary description for Test
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]

    [WebServiceBinding(ConformsTo = 
     WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    // To allow this Web Service to be called
    //from script, using ASP.NET AJAX,
    // uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class Test : System.Web.Services.WebService {

        [WebMethod]
        public string HelloWorld() {
            return "Hello World";
        }
    }
}

Заменяем пространство имен в [WebService(Namespace = http://tempuri.org/)]  на свое, например так [WebService(Namespace = http://porubov.com)]. Расскоментируем строчку [System.Web.Script.Services.ScriptService]  чтобы можно было вызывать сервис из нашего SL-приложения. Запускаем и радуемся - наша служба уже работает!

Теперь можно перейти к написанию кода.

Обычное возвращение строки уже представлено в функции HelloWorld, как видите, ничего сложного. Теперь опишем метод с входными параметрами:

[WebMethod(Description="Возвращает
 форматированную строку в заданном количестве")]
        public string FormatString(string mess, int count) {
            mess += " - форматированная!";
            
            for (int i = 0; i < count; i++) {
                mess += " строка " + i.ToString() + "\n";
            }
            return mess;
        }

Тоже очень просто. Вообще обьявление службы отличается от обычного метода только строчкой [WebMethod] и ограничениями на входные и возвращаемые типы данных. Итак, вот что может принимать и возвращать веб служба:

  • Простые типы данных - строки, целые, числа с плавающей точкой, булевые значения, смешанные типы (например, тип даты-времени, байтовый и т.п.)
  • Массивы
  • Объекты - передаются все общедоступные свойства какого-либо объекта
  • Перечисления - типы в C#, определяемые ключевым словом enum
  • XmlNode - представляют собой часть Xml документа
  • DataSet, DataTable - применяются в основном для возврата данных из БД для последующей привязки к элементам отображения данных в .NET. Не подходит для использования в SL.

Безусловно, в классе веб службы вы можете написать намного более сложный код, который, к примеру, будет получать и записывать данные в удаленную базу данных; Никаких ограничений на обычные методы (не обьявленые как веб методы) нет. Так что вперед!

Posted on 19.12.2007 16:56:52 by Admin

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

Categories: Web Services

Tags: ,

Оценок нет

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