Взаимодействие 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.
  • +2

2 комментария

avatar
  • kevin
  • 0
Получить пришедшие данные от клиента можно также в массиве $HTTP_RAW_POST_DATA. Преимуществом также является то, что в данный массив попадает ващще все, что приходит на сервер, даже файлы. В массив $_POST попадают только именованные данные, которые отправлялись с помощью формы на HTML.
avatar
  • eye-ru
  • 0
Спасибо буду иметь в виду.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.