Rich clients (Flex/AIR/Silverlight) & LINQ : data across the pipe

19 03 2009

I’ve blogged before about Flex & LINQ, but I’m always learning new things, and I wanted to share some of my most recent findings.

Note: this article focuses on Flex & LINQ, but it could as easily be applied to Silverlight & LINQ as well. Silverlight 3 is set to merge client & server with .NET 4.0, but I believe the issue of how much and when to send data between client & server will continue to be relevant.

First off, why LINQ?

  1. With LINQ on your server layer, you can avoid having to write your server value objects – LINQ to SQL will do that for you from your DB schema – allows you to quickly updates these objects if your schema ever changes (and let’s face it, it will). NOTE: unfortunately, there is no free & easy way to sync your LINQ to SQL context to your schema in VS2008).
  2. You can put all your SQL as strongly-typed code in your DAL rather than having to call the DB to do it via stored procs, which decouples your DB from your application, allowing you to switch databases if you ever wanted to, and keeps all your server code in one place. 
  3. Cleaner and shorter code – easier for you, easier for other developers to understand (as long as they understand LINQ 🙂 )

So, if you’ve decided to take the LINQ option and your a Flex or AIR developer, then there is good news. 

Products such as WebORB.NET and FluorineFx both support .NET 3.5 and will allow your Flex application to send Remote Objects back and forth between the two. Yes you could use Web Services to do communicate with the server, but I’m assuming you’ve read up on the performance benefits of remoting and AMF vs Web Services, and you’re opting for speed.

The question is however, how do you do it?

The LINQ to SQL tool (I’m not going to mention the ADO.NET Entities tool, which is more feature rich, but a touch more complicated) creates you a data context as you know. This remembers the actions you perform on your objects and will propagate the changes back to the DB when you “SubmitChanges()”. However, when you’re working on the Flex/.NET model, you’re now using LINQ on an middle-tier (or even an n-tier) application, and that changes things.

What changes is that the “context” will be a new instance between each request (unless you use session access to the RemoteObjects, which I won’t get into here). LINQ won’t know that you changed something outside this context, and so to Update an object in the database you will need to “Attach()” it back to the current context to save it, along with it’s original but from a new  context. (See examples below).

Now, there are plenty of articles out there on LINQ in the middle tier and LINQ with n-tier, so I won’t reinvent the wheel. What I will do is talk about strategies on how to leverage LINQ in your Flex app, and how to synchronise data.

Let’s take a think about possible methodologies for sending/receiving related object data from server to client:

  • Safety method: take a little save a little
  • Hungry method: take a little save lots
  • Greedy method: take everything save lots
  • Thrifty method: take everything save a little

I’ll use the following example to illustrate the different methods:

Example Schema

 

Safety Method

The safety method is a simple-to-follow, clear 1:1 system  – load an object when you need it, and load the associated objects as you need them. When you save data back, call the server with either one or a collection of single unrelated objects. You rely on your foreign keys to do all the loading.

All associations within the LINQ to SQL designer (DBML) need to have INTERNAL access, to prevent them being sent to the client, and so that you can still use them within the server code. 

For example: Your client wants the list of projects? It loads them simply via LINQ. Client wants the project’s list of Companies? Load them via the ProjectID. Need to save a Company, send the server the Company object with an associated ProjectID. 

 

Hungry Method

The hungry method involves retrieving just the data objects you require at the time and building up the object model on the client side, eventually sending back an object with related objects. This means you don’t have an excessive number of save calls back to the server, and you don’t rely on the foreign key, you rely on the attached object.

For example:   You may want to load all Projects within the system via LINQ, but don’t want the associated Companies, Employees or Suburbs. You then want to create a new Project and create Companies, Employees. You then call one Save() method to save the new Project, and let LINQ create the entire collection of Company and Employee records.

Now, by default, LINQ will try to send you all the related Companies, Employees and related Suburbs when you ask for the list of Projects.  You have two main options to avoid this:

  1. Change the ACCESS of the association(s) between parent and child within the DBML (LINQ to SQL) editor to INTERNAL. This means only inside the DLL could you access this property.
  2. In your server DLL, NULL any related properties before returning the data to the client. (Literally: project.Companies = null).    

Do you see the problem? Option 1 is the obvious choice but then it means you couldn’t actually send the data back to .NET because if you tried to send a Project back with Companies attached, .NET would say that Project doesn’t have the Companies property as the association as it is internal (and the exception happens during unmarshalling on the server, handled by either the WebORB or FluorineFx DLL).

The Hungry method starts to become a real issue with visibility, and unfortunately, the easiest is to follow option 2 above, which is not a good solution in my opinion.

NOTE: When saving back to the server, do NOT send back both an associated object and an associated foreign key. This will cause .NET to except. EG: If you were to save a Company with an attached Project, you couldn’t also send back Company’s ProjectID (the FK), .NET wouldn’t know which association to use. 

So, in your client code, either remove the Foreign Keys completely from the value object, or use a property getter only to get the foreign key from the association object.

 

Greedy Method

The greedy method is expensive. You are always sending and receiving all (or a lot) of the data in a single call. The advantage is, less trips between the client and server, and minimal client & server code (one Save method to do everything!).

As you can imagine, debugging the Save method can be a headache – as debugging LINQ usually is 🙂 

Now, to Update an object under the greedy method is tricky yet fun. You need to Attach() this new object to the context, along with it’s original from yet another context. 

For example: You want to load all Employees and their Suburb plus their Company and it’s Project. If you wanted to save it back, you’d need to attach it back in. 

Employee SaveEmployee(Employee e) 
{
  DataClassesDataContext context = new DataClassesDataContext();

  //if is Update
  if (e.EmployeeID > 0) 
  {
     //need to attach Employee with a NEW INSTANCE of the DataContext
     Employee oldEmployee = new DataClassesDataContext().Employees.Single( p => p.EmployeeID == e.EmployeeID);

     //now attach it
     context.Attach(e, oldEmployee);
  }
  else
  {
     context.Employees.InsertOnSubmit(e);
  }
  context.SubmitChanges();
  return e;
}

 

This can get even tricker when you’re attaching objects with children which already exist. It can require going through the children and testing their Primary Keys using the method above.

 

Thrify Method

The thrifty method involves receiving all the required data, and just sending back the minimal amount of objects back to the server for a successful save. 

To prevent data being sent back to the server once it is already in the Flex client, requires the use of the Flex metatag: [Transient]. To use Thrifty, we need to rely on Foreign Key associations as LINQ will use the FK on the insert  (just like saving in the Safety method). The advantage is that you have complete control over anything being saved into your database, which can be a real advantage in a intricate & lengthy project. 

Generally using this method, you would need to recall all of your data again, as some associations have been modified. You can try an sychronise these on the client, but it can get VERY tricky. At the very least, you’ll need to return your saved object to get it’s ID if it was just inserted.

For example: You want to load all Projects from the system, but when you save a Project, you don’t t send back it’s Companies, this property is Transient on the client and doesn’t get send back to the server. If you wanted to save a Company, you’d send back a Company object without the associated Project object, but WITH the ProjectID Foreign Key.

 

I personally use a combination of the Thrifty and the Greedy method, deciding when I want to send all the data back, and when I just want to send back an individual object. It still means however, that I need to reload ALL of my data again after a successful save of some object. 

The most important things to remember is attaching to a new context, and not sending both a foreign key and a related foreign object back to the server simultaneously – this upsets LINQ. 

More examples and further investigation to come…





Silverlight Client to Server Remoting

11 02 2009

Being the Flex/AIR to .NET developer that I am, I find Silverlight curious to say the least.

Initially I had assumed that Silverlight 2, as it was deployed inside an ASP.NET side, would automatically handle remote objects from the client to the server. This would alliviate the developer from having to write two classes for her value objects (one on the client and one on the server). Moreover, it would minimise the amount of setup time to get going.

Turns out, it doesn’t. Not in .NET 3.5. You’ve got the options of using Web Services or solutions like WebORB .NET for Silverlight (using AMF).

Posing the question on Twitter today, I was sent the following link from Tim Heuer from the Silverlight team:

http://channel9.msdn.com/pdc2008/PC11/

So, it seems the future of Silverlight, within .NET 4.0 and Visual Studio 2010 is a seamless integration from server to client via the one code base.

Something Mr. Cool (the speaker from said video) didn’t mention in whether or not the server would require the “Dublin” addition to IIS. This seems to be the way .NET 4.0 is achieving the communication from Client to Server. I think I need to test drive VS2010 to be sure.

The code to get the communication between the client and server is fairly bloaty – and seems a bit hackish at this stage. I get the impression MS are trying to quickly increase the functionality of Silverlight before too many people invest in the Flex Framework. MS are down in the fight as Silverlight currently can’t escape the browser unlike AIR  (WPF can too but it’s Windows dependant). I guess they want to entice the developers via integration rather than the software architects by reach.





WebORB licensing restrictions removed

30 09 2008

Until very recently, the Flash remoting solution, WebORB, was limited in that it couldn’t be used in a Software as a Service (SaaS) instance without a valid support plan. That meant a yearly fee of a few thousand USD.

However, I have been informed today that this restriction has been removed.

Having read it myself, I can confirm that WebORB license now allows the solution to be used in software applications that earn themselves an income.

From the license itself: (please follow the link above for the actual wording)

“… and does not prevent developers from using and bundling Software with higher level applications that run on these platforms….”





Flex, .NET 3.5 with LINQ to SQL

23 09 2008

March 2009: For more information see the latest article on FLEX & LINQ:

https://justinjmoses.wordpress.com/2009/03/19/rich-clients-flex-air-silverlight-linq-data-across-the-pipe/

——————————————————————————-

I had certainly delayed looking at LINQ for too long.

After seeing a screencast on some of the new features in ASP.NET I noticed the very handy LINQ to SQL item.

Well.

Let’s just say I’m not using strongly typed datasets anymore.

LINQ provides strongly typed access to your database (tables, views, sprocs and function) while also allowing you to query those results.

Whilst many still advocate the use of stored procs for larger and more advanced or intensive queries, at least some of the simple overhead can be reduced. Furthermore, updating your C# classes to reflect your DB is as simple as updating the LINQ to SQL item.

But the major advantage from a Flex remoting perspective is how easy it is to have all this returned data in your client.

Say I have three tables: (already linked with relationships via foreign keys)

Employee, Company & Position

I add the LINQ to SQL item to my solution. Inside, I connect the LINQ object up to the db and drag in my database objects. Voila, I have the strongly typed classes: “Employee”, “Company” and “Position”. None of this DataRow, DataTable, DataAdapter business.

Using LINQ syntax, I can do simple queries on the spot, like:

DataClassesDataContext db = new DataClassesDataContext();

var data = from e in db.Employees where e.CompanyID == someCompanyID select p;

List<Employee> employees = data.ToList<Employee>();

Now, I can return this list to either FluorineFx or WebORB and the ArrayCollection that the List is serialised into will contain an array of Employee Value Objects (my Employee.as file). Nothing special there.

BUT, the “Company” property is also provided. This is the Company property that is automatically generated in LINQ to SQL that provides the foreign key reference to the company.

This holds for all your foreign keys.

So if you want to reduce your overhead from a C# (writing classes for your db objects) and DB perspective (writing sprocs for every data call), then take a gander at .NET 3.5.

NOTE:

  • If you weren’t aware, .NET 3.5 framework is actually an addition to .NET 2.0. This means that once you install the framework on a machine, no manual IIS settings are required (as opposed to the 1.1 to 2.0 switch) to activate 3.5 on a website or virtual directory.
  • Both FluorineFx and WebORB support .NET 3.5




FluorineFx and WebORB coding differences part1

3 09 2008

I thought I’d compile a list of differences between coding an Flex .NET remoting solution in FluorineFx and WebORB.

First off, the versioning:

FluorineFx: 1.0.0.13

WebORB (.NET): 3.5

Now, for various features/actions. These are typically in no order:

1. Registering a DLL to work in remoting

both: deploy the DLL in the “bin” folder (alongside “FluorineFx.dll” and “weborb.dll” respectively)

2. Destinations/Channels (in the WEB-INF/flex folder)

WebORB: Uses a “GenericDestination” that is exposed to all classes in all DLLs alongside the

<destination id="GenericDestination">
<properties>
<source>*</source>
</properties>
</destination>

Uses a set of channels including the default AMF channel

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint uri="weborb.aspx" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>false</polling-enabled>
</properties>
</channel-definition>

FluorineFx: Uses the “fluorine” destination that is open to all classes exposed as remoting (see point 3 below).

<destination id="fluorine">
<properties>
<source>*</source>
</properties>
</destination>

Uses a set of channels including the default AMF channel

<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>
</properties>
</channel-definition>

NOTE: Due to a bug in Flex Builder 2 & 3, you must “Clean” your project to register and changes in the WEB-INF xml files.

NOTE: You can see that the “ContextRoot” setting is important in FluorineFx. If you aren’t running off the root domain, but in some other folder / virtual directory, you need to set up the Context Root to match that folder structure. ie. If you’re testing in “http://localhost/TestFolder&#8221; then you must set your Context Root in Flex Builder (Project Properties) to be “TestFolder”.

3. Exposing classses/methods from a DLL to Flex.

WebORB: WebORB will expose all namespaces/classes/methods from a destination by default.

This destination, when combined with the “source” property on a remote object, will expose everything inside your DLLs to the web. This can be toggled in the weborb.config file (under security->deploymentMode) to “closed”.

FluorineFx: Only those classes compiled with the [RemotingService] Attribute in C# will be exposed via FluorineFx, and even then only their public methods. NOTE: that class must be using the “FluorineFx” namespace.

4. Using SSL remoting

WebORB: The SSL channel is there by default “my-secure-amf”. If you ran your app from HTTPS, it would work by default as both the normal and the HTTPS channels are defaults. Alternatively (and for best practises), you can set up a destination to use it:

<destination id="MyDestination">
<channels>
<channel ref="my-secure-amf" />
</channels>
<properties>
<source>My.Name.Space.MyServiceClass</source>
</properties>
</destination>

FluorineFx: Doesn’t come bundled with a secure channel, but can do it easily. You just need to add the following to your services-config.xml file

<channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
<endpoint uri="https://{server.name}:{server.port}/{context.root}/Gateway.aspx" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
</channel-definition>

Then you can add a destination in remoting-config.xml that uses “my-secure-amf” (see the WebORB solution above).

5. Manage security

WebORB: The WebORB console is fully featured to allow you to setup which services can be exposed to which users. You can limit a namespace, class or method by role, hostname, ip range or single ip (allowing masks). Essentially this just adds security configuration data to weborb.config but it’s handy.

To implement custom authentication and authorisation, you must implement Weborb.Security.IAuthenticationHandler and Weborb.Security.IAuthorizationHandler respectively (and add a reference to this classes in your weborb.config file under the security setting). Then you should be able to use the setCredentials() method on your remote object.

FluorineFx: Uses a similar approach to security, but it’s all done in the remoting-config.xml file instead. You need to manually add the constraints and apply them to destinations.

<destination id="MyService">
    <channels>
      <channel ref="my-amf" />
    </channels>
    <properties>
      <source>My.Name.Space.MyServiceClass</source>
    </properties>
    <security>
      <security-constraint ref="privileged-users"/>
    </security>   
  </destination>

and then in your services-config.xml file

  <security>
    <security-constraint>
      <auth-method>Custom</auth-method>
      <roles>
        <role>admin</role>
        <role>privilegeduser</role>
      </roles>
    </security-constraint>
    <login-command class="My.Name.Space.MyLoginCommand" server="asp.net"/>
  </security>

Like WebORB, you’ll need to define your own authenticator/authoriser. You must implement the FluorineFx.Security.ILoginCommand interface. You then insert it’s name aboce, in the “login-command” setting above.


6. Data Type Mapping

Both: use the [RemoteClass(alias=”…”)] metadata syntax above your Value Objects in ActionScript to ensure the remoting gateway will return your objects as the correct type.

WebORB: Returns a DataTable as an array of objects (associative arrays representing a row). Returns DataSets as an object (associated array of arrays of associated arrays). Can optionally use Attribute [ReturnType(“namespace.actionscriptClassName”)] before your C# method to tell WebORB how to serialise the data in the DataTable (I can’t get this to work though).

FluorineFx: Must be told directly which type of data the DataTable/DataSet will be returning. Otherwise will return DataTables and DataSets in flat array without column associations.

You’ll need to use Attributes above methods in C#: [DataTableType(string remoteClass)] & [DataSetType(string remoteClass).





Flex Remoting: channels, destinations and SSL

26 08 2008

If you’re like me, then you’ve gotten well into flash remoting as a solution for Flex Data Messaging. You’re using AMF to allow the creation of remote objects between actionscript on the client and some server language (PHP, Java, .NET, etc).

I’ve been running into troubles with WebORB (v3.5) and setting channels that work.

Essentially, for whatever reason, my compiled app didn’t register the changes in my services-config.xml file that resides in the WEB-INF folder of whatever software you’re using to interface with the server side language. And believe me, I tried it a thousand different ways.

The easiest way to override this faulty behaviour is to set the channels and endpoints inside your flex app when you’re building the remote object.

You can see below a solution in weborb for .NET (hence the weborb.aspx endpoint)

Service.as

————————————————————————–

protected static function init(serviceName:String, isSecure:Boolean = false):void
{

var destination:String;

var remoteObject:RemoteObject = null;

var channelSet:ChannelSet = new ChannelSet();

var channel:Channel;

if (isSecure)
{
destination = “MySecureDestination”;

channel = new SecureAMFChannel(null,”weborb.aspx”);
}
else
{
destination = “MyDestination”;

channel = new AMFChannel(null,”weborb.aspx”);
}

channelSet.addChannel(channel);

remoteObject  = new RemoteObject(destination);

//30s timeout on requests
remoteObject.requestTimeout = 30;

remoteObject.showBusyCursor = true;

remoteObject.source = “My.Name.Space.” + serviceName;

remoteObject.channelSet = channelSet;

}

————————————————————————–

And in my remoting-config.xml file:

————————————————————————-

<destination id=”MyDestination”>
<properties>
<source>*</source>
</properties>
</destination>

<destination id=”MySecureDestination”>
<channels>
<channel ref=”my-secure-amf” />
</channels>
<properties>
<source>*</source>
</properties>
</destination>

———————————————————–

As you first start using the SSL option, you may find you start receiving an error about cross domain security issues between HTTP and HTTPS. The deal is that if you are loading your SWF from HTTP, you require a crossdomain.xml policy file in the root of your website to allow HTTPS access.

From Adobe Flex 3 Help: crossdomain.xml

<cross-domain-policy>

<allow-access-from domain=”*.mydomain.com” secure=”false”/>

</cross-domain-policy>

As the Help mentions, you don’t require the crossdomain policy if you’re calling HTTP from a HTTPS loaded swf.





Flex.NET remoting methodology – coding standards and best practises

27 03 2008

I’ve been dabbling with different methodologies into Flex.NET remoting, and trying to find a coding standard that works and is appropriate for this technology.

I’ve provided my solution in the hope that it will spur comments and generate other opinions in this rather new field.

One of the annoying things with Flex remoting is having to define the same object twice – once in C# and once in ActionScript 3 (AS3). Obviously as good coders, we know this to be a no-no.

Of course, there are codegen solutions out there, but I’ve been dissatisfied with them, and prefer the manual touch.

This is what I’ve come up with:

  1. In Visual Studio, create a DataSet that interfaces with the database, exposing specific TableAdapters to each of your objects.
  2. In both Flex and .NET, create an object that spans across the two platforms. As it’s defined twice, use some codegen tool to generate the class in both C# and AS3.
  3. In your .NET library, create a “Service” for the action that provides the ability to interface between the client (Flex) and the server (.NET). This service talks to the DB via the above mentioned TableAdapters.
  4. In your Flex application, create a “Service” that mimics the methods of the service in .NET that you want to access

Don’t worry, I never read those summaries either. Here’s the example that explains it all:

Problem: I want to modify a User object across the platform

Solution:

  1. Create my DAL by adding a DataSet to my Service Layer (the assembly that will handle all the .NET interfacing). In the DAL, create a UserTableAdapter and expose a Get method called : GetUserByID(int userID).
  2. Create the object in C# and is AS3 . Note the use of the compiler directive “RemoteClass” in the AS3 is the syntax for WebORB’s remoting solution.
    C# (User.cs)

    namespace JustinJMoses.Examples.RemotingExample.Objects
    {
    public class User
    {
    public int UserID = -1;

           public String GivenNames;

           public String Surname;

           public String Email;
    }
    }

    AS3 (User.as)

    package com.justinjmoses.examples.remotingexample

    {

    [RemoteClass(alias=”JustinJMoses.Examples.RemotingExample.Objects.User”)]

    public class User

    {

    public var UserID:int = -1;

    public var Email:String;

    public var GivenNames:String;

    public var Surname:String;

    }

    }

  3. Make a service for the User in C# – UserService.cs

    using JustinJMoses.Examples.RemotingExample.Objects;

    using JustinJMoses.Examples.RemotingExample.DAL;

    using JustinJMoses.Examples.RemotingExample.DAL.MyDALTableAdapters;

    namespace JustinJMoses.Examples.RemotingExample.Services
    {

    public class UserService
    {

    public User Load(int UserID)
    {

    UserTableAdapter adapter = new UserTableAdapter();

    MyDAL.UserDataTable table = adapter.GetUserByID(UserID);

    MyDAL.UserRow row = (MyDAL.UserRow)table.Rows[0];

    User u = new User();

    u.UserID = row.UserID;

    u.GivenNames = row.GivenNames;

    u.Surname = row.Surname;

    u.Email = row.Email;

    return u;

    }

    }

    }

  4. Make a service for the Flex app in AS3: UserService.as

    package com.justinjmoses.examples.remotingexample
    {

    import mx.rpc.events.ResultEvent;

    public class UserService extends BaseService
    {

    public static function Load(onResultFunction:Function,userID:int):void
    {

    init(“UserService”);

    remoteObject.Load.addEventListener(ResultEvent.RESULT,onResultFunction);

    remoteObject.Load(userID);

    }

    }

    }

    that extends from the base service class BaseService.as

    package com.justinjmoses.examples.remotingexample
    {

    import mx.controls.Alert;

    import mx.core.Application;

    import mx.rpc.events.FaultEvent;

    import mx.rpc.events.InvokeEvent;

    import mx.rpc.events.ResultEvent;

    import mx.rpc.remoting.mxml.RemoteObject;

    public class BaseService

    {

    protected static var remoteObject:RemoteObject = null;

    protected static function init(serviceName:String):void

    {

    remoteObject = null;

    remoteObject = new RemoteObject(“GenericDestination”);

    remoteObject.showBusyCursor = true;

    remoteObject.addEventListener(FaultEvent.FAULT, BaseService.onFault);

    remoteObject.source = “JustinJMoses.Examples.RemotingExample.Services.” + serviceName;

    }

    protected static function onFault (event:FaultEvent):void

    {

    Alert.show(event.fault.faultString, “Error”);

    }

    }

    }

  5. The function can now be called statically in AS3

    private function onCrtComplete():void
    {

    UserService.Load(onUserLoaded, 12);

    }

    private function onUserLoaded(evt:ResultEvent):void
    {

    var user:User = User(evt.result);
    }

NOTE: This soln is done via WebORB remoting. Syntax includes the remote object destination of “Generic Destination”, and the compiler directive “RemoteObject()” in AS3.