icon ria Invoking RESTful and AMF services from Flex using WCF / MVC / FluorineFX in .NETI’ve written a small Rich Internet Application using Flex and [dot]NET. Data from [dot]NET is returned to Flex using different technologies being MVC, WCF and FluorineFX.

In dot[NET], there are two MVC controllers, RestJsonController and RestXmlController. They both have about the same logic, but one returns Json, the other XML. There’s also a UserService with methods made public using both WCF and FluorineFX. For WCF, REST is used with both GET (WebGet) and POST(WebInvoke).

On the Flex side, REST calls are being done using URLLoader and URLRequest.  There are examples using GET and examples using POST. You’ll also see that URLVariables, Json strings or XML are used to transport data. For the AMF calls, a RemoteObject is used to call a FluorineFx gateway.

Flex only supports the HTTP Verbs GET and POST, so full REST isn’t really possible.

I created the example in Visual Studio 2010 (ASP.NET MVC 3 Web Application) and Flash Builder 4.5 Premium (SDK Version 4.5.1). You can easily open the .NET solution. The Flex source is configured to call localhost on port 53259, so make sure the .NET WebApp is started on that port (or change the Flex source code). For the Flex project, import it using ‘Existing Projects into Workspace’. Since Flash Builder has a problem with relative paths (adobe, please have a look at that), you’ll have to change some things. In the properties of the project, go to Flex Build Path, and set the Output folder to [root example project]/FlexDotNetREST/Flex, being the Flex folder under the root of the .NET Web App. Then right click FlexRest.mxml –> Run As –> Run Configurations… URL or path to launch should be http://localhost:53259/Flex/FlexRest.html.

A zip of the example can be downloaded here.

As I wife recently gave birth to a second daughter, I haven’t got the time anymore to blog a lot. So, explaining this will be difficult. But you have the source and I’ve written a lot of comment in the source it self. So check it out and let me know if it was useful.

Be sure to go and read some articles and blog posts on REST, especially the difference between low REST and high REST (lo-REST – hi-REST). A lot of developers/managers/companies think they have a RESTful api, but actually, they don’t.

http://blog.jonnay.net/archives/665-Hi-Rest-and-Lo-Rest,-two-broken-halves-of-the-tower-of-Babylon.html
http://lesscode.org/2006/03/19/high-low-rest/

WCF REST
REST in Windows Communication Foundation (WCF)
A Developer’s Introduction to Windows Communication Foundation 4

 

Sources (Added some of them below for search engines. It’s better to just download the zip file and check the source in there).

Flex

MXML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
<?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" width="100%" height="100%"
			   creationComplete="creationCompleteHandler(event)">
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			import mx.rpc.AsyncToken;
			import mx.rpc.Fault;
			import mx.rpc.IResponder;
			import mx.rpc.Responder;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.rpc.remoting.mxml.RemoteObject;
 
			private const BASE_MVC_REST_XML_URL:String = "http://localhost:53259/RestXml/";
			private const BASE_MVC_REST_JSON_URL:String = "http://localhost:53259/RestJson/";
			private const BASE_WCF_REST_URL:String = "http://localhost:53259/RestWcf/";
			private const BASE_AMF_GATEWAY_URL:String = "http://localhost:53259/Gateway.aspx"; //FluorineFx Gateway
 
			//The xmlns attribute is needed to make it work with WCF. 
			//With MVC it'll work without it (probably because of the custom provider)
			//The help page from WCF shows clear examples.
			private const XMLUSER:XML = <User xmlns="http://schemas.datacontract.org/2004/07/FlexDotNetREST.Models">
											<UserName>LievenCardoen</UserName>
											<FirstName>Lieven</FirstName>
											<LastName>Cardoen</LastName>
											<Email>lc@gmail.com</Email>
											<Phone>+32456879756</Phone>
										  </User>
 
			private const JSONUSER:String = '{"UserName":"LievenCardoen","FirstName":"Lieven"' +
				',"LastName":"Cardoen","Email":"lc@gmail.com","Phone":"+32456879756"}';
 
			private var urlVariables1:URLVariables = new URLVariables();
			private var urlVariables2:URLVariables = new URLVariables();
 
			/************************
			/* GET using URLVariables
			/************************/
			public function get(url : String, variables : URLVariables = null) : void 
			{
				log("get(" + url + ", " + variables + ")");
 
				var urlLoader : URLLoader = new URLLoader();
 
				urlLoader.addEventListener(Event.OPEN, openHandler);
				urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				urlLoader.addEventListener(Event.COMPLETE, completeHandler);
				urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
				urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
 
				//GET doesn't support custom headers, so don't bother trying.
 
				var urlRequest : URLRequest = new URLRequest(url);
				urlRequest.method = URLRequestMethod.GET;
				urlRequest.data = variables;
 
				urlLoader.load(urlRequest);
			}
 
			/*************************
			/* POST using URLVariables
			/*************************/
			public function post(url : String, variables : URLVariables = null) : void 
			{
				var urlLoader : URLLoader = new URLLoader();
 
				urlLoader.addEventListener(Event.OPEN, openHandler);
				urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				urlLoader.addEventListener(Event.COMPLETE, completeHandler);
				urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
				urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
 
				var header : URLRequestHeader = new URLRequestHeader("custom-header", "blahblah");
 
				var urlRequest : URLRequest = new URLRequest(url);
				urlRequest.requestHeaders.push(header);
				urlRequest.method = URLRequestMethod.POST;
 
				//If urlRequest.data is null, Flash automatically uses
				//a GET instead of a POST (and your custom headers
				//wouldn't work anymore)
				if(null == variables)
				{
					variables = new URLVariables();
					variables.temp = "temp";
				}
				urlRequest.data = variables;
 
				urlLoader.load(urlRequest);
			}
 
			/********************************************
			/* POST with JSON string
			 * JSON is sent and received
			 * !!! You can also send JSON and receive XML
			 * or send XML and receive JSON. Play
			 * with the Content-Type and Accept Http
			 * headers to check it out. This will however
			 * only work with WCF, not with MVC.NET.
			/********************************************/
			public function jsonPost(url : String, jsonString : String) : void 
			{
				log("jsonPost(" + url + ", " + jsonString + ")");
 
				var urlLoader : URLLoader = new URLLoader();
				urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
 
				urlLoader.addEventListener(Event.OPEN, openHandler);
				urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				urlLoader.addEventListener(Event.COMPLETE, completeHandler);
				urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
				urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
 
				var header1 : URLRequestHeader = new URLRequestHeader("Content-Type", "application/json");
				var header2 : URLRequestHeader = new URLRequestHeader("Accept", "application/json");
				var header3 : URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
 
				var urlRequest : URLRequest = new URLRequest(url);
				urlRequest.requestHeaders.push(header1);
				urlRequest.requestHeaders.push(header2);
				urlRequest.requestHeaders.push(header3);
 
				// If urlRequest.data is empty or null, Flash will 
				// automatically use a GET instead of a POST
				//(and your custom headers wouldn't work anymore)
				if(jsonString == null || jsonString == "") jsonString = "[]";
 
				urlRequest.data = jsonString;
				urlRequest.method = URLRequestMethod.POST;
 
				urlLoader.load(urlRequest);
			}
 
			/**********************************************
			/* POST with XML string
			 * XML is sent and received
			 * * !!! You can also send JSON and receive XML
			 * or send XML and receive JSON. Play
			 * with the Content-Type and Accept Http
			 * headers to check it out. This will however
			 * only work with WCF, not with MVC.NET.
			/**********************************************/
			public function xmlPost(url : String, xml : XML = null) : void 
			{
				log("xmlPost(" + url + ", " + xml.toString() + ")");
 
				var urlLoader : URLLoader = new URLLoader();
				urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
 
				urlLoader.addEventListener(Event.OPEN, openHandler);
				urlLoader.addEventListener(ProgressEvent.PROGRESS, progressHandler);
				urlLoader.addEventListener(Event.COMPLETE, completeHandler);
				urlLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
				urlLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
				urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
 
				var header1 : URLRequestHeader = new URLRequestHeader("Content-Type", "application/xml");
				//Next header specifies we want to get back XML
				var header2 : URLRequestHeader = new URLRequestHeader("Accept", "application/xml");
				var header3 : URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
 
				var urlRequest : URLRequest = new URLRequest(url);
				urlRequest.requestHeaders.push(header1);
				urlRequest.requestHeaders.push(header2);
				urlRequest.requestHeaders.push(header3);
 
				//If urlRequest.data is null, Flash automatically uses 
				//a GET instead of a POST.
				//(and your custom headers wouldn't work anymore)
				if(null == xml) xml = <User xmlns="http://schemas.datacontract.org/2004/07/FlexDotNetREST.Models"/>;
 
				urlRequest.data = xml.toString();
				urlRequest.method = URLRequestMethod.POST;
 
				urlLoader.load(urlRequest);
			}
 
			/***********************
			/* Remote Object Call
			/***********************/
			public function remoteObjectCall(url : String) : void
			{
				//There are two RemoteObject classes, use the one from mxml package.
				//GenericDestination --> See site/WEB-INF/flex/services-config.xml
				var ro:RemoteObject = new RemoteObject("GenericDestination");
				//Name of the .NET class (namespace + class name)
				//FluorineFx will create an instance of it using reflection
				ro.source = "FlexDotNetREST.Services.UserService"; 
				ro.endpoint = BASE_AMF_GATEWAY_URL;
 
				var user:User = new User();
				user.UserName = "lievencardoen";
				user.FirstName = "Lieven";
				user.LastName = "Cardoen";
				user.Email = "lc@gmail.com";
				user.Phone = "123456789";
 
				//Create(...) is the .NET method that FluorineFx will trigger
				//If FluorineFx doesn't find a suitable method, it'll throw
				//an error.
				var token:AsyncToken = ro.Create(user); 
				var responder:IResponder = new mx.rpc.Responder(ro_resultHandler, ro_faultHandler)
				token.addResponder(responder);
			}	
 
			//Result handler remote object call
			private function ro_resultHandler(event:ResultEvent) : void
			{
				log("ro_resultHandler(" + event + ")");
				//AMF format is already deserialized into a User object
				var user:User = event.result as User;
				log("Username : " + user.UserName);
			}
 
			//Fault handler remote object call
			private function ro_faultHandler(event:FaultEvent) : void
			{
				log("ro_faultHandler(" + event + ")");
			}
 
			//Log to TextArea
			private function log(log:String) : void
			{
				logTextArea.text += log + "\n";
			}
 
			/**********************
			/* Event handlers
			/**********************/
 
			//CreationComplete Handler
			private function creationCompleteHandler(event:FlexEvent):void
			{
				urlVariables1.userName = "LievenCardoen";
				urlVariables1.firstName = "Lieven";
				urlVariables1.lastName = "Cardoen";
				urlVariables1.email = "lc@gmail.com";
				urlVariables1.phone = "+32456879756";
 
				urlVariables2.firstNumber = 11111;
				urlVariables2.secondNumber = 22222;
			}
 
			//URLLoader handler
			private function openHandler(event : Event) : void 
			{
				log("openHandler(" + event + ")");
			}
 
			//URLLoader handler
			private function progressHandler(event : ProgressEvent) : void 
			{
				var progress : int = 100 * (event.bytesLoaded / event.bytesTotal);
 
				log("progressHandler(" + event + ") - " + progress + " %");
			}
 
			//URLLoader handler
			private function completeHandler(event : Event) : void
			{
				//Here you can deserialize the data (json or xml) to objects.
				//AMF is deserialized by Flash itself. 
				log("completeHandler(" + event + ")");
				log("data :\n " + (event.target as URLLoader).data);
				log("---------------------------------------------------");
			}            
 
			//URLLoader handler
			private function httpStatusHandler(event : HTTPStatusEvent) : void 
			{   
				log("httpStatusHandler(" + event + ") - status : " + event.status);
			}
 
			//URLLoader handler
			private function securityErrorHandler(event : SecurityErrorEvent) : void 
			{
				log("securityErrorHandler(" + event + ") - text : " + event.text);
			}
 
			//URLLoader handler
			private function ioErrorHandler(event : IOErrorEvent) : void 
			{
				log("ioErrorHandler(" + event + ") - text: " + event.text);
			}
 
			//Button click handler REST XML MVC
			private function restXmlClickHandler(event:MouseEvent) : void
			{
				get(BASE_MVC_REST_XML_URL + "index");
				get(BASE_MVC_REST_XML_URL + "details/3");
				get(BASE_MVC_REST_XML_URL + "getAll");
				xmlPost(BASE_MVC_REST_XML_URL + "create", XMLUSER);
				post(BASE_MVC_REST_XML_URL + "echo", urlVariables1);
				get(BASE_MVC_REST_XML_URL + "echo", urlVariables2);
			}
 
			//Button click handler REST JSON MVC
			private function restJsonClickHandler(event:MouseEvent) : void
			{
				get(BASE_MVC_REST_JSON_URL + "Index");
				get(BASE_MVC_REST_JSON_URL + "Details/3");
				get(BASE_MVC_REST_JSON_URL + "GetAll");
				jsonPost(BASE_MVC_REST_JSON_URL + "create", JSONUSER);
				post(BASE_MVC_REST_JSON_URL + "echo", urlVariables1);
				get(BASE_MVC_REST_JSON_URL + "echo", urlVariables2);
			}
 
			//Button click handler REST JSON + XML WCF
			private function wcfXmlClickHandler(event:MouseEvent) : void
			{
				get(BASE_WCF_REST_URL + "index");
				get(BASE_WCF_REST_URL + "details/3");
				get(BASE_WCF_REST_URL + "getAll");
				xmlPost(BASE_WCF_REST_URL + "create", XMLUSER);
				jsonPost(BASE_WCF_REST_URL + "create", JSONUSER);
			}
 
			//Button click handler
			private function amfClickHandler(event:MouseEvent) : void
			{
				remoteObjectCall("");
			}
		]]>
	</fx:Script>
	<s:layout>
		<s:VerticalLayout paddingLeft="20" paddingTop="20"/>
	</s:layout>
	<s:Group>
		<s:layout>
			<s:HorizontalLayout paddingLeft="20" paddingTop="20"/>
		</s:layout>
		<s:Button label="Test Rest Xml" click="restXmlClickHandler(event)"/>
		<s:Button label="Test Rest Json" click="restJsonClickHandler(event)"/>
		<s:Button label="Test Wcf Xml" click="wcfXmlClickHandler(event)"/>
		<s:Button label="Test Amf" click="amfClickHandler(event)"/>
	</s:Group>
	<s:TextArea id="logTextArea" width="100%" height="100%"/>
</s:Application>

AS3 User Class

1
2
3
4
5
6
7
8
9
10
11
12
13
package
{
	//Map the Flex User to the server side .NET User (for AMF)
	[RemoteClass(alias="FlexDotNetREST.Models.User")]
	public class User
	{
		public var UserName:String;
		public var FirstName:String;
		public var LastName:String;
		public var Email:String;
		public var Phone:String;
	}
}

.NET

RestJsonController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 
using System.Collections.Generic;
using System.Web.Mvc;
using FlexDotNetREST.Models;
 
namespace FlexDotNetREST.Controllers
{
    /// <summary>
    /// MVC Controller that will return Json strings.
    /// Sending the parameters can be done with Json, Xml or variables.
    /// You could join this with the RestXmlController and check on the
    /// HTML Header Accept what to return (Json or Xml).
    /// </summary>
    public class RestJsonController : Controller
    {
        //
        // GET: /RestJson/
        public ActionResult Index()
        {
            return Json("Index Json", JsonRequestBehavior.AllowGet);
        }
 
        //
        // GET: /RestJson/Details/5
        public ActionResult Details(int id)
        {
            var user = new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756");
            return Json(user, JsonRequestBehavior.AllowGet);
        }
 
        //
        // GET: /RestJson/GetAll
        public ActionResult GetAll()
        {
            var users = new List<User>
                            {
                                new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756"),
                                new User("JohnBetong", "John", "Betong", "jb@gmail.com", "+32456457674")
                            };
            return Json(users, JsonRequestBehavior.AllowGet);
        }
 
        //
        // GET: /RestJson/Echo
        public ActionResult Echo(int firstNumber, int secondNumber)
        {
            var number = new Number(firstNumber, secondNumber);
            return Json(number, JsonRequestBehavior.AllowGet);
        }
 
        //
        // POST: /RestJson/Echo
        [HttpPost]
        public ActionResult Echo(string userName, string firstName, string lastName, string email, string phone)
        {
            userName += " Echo";
            var user = new User(userName, firstName, lastName, email, phone);
            return Json(user, JsonRequestBehavior.AllowGet);
        }
 
 
        //
        // POST: /RestJson/Create
        [HttpPost]
        public ActionResult Create(User user)
        {
            user.UserName += " Created";
            return Json(user, JsonRequestBehavior.AllowGet);
        }
    }
}

RestXmlController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
 
using System.Collections.Generic;
using System.Web.Mvc;
using FlexDotNetREST.Models;
using MvcContrib.ActionResults;
 
namespace FlexDotNetREST.Controllers
{
    /// <summary>
    /// MVC Controller that will return Xml strings (XmlResult from MvcContrib)
    /// Sending the parameters can be done with Json, Xml or variables.
    /// You could join this with the RestJsonController and check on the
    /// HTML Header Accept what to return (Json or Xml).
    /// </summary>
    public class RestXmlController : Controller
    {
        //
        // GET: /RestXml/
        public ActionResult Index()
        {
            return new XmlResult("Index Xml");
        }
 
        //
        // GET: /RestXml/Details/5
        public ActionResult Details(int id)
        {
            var user = new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756");
            return new XmlResult(user);
        }
 
        //
        // GET: /RestXml/GetAll
        public ActionResult GetAll()
        {
            var users = new List<User>
                            {
                                new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756"),
                                new User("JohnBetong", "John", "Betong", "jb@gmail.com", "+32456457674")
                            };
            return new XmlResult(users);
        }
 
        //
        // GET: /RestJson/Echo
        public ActionResult Echo(int firstNumber, int secondNumber)
        {
            var number = new Number(firstNumber, secondNumber);
            return new XmlResult(number);
        }
 
        //
        // POST: /RestJson/Echo
        [HttpPost]
        public ActionResult Echo(string userName, string firstName, string lastName, string email, string phone)
        {
            userName += " Echo";
            var user = new User(userName, firstName, lastName, email, phone);
            return new XmlResult(user);
        }
 
        //
        // POST: /RestXml/Create
        [HttpPost]
        public ActionResult Create(User user)
        {
            user.UserName += " Created";
            return new XmlResult(user);
        }
    }
}

UserService (WCF)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using FlexDotNetREST.Models;
using System.Collections.Generic;
 
namespace FlexDotNetREST.Services
{
    /// <summary>
    /// Concrete implementation of service contract IUserService.
    /// Both WCF and FluorineFx will be used to trigger these methods.
    /// </summary>
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class UserService : IUserService
    {
        [WebGet(UriTemplate = "index")]
        public String Index()
        {
            return "Index Json";
        }
 
        [WebGet(UriTemplate = "Details/{id}")]
        public User Details(string id)
        {
            var user = new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756");
            return user;
        }
 
        [WebGet(UriTemplate = "GetAll")]
        public IList<User> GetAll()
        {
            var users = new List<User>
                            {
                                new User("LievenCardoen", "Lieven", "Cardoen", "lc@gmail.com", "+32456879756"),
                                new User("JohnBetong", "John", "Betong", "jb@gmail.com", "+32456457674")
                            };
            return users;
        }
 
        [WebInvoke(UriTemplate = "Create", Method = "POST")]
        public User Create(User user)
        {
            user.UserName += " Created";
            return user;
        }
    }
}

services-config.xml (FluorineFX)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
  <factories>
    <factory id="spring" class="Edu3.FluorineFX.Spring.SpringFactory"/>
  </factories>
  <services>
    <service id="remoting-service" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
      <adapters>
        <adapter-definition id="dotnet" class="FluorineFx.Remoting.RemotingAdapter" default="true"/>
      </adapters>
      <!-- Name of destination will be used by the RemoteObject in Flex -->
      <!-- You can give it any name you want, but it must match the     -->
      <!-- the name you give it in Flex.                                -->
      <destination id="GenericDestination">
        <channels>
          <channel ref="my-amf"/>
        </channels>
        <properties>
          <source>*</source>
        </properties>
      </destination>
    </service>
  </services>
  <channels>
    <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
      <endpoint uri="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
      <properties>
        <serialization>
          <legacy-collection>true</legacy-collection>
        </serialization>
        <polling-enabled>false</polling-enabled>
      </properties>
    </channel-definition>
  </channels>
</services-config>

web.config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 
<?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->
 
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    <sectionGroup name="fluorinefx">
      <section name="settings" type="FluorineFx.Configuration.XmlConfigurator, FluorineFx" requirePermission="false"/>
    </sectionGroup>
  </configSections>
 
  <!-- FluorineFx uses Log4Net for logging. If you have any problems getting       -->
  <!-- up and running, look in these logs for more information.                    -->
  <log4net>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file type="log4net.Util.PatternString"
              value="Logs/FlexDotNetREST_%env{COMPUTERNAME}_"/>
      <appendToFile value="true"/>
      <rollingStyle value="Date"/>
      <staticLogFileName value="false"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
      <datePattern value="yyyy-MM-dd-HH.lo\g"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
      </layout>
    </appender>
    <root>
      <level value="ALL"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
  </log4net>
 
  <!-- You can ignore most of the FluorineFx settings. The only one being important -->
  <!-- is the remotingServiceAttribute being set to browse.                         -->
  <!-- For more info, see the FluorineFX website + documentation.                   -->
  <fluorinefx>
    <settings>
      <!--  Reflection optimizer provider="codedom|il" debug="true|false" -->
      <!--<optimizer provider="codedom" debug="true"/>
      <wsdlGenerateProxyClasses>true</wsdlGenerateProxyClasses>
      <wsdlProxyNamespace>FluorineFx.Proxy</wsdlProxyNamespace>-->
      <!--  Time Zone Compensation ="none|auto" -->
      <timezoneCompensation>ignoreUTCKind</timezoneCompensation>
      <!--  Any value-type that is not explicitly initialized with a value will contain the default value for that object type -->
      <!--<acceptNullValueTypes>false</acceptNullValueTypes>-->
      <!-- value="browse|access" -->
      <remotingServiceAttribute>browse</remotingServiceAttribute>
      <classMappings/>
      <!--<services>
        <service>
          <name>ServiceName</name>
          <service-location>.NET Full type name</service-location>
          <methods>
            <remote-method>
              <name>MethodName</name>
              <method>.NET Method name</method>
            </remote-method>
          </methods>
        </service>
      </services>-->
      <!--<cache>
        <cachedService timeout="30" slidingExpiration="false" type=".NET Full type name"/>
      </cache>-->
      <!--<importNamespaces>
        <add namespace="Namespace name to import" assembly=""/>
      </importNamespaces>
      <nullable>
        <type name="System.Int32" value="MinValue"/>
        <type name="System.Double" value="MinValue"/>
        <type name="System.DateTime" value="MinValue"/>
        <type name="System.Guid" value="Empty"/>
      </nullable>-->
      <!-- preferredAlgorithm="deflate|gzip" compressionLevel="high|normal|low" handleRequest="all|amf|none" -->
      <httpCompress preferredAlgorithm="gzip" compressionLevel="high" handleRequest="all">
        <!-- compress responses larger then threshold bytes-->
        <threshold>10240</threshold>
        <excludedMimeTypes>
          <add type="text/xml"/>
          <add type="image/jpeg"/>
          <add type="image/png"/>
          <add type="image/gif"/>
          <add type="application/zip"/>
          <add type="application/x-zip-compressed"/>
          <add type="application/x-gzip-compressed"/>
          <add type="application/x-compressed"/>
          <add type="application/octet-stream"/>
          <add type="application/pdf"/>
          <!-- FireFox has a problem with Flash content being gzipped.  -->
          <add type="application/x-shockwave-flash"/>
        </excludedMimeTypes>
        <!--	This must be enabled for WebResource.axd and ScriptResource.axd because otherweise the scriptmanager doesn't work anymore
						and thus the radcontrols won't work either
				-->
        <excludedPaths>
          <!--Fluorine service browser scripts and resources -->
          <!--
					  <add path="FluorineWebResource.axd"/>
					  <add path="FluorineCodeGenerator.aspx"/>
					  -->
          <!--standard .NET validating scripts and postback script -->
          <!---->
          <add path="WebResource.axd"/>
          <!--MS AJAX and has it's own compression module that will take care of the AJAX scripts -->
          <!---->
          <add path="ScriptResource.axd"/>
        </excludedPaths>
      </httpCompress>
      <!--<fluorineContextFactory type="FluorineFx.Context.FluorineRtmpContextFactory"/>
      <rtmpServer>
        <threadpool minWorkerThreads="0" maxWorkerThreads="25" idleTimeout="60000"/>
      </rtmpServer>-->
    </settings>
  </fluorinefx>
 
  <appSettings>
    <add key="webpages:Version" value="1.0.0.0"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
 
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
    <!-- Apparently this is the configuration of the module that makes it work.                    -->
    <!-- I would expect that it should only be configured in the system.webserver section.         -->
    <!-- I always used a web site instead of a web app. In this example I use a web app, so maybe  -->
    <!-- that's the reason...                                                                      -->
    <httpModules>
      <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx"/>
    </httpModules>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages"/>
      </namespaces>
    </pages>
  </system.web>
 
  <system.webServer>
    <validation validateIntegratedModeConfiguration="true"/>
    <modules runAllManagedModulesForAllRequests="true">
      <!-- Adding the module here doesn't work. Don't know why yet. -->
      <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx" preCondition="managedHandler"/>
    </modules>
  </system.webServer>
 
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
 
  <!-- Configure WCF. For more info, see google ;-) and microsoft documentation. -->
  <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>
pixel Invoking RESTful and AMF services from Flex using WCF / MVC / FluorineFX in .NET
No TweetBacks yet. (Be the first to Tweet this post)