Как стать автором
Обновить

ASP.NET и Flex — дружба навек

Время на прочтение6 мин
Количество просмотров2.9K
Этот пост хотелось бы посвятить возможности интеграции двух платформ ASP.NET и Flex.

Предисловие

Как правило, Flash является прекрасным средством для создания насыщенных мультимедиа проектов, а с выходом ActionScript 3 и технологии Flex программировать стало одно удовольствие. При этом можно создавать и RIA, и desktop приложения (спасибо, Adobe AIR).

С другой стороны у нас ASP.NET — мощный инструмент для создания web-приложений. Можно использовать два совершенно разных подхода к построению приложения: либо использовать WebForms + Web Services, либо ASP.NET MVC, придерживаясь REST-стиля.
Прежде чем закончить лирическое отступление, хотелось бы обозначить инструменты, которые нам понадобятся.
Итак, это –
  1. Visual Studio 2010 Professional
  2. Flash Builder 4 Standard


Встречайте, FluorineFX

В качестве примера хотелось бы привести пример приложения, которое будет работать с часто обновляющимися данными и синхронизироваться с другими клиентами. Обычно в случае Flex используется либо AMF-streaming, либо RTMP-streaming. Для добавления поддержки со стороны сервера на помощь приходит библиотека FluorineFX. Сайт проекта и полезные ссылки здесь.

Готовим сервер

Перед созданием ASP.NET-приложения мы должны создать библиотеку, представляющую собой мини-сервер, инкапсулирующий в себе сервисы и логику для клиентов. Для этого создайте новый проект библиотеки на C# и назовите ServiceLibrary.
Для мониторинга активных клиентов, необходимо создать класс, наследуемый от MessagingAdapter и реализующий собой интерфейс ISessionListener.

public class AppAdapter : MessagingAdapter, ISessionListener
{
    public AppAdapter()
    {
        ClientManager.AddSessionCreatedListener(this);
    }

    #region ISessionListener Members

    public void SessionCreated(IClient client)
    {
        //Ваши действия при присоединении клиента
        client.AddSessionDestroyedListener(this);
    }

    public void SessionDestroyed(IClient client)
    {
        //Ваши действия при разъединении клиента
    }

    #endregion

    public override object Invoke(IMessage message)
    {
        //Здесь передается управление вашему коду для обработки пересылки сообщений
        return null;
    }
}

Для клиентов, работающих через remoting, создадим сервис, который и будет предоставлять API.


[RemotingService()]
public class DataService
{
    public DataService()
    {
    }

    //Данный показательный метод будет использоваться клиентами. 
    public string GetData()
    {
        return "Hello, world!";
    }
}

На этом пока что код мини-сервера достаточен для использования. Каждый экземпляр класса будет создаваться при подключении нового клиента и работать в одном и том же домене, что и ASP.NET-приложение.

Подготовка веб-приложения

Работать веб-приложение будет на ASP.NET 4. Для этого создадим новый проект в студии.
Для подключений клиентов FluorineFX использует gateway, который представляет собой не что иное, как обычную ASPX страницу, запросы на которую http-модуль Fluorine’a и будет обрабатывать. Более подробно этот вопрос мы рассмотрим чуть ниже, а пока добавим обычную ASP.NET-страницу и назовем Gateway.aspx.
Сконфигурируем web.config
<configuration>
  <configSections>
    <sectionGroup name="fluorinefx">
      <section name="settings" type="FluorineFx.Configuration.XmlConfigurator, FluorineFx" requirePermission="false"/>
    </sectionGroup>
  </configSections>
  <fluorinefx>
    <settings>
      <rtmpServer>
        <threadpool minWorkerThreads="0" maxWorkerThreads="25" idleTimeout="60000"/>
        <rtmpConnection pingInterval="0" maxInactivity="60000" maxHandshakeTimeout="0"/>
        <rtmptConnection pingInterval="5000" maxInactivity="60000" maxHandshakeTimeout="5000"/>
        <rtmpTransport receiveBufferSize="4096" sendBufferSize="4096" tcpNoDelay="true"/>
      </rtmpServer>
    </settings>
  </fluorinefx>
 
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpModules>
      <add name="FluorineGateway" type="FluorineFx.FluorineGateway,FluorineFx" />
    </httpModules>
  </system.web>
 
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx"/>
    </modules>
  </system.webServer>
</configuration>

Замечу, что FluorineFX работает только с конфигурационными файлами, расположенными в папке WEB-INF. Именно так настраивается сервер под BlazeDS и LifeCycle Data Services.

А теперь создадим конфигурационные файлы. Для этого создайте папку WEB-INF в корневом каталоге и подпапку flex.
Добавьте xml-файл под названием services-config.xml.
<?xml version="1.0" encoding="utf-8" ?>
<services-config>
  <services>
    <service-include file-path="remoting-config.xml" />
    <service-include file-path="messaging-config.xml" />
  </services>
 
  <channels>
    <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
      <endpoint uri="http://{server.name}:{server.port}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
      <properties>
        <!-- <legacy-collection>true</legacy-collection> -->
      </properties>
    </channel-definition>
    <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
      <endpoint uri="rtmp://{server.name}:1950" class="flex.messaging.endpoints.RTMPEndpoint"/>
    </channel-definition>
  </channels>
</services-config>

Выше мы указали 2 end-point’a: для AMF и RTMP каналов, а также местонахождение двух конфигурационных файлов для клиентов, работающих через remoting и/или messaging. Добавим в ту же папку файлы remoting-config.xml и messaging-config.xml.

Клиент Flex

Теперь пришло время создания клиента. Первым делом создайте проект Flex во Flash Builder. Далее откройте свойства проекта > Компилятор Flex. В текстовом поле «Дополнительные аргументы компилятора» допишите следующую строку -services "{расположение_проекта}\WEB-INF\flex\services-config.xml". И, конечно же, добавить в проект ссылку на fds.swc для включения поддержки RTMPChannel. Данная библиотека входит в состав LCDS, однако если LCDS отсутствует, то в файлах в конце статьи он присутствует. В файле *.mxml приложения вставьте следующий код:
<fx:Declarations>
	<mx:Consumer id="consumer" destination="data_destination" message="messageHandler(event)"/> 
	<mx:RemoteObject id="dataRO" destination="DataDest">
		<mx:method name="GetData" result="GetDataResult(event)" fault="GetDataFault(event)" />
	</mx:RemoteObject>
</fx:Declarations>
<fx:Script>
<![CDATA[
	private function GetDataResult(event:ResultEvent):void {
		var result:String = event.result as String;
		//Ваш код
	}
	
	private function GetDataFault(event:FaultEvent):void{
		var error:String = ObjectUtil.toString(event.fault);
		//Ваш код
	}
	
	private function messageHandler(event:MessageEvent):void
	{
		var msg:IMessage = event.message;
		
		var type:object = msg.body;
		//Ваш код
	}
]]>
</fx:Script>

И последний штрих – это добавление метода SendMessage в наш AppAdapter для отправки сообщений с сервера клиенту.

AppAdapter.cs

public class AppAdapter : MessagingAdapter, ISessionListener
{
    /*
     * ...
    */

    public override object Invoke(IMessage message)
    {
        //Здесь передается управление вашему коду для обработки пересылки сообщений
        MessageService messageService = this.Destination.Service as MessageService;
        messageService.PushMessageToClients(message);
        return null;
    }

    public static void SendMessage(string message)
    {
        MessageBroker msgBroker = MessageBroker.GetMessageBroker(null);
        AsyncMessage msg = new AsyncMessage();
        msg.destination = "data_destination";
        msg.headers.Add(AsyncMessage.SubtopicHeader, "client");
        msg.headers.Add(AsyncMessage.EndpointHeader, "my-rtmp");
        msg.headers.Add(AsyncMessage.RemoteCredentialsHeader, string.Empty);
        msg.headers.Add(AsyncMessage.FlexClientIdHeader, Guid.NewGuid().ToString("D"));
        msg.clientId = Guid.NewGuid().ToString("D");
        msg.messageId = Guid.NewGuid().ToString("D");
        msg.timestamp = Environment.TickCount;
        msg.body = message;
        msgBroker.RouteMessage(msg);
    }
}


Послесловие

В данном посте хотелось раскрыть основную суть возможности связывания Flex + ASP.NET. Конечно, не были раскрыты такие моменты как аутентификация и авторизация, строго типизированные ответы сервера, а не просто string и многое еще. Но об этом уже в следующий раз.
Весь код для Flex и сам солюшн с примером для VS 2010 можно скачать здесь.
Теги:
Хабы:
Всего голосов 11: ↑7 и ↓4+3
Комментарии1

Публикации

Истории

Ближайшие события

19 марта – 28 апреля
Экспедиция «Рэйдикс»
Нижний НовгородЕкатеринбургНовосибирскВладивостокИжевскКазаньТюменьУфаИркутскЧелябинскСамараХабаровскКрасноярскОмск
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань
20 – 22 июня
Летняя айти-тусовка Summer Merge
Ульяновская область