If you are making a HTTPService call in Flex, you need to make sure that the domain specified in the url attribute is the domain from where your application was downloaded or there is a crossdomain.xml file granting access to your application’s originating is available on the domain specified in the HTTPService url attribute.

Take a look at the following example. Trying to load a XML file :-


<s:HTTPService resultFormat="e4x"
 result="resultHandler(event)"
 id="serv"
 url="http://news.bbc.co.uk/nol/shared/bsp/hi/services/desktop_alerts/xml/ukfs/alert_data.xml" />

If you run the above code, you get the following error :-


[RPC Fault faultString="Security error accessing url" faultCode="Channel.Security.Error" faultDetail="Destination: DefaultHTTP"]
 at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::faultHandler()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:345]
 at mx.rpc::Responder/fault()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\Responder.as:68]
 at mx.rpc::AsyncRequest/fault()[E:\dev\4.x\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:113]
 at DirectHTTPMessageResponder/securityErrorHandler()[E:\dev\4.x\frameworks\projects\rpc\src\mx\messaging\channels\DirectHTTPChannel.as:432]
 at flash.events::EventDispatcher/dispatchEventFunction()
 at flash.events::EventDispatcher/dispatchEvent()
 at flash.net::URLLoader/redirectEvent()

This means the URL we are trying to access does not have a crossdomain.xml file. And as is obvious, we can not ask for one in every case.

As I started looking into YQL recently, I figured this could be done with YQL. Here is a complete example I came up with that uses YQL to query the same URL that we could not access above and it parses the XML and displays in a grid.

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
 xmlns:s="library://ns.adobe.com/flex/spark"
 xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955"
 minHeight="600" initialize="doInit()">

 <fx:Declarations>
 <!-- Place non-visual elements (e.g., services, value objects) here -->
 <s:HTTPService resultFormat="e4x"
 result="resultHandler(event)"
 id="serv"
 url="{yql_url('http://news.bbc.co.uk/nol/shared/bsp/hi/services/desktop_alerts/xml/ukfs/alert_data.xml')}" />
 </fx:Declarations>

 <fx:Script>
 <![CDATA[
 import mx.rpc.events.ResultEvent;

 [Bindable] private var items:XMLList ;

 private function doInit():void
 {
 serv.send();
 }

 private function yql_url(url:String):String
 {
 var str:String = 'http://query.yahooapis.com/v1/public/yql?q=';
 var query:String = 'select * from xml where url="';
 query = query + url + '"';
 return str + encodeURI(query);
 }

 private function resultHandler(event:ResultEvent):void
 {
 var data:XML = new XML(String(event.result));
 items = data.results.stories.story;
 }

 ]]>
 </fx:Script>

 <mx:DataGrid id="newsList" dataProvider="{items}" width="500" height="200">
 <mx:columns>
 <mx:DataGridColumn dataField="headline" />
 </mx:columns>
 </mx:DataGrid>

</s:Application>

Basically, what is happening here is I am sending a query to the YQL which looks something like this.


http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'http%3A%2F%2Fnews.bbc.co.uk%2Fnol%2Fshared%2Fbsp%2Fhi%2Fservices%2Fdesktop_alerts%2Fxml%2Fukfs%2Falert_data.xml'

That does the trick. Returns me an XML as I wanted and then its upto me to do whatever I want with the XML.

I am actually wondering why is YQL not as widely used or heard about as it should be.