Взаимодействие Silverlight приложения с PHP


Достать нынче дешевый Windows хостинг легко и дорого, а создавать Silverlight клиент-серверные приложения хочется. Собственно,  тем и занимаюсь последнее время. Так как Linux хостинг у меня уже есть, решил его использовать для этих целей.

Итак, опишем задачу. Silverlight приложение позволяет вводить текст и отсылать его на сервер, где эти данные обрабатываются PHP скриптом – вычисляется MD5 хеш, который отсылается клиенту, полученные данные отображаются в ТеxtBox.

Примечание: В  Silverlight 4 RC функций по вычислению MD5 хеша все еще нет, хотя при непродолжительном поиске можно найти готовые классы.

Создание клиента

Для начала создадим стандартный проект  Silverlight Application. Добавим  в главную и единственную форму: TextBox для ввода отсылаемых данных, кнопку, которая инициирует отсылку и TextBlock который и будет отображать ответ, открываем MainPage.xaml и добавляем следующий текст:

<UserControl x:Class="SilverlightClient.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White"
          Width="400" Height="300">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="90" />
            <ColumnDefinition Width="285*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="72*" />
            <RowDefinition Height="50" />
            <RowDefinition Height="25" />
            <RowDefinition Height="153*" />
        </Grid.RowDefinitions>
        <TextBlock Text="Данные:" Grid.Row="1" Grid.Column="0"
                   VerticalAlignment="Center" HorizontalAlignment="Right"/>
        <TextBlock Text="MD5:" Grid.Row="2" Grid.Column="0"
                   VerticalAlignment="Center" HorizontalAlignment="Right"/>
        <TextBox x:Name="inputText" Grid.Column="1" Grid.Row="1"
                 BorderBrush="Black" BorderThickness="1"
                 TextWrapping="Wrap"/>
        <TextBox x:Name="ReceivedText" Text="Empty" Grid.Column="1" Grid.Row="2"
                 BorderBrush="Black" BorderThickness="1"/>
        <Button x:Name="SendButton" Content="Отправить" Width="100" Height="25"
                HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Grid.Column="1"
                Click="SendButton_Click"/>
    </Grid>
</UserControl>

С разметкой формы закончили, перейдем к разработке клиентской логики.

  1. По нажатию кнопки «SendButton» отправляем текст из текстового поля «inputText».
  2. При получении данных отображаем их в поле «ReceivedText».

Двойной клик мыши по кнопке «SendButton» автоматически создаст обработчик события Click,  остается только его наполнить смыслом:

// Если поле ввода пустое, то ничего не делаем
if (String.IsNullOrEmpty(inputText.Text)) return;
// Создаем экземпляр класса WebClient
var client = new WebClient();
// Адрес серверной части
var uri = new Uri("http://localhost/index.php");
// задаем обработчик события UploadStringCompleted
client.UploadStringCompleted += new UploadStringCompletedEventHandler(UploadStringCompleted);

// передаем данные на сервер
client.UploadStringAsync(uri, inputText.Text);

Чуть выше мы реализовали метод для отправки данных, и там же подписались на событие UploadStringCompleted. Это событие возникает когда данные отправлены и получен ответ от сервера, для проверки этого достаточно добавить в index.php команду sleep(10), это добавить паузу 10 секунд в обработку запроса. В методе

void UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)

мы и реализуем логику:

void UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                ReceivedText.Text = e.Result;
            }
        }

А логика простая, если не возникло ошибок, то отображаем содержимое в ReceivedText.

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

Получили код который отсылает данные на сервер. Серверную часть напишем на PHP, потому как WCF сервис в Apache ну никак не захостится. Создаем файл index.php со следующим содержимым:

<?php
$data = file_get_contents('php://input');
if ($data) {
	echo md5($data);
}
else {
	echo "";
}
?>

Тут все просто для PHP программиста, а вот для меня этот код стоил 2 часов времени, если не больше. Дело в том, что отсылая данные на сервер и не указывая дополнительных заголовков, они не попадают в массив $_POST. Добраться до них можно только таким способом – file_get_contents(‘php://input’). По полученным данным вычисляется хеш md5 и возвращается обратно.

Примечание

Для того чтобы клиентское приложение могло обращаться к серверу рядом с index.php нужно создать файл crossdomain.xml со следующим содержимым:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

Скрин запущенного приложения

Исходники проекта

В следующей статье усложним задачу и будем передавать JSON данные из Silverlight в PHP.

,

  1. #1 by Денис on 2010.03.22 - 10:09

    Достать нынче дешевый Windows хостинг легко и дорого

    Да здравствует великий и могучий русский речь :)

    Ну это я так, придираюсь, статья интересная, мало ли, пригодится.

    PS. Вопрос возник – а нельзя для этого всего веб-сервисы заюзать. На PHP же можно сервис реализовать, а из Silverlight’а его дернуть?

  2. #2 by AlexandrYZ on 2010.03.22 - 10:26

    Это игра слов ;-)

    До веб-сервисов на PHP я еще не дошел, но про это я тоже напишу.

  3. #3 by Матвей on 2010.04.13 - 16:26

    Привет очень интересный пост, я скачаал исходники но незнаю как запустить это приложение чтоб посмотреть как оно в дейстивии работает)) почему то не могу я к этому файлику обратиться (index.php)…в двух словах мог бы рассказать как php и silverlight проекты)) с уважением, Матвей)

(никто не узнает)