You are browsing the archive for .NET.

Avatar of Anton

by Anton

AES encryption envelope and Xamarin PCL

July 31, 2014 in .NET

Recently I’ve been asked a question about how the AES encryption envelope can be used with a PCL build of Data Abstract, the issue being that PCL doesn’t expose the needed cryptography API. Although I don’t known the reason for this, I am still going to provide a solution.

Before we dive into the technical details, I have to say that relying on AES message encryption alone is not the best option. Once someone steals your password, they will be able to intercept, read and modify any client-server traffic. So keeping passwords safe and not storing them in non-encrypted form is an absolute must. But you should still consider SSL to protect your communication channels.

Let’s go back to AES for now.

For most of the platforms supported by RemObjects SDK “natively”, the AESEncryptionEnvelope can be instantiated in the application and then this instance can be added to the .Envelopes collection of the Message instance created in the PCL communication library (this is the magic of PCL, yes). Unfortunately, there are two quite important platforms that are supported only by the PCL build of RemObjects SDK. So a solution is needed.

Assume we have a very simple PCL library that calls a RemObjects SDK server and that the server has AESEncryptionEnvelope enabled, so we have to enable it on the client side as well. The client is a Xamarin.iOS application (but the Xamarin.Android approach is exactly the same). Below, I’ll be talking about ‘native’ code, by which I mean code that directly references Xamarin libraries, opposed to code that references PCL.

So the solution is dead simple: In the ‘native’ code part, wrap Crypto API into a form that the PCL code part can understand and provide this wrapped instance to the RemObjects SDK message instance. Obviously, the best way to provide something is to wrap it into a form that RemObjects SDK understands. In our case, we’ll derive a class from the abstract class MessageEnvelope. For further reference I’ll provide the code entirely:

using System;
using System.ComponentModel;
using System.IO;
using System.Text;
using RemObjects.SDK.Helpers;
using System.Security.Cryptography;

namespace RemObjects.SDK
{
     public class AesEncryptionEnvelope : MessageEnvelope
     {
          #region Default values
          private const String CATEGORY_ENCRYPTION = "Encryption";
          private const String IV = "@1B2c3D4e5F6g7H8";

          private const Int32 BUFFER_SIZE = 65536;//64k
          private const Int32 BLOCK_SIZE = 128 / 8;
          #endregion

          #region Private fields
          private Byte[] fEncodedPassword;
          #endregion

          public AesEncryptionEnvelope()
               : base()
          {
          }

          public AesEncryptionEnvelope(String password)
               : this()
          {
               this.Password = password;
          }

          #region Properties
          public String Password
          {
               get
               {
                    return this.fPassword;
               }
               set
               {
                    this.fPassword = value;
                    this.EncodePassword();
               }
          }
          private String fPassword;

          public override String DefaultEnvelopeMarker
          {
               get
               {
                    return "AES";
               }
          }
          #endregion

          protected override MemoryStream InternalWrap(Stream source, Byte[] header)
          {
               // Size of the original stream
               Int64 lStreamLength = source.Length - source.Position;
               Byte[] lStreamSizeBuffer = BinHelpers.Int32ToBuffer((Int32)lStreamLength);

               // Create bytes array containing
               // [... original header ...][stream size]
               // This is cheaper than creating MemoryStream and then converting it to Byte[]
               Byte[] lHeader = new Byte[header.Length + 4];
               Array.Copy(header, lHeader, header.Length);
               Array.Copy(lStreamSizeBuffer, 0, lHeader, header.Length, 4);

               return this.InternalEncrypt(source, lHeader);
          }

          protected override MemoryStream InternalUnwrap(Stream source)
          {
               // Read size of the original stream
               Byte[] lBuffer = new Byte[BinHelpers.SIZE_INT32];
               Int32 lBytesRead = source.Read(lBuffer, 0, BinHelpers.SIZE_INT32);

               if (lBytesRead != BinHelpers.SIZE_INT32)
                    BinHelpers.UnexpectedEndOfStream();

               Int32 lStreamSize = BinHelpers.Int32FromBuffer(lBuffer);

               MemoryStream lDecryptedData = new MemoryStream();
               this.InternalDecrypt(source, lDecryptedData);

               if (lDecryptedData.Length < lStreamSize)
                    throw new Exception("Decryption error. Invalid length of the stream.");

               lDecryptedData.SetLength(lStreamSize);

               return lDecryptedData;
          }

          private void EncodePassword()
          {
               if (String.IsNullOrEmpty(this.Password))
               {
                    this.fEncodedPassword = null;
                    return;
               }

               this.fEncodedPassword = new Byte[32];

               Byte[] lPasswordBytes = Encoding.UTF8.GetBytes(this.Password);
               Array.Copy(new SHA1CryptoServiceProvider().ComputeHash(lPasswordBytes), this.fEncodedPassword, 20);
               Array.Copy(new MD5CryptoServiceProvider().ComputeHash(lPasswordBytes), 0, this.fEncodedPassword, 20, 12);
          }

          private CryptoStream GetCryptoStream(Stream baseStream, CryptoStreamMode mode)
          {
               if (this.fEncodedPassword == null)
                    throw new Exception("No password configured for AesEncryptionEnvelope.");

               RijndaelManaged lSymmetricKey = new RijndaelManaged();
               lSymmetricKey.Mode = CipherMode.CBC;
               lSymmetricKey.Padding = PaddingMode.None; // Do padding manually
               lSymmetricKey.Key = this.fEncodedPassword;
               lSymmetricKey.IV = Encoding.UTF8.GetBytes(IV);

               ICryptoTransform lTransform = (mode == CryptoStreamMode.Write) ? lSymmetricKey.CreateEncryptor() : lSymmetricKey.CreateDecryptor();

               return new CryptoStream(baseStream, lTransform, mode);
          }

          private MemoryStream InternalEncrypt(Stream source, Byte[] header)
          {
               MemoryStream lEncryptedData = new MemoryStream(header.Length + (Int32)AesEncryptionEnvelope.GetEstimatedStreamLength(source));
               lEncryptedData.Write(header, 0, header.Length);

               using (CryptoStream cryptoStream = this.GetCryptoStream(lEncryptedData, CryptoStreamMode.Write))
               {
                    StreamHelpers.CopyStreamToStream(source, cryptoStream);

                    // Add tail
                    Int32 lTailLength = ((Int32)(source.Length - lEncryptedData.Length)) + header.Length;
                    if (lTailLength != 0)
                    {
                         lTailLength = AesEncryptionEnvelope.BLOCK_SIZE - lTailLength;
                         Byte[] lTail = new Byte[lTailLength];
                         cryptoStream.Write(lTail, 0, lTailLength);
                    }

                    cryptoStream.FlushFinalBlock();

                    // The original lEncryptedData stream will be enclosed together with the CryptoStream instance
                    // Note that the used constructor doesn't actually copy the data, so memory consumption/performance
                    // is not an issue here
                    MemoryStream lResult = new MemoryStream(lEncryptedData.GetBuffer());

                    // Otherwise the tail contained in the buffer will break the AES decryption on the other side
                    lResult.SetLength(lEncryptedData.Length);

                    return lResult;
               }
          }

          private void InternalDecrypt(Stream source, Stream destination)
          {
               using (CryptoStream cryptoStream = this.GetCryptoStream(source, CryptoStreamMode.Read))
               {
                    StreamHelpers.SetStreamCapacity(destination, source, AesEncryptionEnvelope.GetEstimatedStreamLength(source));
                    StreamHelpers.CopyStreamToStream(cryptoStream, destination);
               }
          }

          private static Int32 GetEstimatedStreamLength(Stream source)
          {
               Int32 lSourceLength = 0;
               try
               {
                    lSourceLength = (Int32)(source.Length - source.Position);
               }
               catch (NotSupportedException)
               {
                    return -1; // Unknown
               }

               Int32 lResult = (lSourceLength / 16) * 16;
               if (lResult < lSourceLength)
                    lResult += 16;

               return lResult;
          }
     }
}

(You'll have to reference the RemObjects SDK assemblies to get this code compiled.)

Then provide an instance of this AesEncryptionEnvelope class to the code part where the communication components are instantiated and add it there to the Envelopes collection:

message.Envelopes.Add(envelopeInstance, true);

And that's it. AES encryption is enabled.

I also want to mention that while theoretically it is possible to implement AES encryption/decryption completely in managed PCL code, there are reasons NOT to do this. Re-implementing part of the base class library leads to code bloating. What's more important is that cryptography APIs implemented by Xamarin platforms might utilize low-level platform methods for better performance and security – something that a PCL managed code-only implementation won't be able to provide by definition.

PS.: The above-mentioned approach can be extended. More powerful (and resources-consuming) cryptography algorithms can be used instead of AES, like asymmetric encryption. Custom envelopes based on them can be used in RemObjects SDK-powered applications – all you need to do is to properly override the abstract methods of the MessageEnvelope class.

Avatar of Anton

by Anton

PCLs, async/await server calls, and more…

June 26, 2014 in .NET, Data Abstract

The new Data Abstract 8 is out. So I’d like to highlight some of its features and the changes they imply.

Xamarin support changes

To start with, the Xamarin iOS and Android platforms are now supported via Data Abstract for the Portable Class Library. This means that there is no more separate Data Abstract for MonoAndroid or MonoTouch builds.

On the bright side, this means that both target platforms now share the same set of features and, due to the PCL support, development of code shared between iOS and Android targets becomes a little easier. There are, however, some caveats you should be aware of:

  • Only DA LINQ data access is supported, DataSet support on the iOS side is not available anymore, so a data access code revamp is needed.
  • Only the simple HTTP client channel is available in Data Abstract for PCL. While this might look restricting, it is still the best choice for apps targeting mobile devices operating with a potentially unstable connection. In such conditions, SuperHTTP has no considerable advantage over the simple HTTP client channel.
  • Only asynchronous server calls are possible. While this is a must in the mobile world due to unpredictable network delays, it can be a real headache when the Begin/End asynchronous calls pattern is used, especially when several remote calls are chained in the same method. Luckily, starting this release, RemObjects SDK for .NET now provides support for async/await remote calls.

async/await remote calls

Old async code with callback methods and BeginOperation/EndOperation calls was hard to develop and maintain. Starting with the Summer 2014 release, RemObjects SDK now allows to call remote servers using code like:

var result = await service.SumAsync(1, 2);

Of course, the target platform also has to support await calls, so this feature is not supported for .NET 3.5 clients. For all other target platforms,_Intf code will contain method declarations like:

public interface ISampleService_Async : RemObjects.SDK.IROService_Async {
    System.IAsyncResult BeginSum(double a, double b, System.AsyncCallback @__Callback, object @__UserData);
    double EndSum(System.IAsyncResult @__AsyncResult);
    System.Threading.Tasks.Task SumAsync(double a, double b);
}

Note the last method declaration. It is the asynchronous server call proxy that can be called using the async/await pattern.

Unfortunately, it is not possible to expand the DataAdapter class with …Async methods due to the necessity to support .NET 3.5. Instead, a set of extension methods was introduced that provide nearly the same experience.

These extension methods are defined in the assembly RemObjects.DataAbstract.Async.dll. For platforms that support Extension SDK packages (f.e. Windows Phone) this assembly is included in the Data Abstract packages. On other platforms (f.e. desktop .NET) this assembly has to be referenced explicitly.

Note that to call an extension method, you need to add the namespace this method is declared in to the using (C#)/Imports (VB.NET) or uses (Oxygene) clause.

The following extension methods are provided:

  • IBaseLoginService_Async interface, methods are declared in the RemObjects.DataAbstract namespace.

    • Boolean LoginExAsync(String)
    • LogoutAsync()
  • DataAdapter (including LocalDataAdapter and RemoteDataAdapter), methods are declared in the RemObjects.DataAbstract namespace. All methods are awaitable versions of corresponding synchronous DataAdapter methods.

    • FillAsync(DataSet, Boolean)
    • FillAsync(DataSet, Boolean, Boolean)
    • FillAsync(DataSet, String[], Boolean)
    • FillAsync(DataSet, String[], WhereExpression[], Boolean)
    • FillAsync(DataSet, String[],TableRequestInfo[], Boolean)
    • FillAsync(DataTable, WhereExpression, Boolean)
    • FillAsync(DataTable,TableRequestInfo, Boolean)
    • FillWithDASqlAsync(DataTable, String, DataParameter[])
    • UpdateAsync(DataSet)
    • UpdateAsync(DataSet, String[])
    • UpdateAsync(Delta[], Boolean)
  • LinqDataAdapter (including LocalLinqDataAdapter and RemoteLinqDataAdapter), methods are declared in the RemObjects.DataAbstract.Linq namespace.

    • LoadListAsync<T>(IQueryable<T>) – asynchronously loads data into List<T>
    • LoadBindableListAsync<T>(IQueryable<T>) – asynchronously loads data into BindingList
    • ApplyChangesAsync()

    Asynchronous data loading using one of these methods will look like

    var list = await fDataAdapter.LoadListAsync(
            from x in fDataAdapter.GetTable<Clients>() select x);
    

Windows Phone Applications support

This application type has a somewhat misleading name. Microsoft has renamed the good old Windows Phone apps based on Silverlight to Windows Phone Silverlight applications and introduced new WinRT based phone applications as Windows Phone. We register Data Abstract and RemObjects SDK as Extension SDKs for both these platforms. In case you want to reference Data Abstract assemblies directly, you need to reference assemblies from the WindowsPhone folder for Silverlight based applications and assemblies from the WinRT folder for Windows Phone Store applications. It is strongly recommended to use the ExtensionSDKs’ references instead of direct assembly references to avoid situations where wrong assemblies are referenced and the application just cannot be built.


That’s all for now. See you around and don’t forget to check the Breaking Changes page!

Avatar of marc

by marc

Data Abstract, RemObjects SDK and Hydra “Spring 2014” Releases

March 31, 2014 in .NET, Cocoa, Data Abstract, Delphi, Hydra, Java

On Friday, we released the latest updates to our Data Abstract and RemObjects SDK products for all five platforms, as well as for Hydra. Like always, a whole bunch of fixes and improvements across the product lines are gathered together in this release.

For Data Abstract and RemObjects SDK, this is also our last planned release for the 7.0 product version, as we prepare for a major new product cycle — codenamed DA8 — starting with our summer release in May. As such, this update focuses mainly on bug fixes and smaller enhancements (of which there are many).

The new release also includes official support for use with our recently released RemObjects C#, including project templates and IDE improvements to let you build .NET, Cocoa and Java apps with RO/DA using our C# implementation, as well as building managed hosts and plugins for Hydra.

As always, the new update is free for all users with an active subscription, and available on the customer portal. Our free 30-day trial downloads have also been updated to the new version.

If your subscription has elapsed, then now is a great time to renew. Renewing will not only give you access to the new 7.0 update, but also access to the beta versions of DA8 that will become available over the course of April, as well as the first (and future) DA8 or RO8 releases throughout the year.

If your previous subscription ended a while ago, you will be happy to hear that we recently updated our online shop to automatically grant “amnesty renewals”. That means you can be assured that your renewed license will always cover the current product and at least six months of future updates from your renewal date.

If you have or are considering getting a Suite subscription, remember that the Suites for .NET, Cocoa and Java now also include RemObjects C# — so you get been more value at the same great price as before (and you can always up-renew from RO or DA to the Suite, of course).

But enough talk, i’m sure you’re anxious to try out the new bits. We’re happy to have this new set of updates out to you now, and we’re extremely excited about what we have coming for DA8 and RO8 this summer and beyond.

yours,
marc hoffman
Chief Architect

Avatar of Anton

by Anton

Winter has come

December 23, 2013 in .NET, Data Abstract

By the time this blogpost will be published, the Winter 2013 release of Data Abstract will already become available. I feel that I should talk about several important features made available in it, and about a few things that will soon fade in oblivion.

So the new features first.

Private Schema tables access. Local Data Adapters (both dataset-based and DA LINQ ones) are now allowed to access Schema tables that aren’t marked as ‘public’ and thus aren’t accessible by remote clients. There is no need anymore to write additional code to access these tables using local data adapters or from Schema scripts.

Data Abstract for Portable Class Library (aka DA/PCL). Yes, this release contains a (limited) port of Data Abstract to Portable Class Library. You can now build one Class Library and then reuse it in Silverlight, Windows Phone or Windows Store application.

Unfortunately the dreaded Technical Debt monster arose and strikes from the back so the PCL library has some limitations on the desktop .NET Framework. The problem is that the RemoteLinqDataAdapter class is located in differently named assemblies in desktop .NET and in all other platforms (namely RemObjects.DataAbstract.Linq.dll and RemObjects.DataAbstract.dll). Introducing the .Linq assembly back-when was a good (and the only) way to introduce DA LINQ without breaking support of .NET 2.0. And an additional assembly wasn’t an issue until a need to create portable set of assemblies arose.

I can say that we plan to provide improve this to more seamlessly support all four .NET platforms (i.e. Windows Phone, Windows Store (WinRT), Silverlight AND desktop .NET) in the next release of Data Abstract. Stay tuned ;)

Important note: Up to this release, non-desktop Data Abstract assemblies had a platform name suffixes in their names (f.e. RemObjects.DataAbstract.Silverlight.dll or RemObjects.DataAbstract.WinRT.dll). Since this release these suffixes exist no more, so ALL assemblies have the same name.

And now to the stuff now considered obsolete.

Data Abstract provides two binary data adapters: BinDataAdapter and Bin2DataAdapter. The former one, BinDataAdapter data adapter, is now considered obsolete and will go away in the next major releases. We have Bin2DataAdapter data adapter that serves the same purpose, is way more advanced and feature-full and, unlike the BinDataAdapter, is supported by Data Abstract on platforms other than .NET and Delphi. The only reason we still shipped BinDataAdapter this long was backwards compatibility. Yet it is time to finally take a step forward and leave this obsolete data adapter behind. So, in the unlikely case that you are still using this data adapter, you really should to consider to switch to the Bin2DataAdapter data adapter. There’s no downside.

Also we have a set of ASP.NET components provided in the RemObjects.DataAbstract.Web.dll. This entire .dll will be removed in the next major release, and has been marked as obsolete. The reason behind this is that the very approach implied by these components is outdated and based on an old model of using ASP.NET. Mixing the UI (ie .aspx code) and data access results in dirty code and errors that can be detected only at runtime, thus resulting in a nightmare while supporting such apps. Believe me, I know. So if you are not using the RemObjects.DataAbstract.Web, then there is no need to worry. If you do then I’d strongly suggest you to either move to the properly layered architecture, where UI has no data access code and/or to take a look at the Data Abstract for JavaScript. It allows to create modern and robust UI and is shipped together with Data Abstract for .NET.

That’s all for now.

Still stay tuned – soon I’ll show you some exciting new features of RemObjects SDK and Data Abstract.

Avatar of Anton

by Anton

Code Deodorant

October 28, 2013 in .NET, Elements, Tools, Visual Studio

We all write smelly code from time to time. Reasons are different, from ‘I’ll rewrite this code later, I just need this feature working now somehow’ to ‘Deadline is coming and this pesky bug is still not fixed’ or some mistake from a junior developer, yet the result is always the same. Every large codebase has lines of code that smell and stink. Of course there is an ideal codebase repository somewhere that does not have a single line of dirty code, or odd reinvent-the-wheel solutions, or patterns misuse etc… But, I’m afraid, that is along the lines of a flying unicorn. In the real world, we sometimes have to sacrifice code purity to deadlines or other reasons. In this case the main goal is to keep the unclean code and the technical debt caused by it manageable. Not a simple task, when the project has more than 55k lines of code, like ROFX/.NET (i.e. Data Abstract, RemObjects SDK, Internet Pack and Script for .NET) does.

So we need a tool that analyzes our source code and helps to pinpoint code that is potentially dirty. Such tools are called Static Code Analyzers. There are several of them available for .NET and I’d like to highlight the one I like best. This particular tool is not tied to C# or VB.NET and works perfectly with Oxygene code. It also provides Visual Studio integration (including the upcoming VS 2013), and it can also be run on a build machine as a part of the build process. This awesome tool is called NDepend (http://www.ndepend.com/).

In the following, we will create a simple application and apply NDepend to it. We’ll use Oxygene, as I need to show you how to avoid some sharp edges. While C# support in NDepend is near perfect, there are some (minor) nuisances that need to be avoided for Oxygene projects.

Let’s create an Oxygene for .NET Class Library project and add some code like this:

namespace SampleClassLibrary;

interface

type
  Class1 = public class
  private
    var fUnusedField: Int32;

    method NeverCalledMethod(); empty;
  public
    constructor(); empty;
  end;


  UtilityClass = public class
  public
    class method Foo(); empty;
  end;


 SomeBaseClass = abstract class
  public
    constructor(); empty;

    method AbstractMethod(); abstract;
  end;


implementation
end.

As you can see, there are several things that are not ideal, like unused fields and methods or the public constructor of an abstract class. This is, of course, simplified code, where all such things are clearly visible. At the same time, it is very hard to find all suspicious places in a real-world codebase, where the code was created by dozens of different developers and is spread between several projects containing several hundreds of code files. Of course thorough code review would help, but it is still a question of how much efforts it would require. And the question that remains – even after the code review – is to be sure that everything is clean?.

Enter NDepend.

Attach NDepend to the current solution using the menu item NDepend -> Attach new NDepend project to current VS solution.

Because NDepend doesn’t recognize Oxygene projects out of the box, we need to reference the compiled assemblies instead of the source code project, as we would do for C# or VB.NET projects. Press the ‘Add assemblies in Folder‘ button and select the folder containing the current project’s compiled assemblies. Note that NDepend will automatically preselect the folder containing compiled assemblies for the active project.

Confirm the folder selection. Assemblies will be added to the NDepend project.

Press the ‘Analyze a single .NET assembly‘ button and the project analysis will start. After it completes (a very fast procedure, even for big full Data Abstract for .NET solution), a helper dialog will appear.

Open the NDepend rules explorer (NDepend -> Rule -> View Queries).

As you can see, some entries are marked with a warning sign. These are rules that are potentially violated and were successfully detected by NDepend.

  • The abstract class SomeBaseClass should have a protected constructor instead of a public one.
  • The UtilityClass class should be static.
  • The abstract class SomeBaseClass is potentially dead code (it has assembly-only visibility and isn’t used anywhere it this assembly).
  • The Class1.fUnusedField field is not used anywhere and is thus not needed.

Try NDepend on your project and most likely you’ll find some potentially dangerous code lines.

As you can see, NDepend is mostly language independent, so all tutorials and tips ‘n tricks found at http://www.ndepend.com/ can be used with Oxygene, too.

One last advice: For some rules you won’t be able to navigate to a method or class violating some rule by double-clicking the method’s name.

This happens because in some cases (for navigation purposes) NDepend relies on its built-in language parser (that is limited to C# only) rather than on .PDB information. This custom source code parser is used because .PDB files provide information about source code declarations of concrete methods only, so additional effort is needed to acquire information about source code for namespace and type declarations.

To make it easier to find the problematic method, modify the code validation rule output by adding the full method (or class) name. To do this, just change the “rule output statement” (usually found at the very end of each rule’s query code) from code like this (for the Methods that could have a lower visibility rule):

select new { t, t.Visibility , 
                CouldBeDeclared = t.OptimalVisibility, 
                t.TypesUsingMe }

to this:

select new { t, t.Visibility , 
                CouldBeDeclared = t.OptimalVisibility, 
                t.TypesUsingMe,
                t.FullName }

Now you’ll see the full path (including namespace and class name) of the problematic entry.

P.S.: Don’t be afraid of the NDepend query language. It is a very powerful way to define own or customize existing code validation rules. At the same time, the predefined rules set allows to use the code analyzer without even touching the query language at all (except for the above-mentioned issue).

P.P.S.: Before you say ‘Hey, this thing is way too expensive’, try to estimate how much time it will save you and your team members and how much this time costs.

Avatar of Anton

by Anton

Data Abstract for Beginners Guide

October 11, 2013 in .NET, Data Abstract

Do what I do. Hold tight and pretend it’s a plan!

Introduction

Not long ago we published the RemObjects SDK Beginners Guide. Now we’re taking it one step further and look at the Data Abstract framework.

Most present-day business applications operate with some database data, and most often they are required to run on a variety of mobile devices (from laptops accessing the network over WiFi connections to iPad and Android tablets); now add performance and security concerns and you get an explosive mixture that could take an unpredictable amount of efforts to deal with.

So how can Data Abstract help to minimize these software development risks? Take a look at just some of the features this framework provides:
a) Supports a huge variety of platforms on the client side and .NET (or Mono) on the server side.
b) Provides the ability to create SSL-protected or AES-encrypted communication channels.
c) It is possible to use literally any relational database that has an ADO.NET driver.
d) Data source (database schema or even database server type) can be changed without any changes in the server or client code.
e) Data is sent over the wire in binary-serialized compressed form to keep network traffic at a minimum.
f) The .NET client side provides simple-to-use LINQ interfaces, as well as old-fashioned DataTable-based interfaces to the remote data.
g) With our pre-built Relativity Server you can set up your own middle tier server without writing a line of code.
…and much more.

The article below describes the core Data Abstract facilities and their relationships. It also provides a (very short) jump-in crash course into Data Abstract. In just a few minutes you will be able create your first Data Abstract-based server and client applications.

Overview

Data Abstract is built on top of the RemObjects SDK communication framework. In short, a Data Abstract server application is a RemObjects SDK-based server with database connection management, efficient data exchange protocol and declaratively (i.e. not in the program code) defined mapping between the database schema and the data structure exposed to the client applications. On the client side, Data Abstract provides components to simplify the data access so there is no need to manually compose calls to the server.

So the whole picture looks like this:
Data Abstract Overview

As you can see, the core Data Abstracts components are:

  • The ConnectionManager that manages connections to the underlying database (or databases). It allows to pool database connections if the database’s ADO.NET driver doesn’t provide this feature or when more precise control over the connections pool is needed.
  • The Schema that describes mapping between the underlying database tables and data structures exposed by the server (called data tables). The client application only has access to the data exposed via Schema tables, without direct access to the underlying database tables. Schemas can be edited using the Schema Modeler tool.
    Note that the Schema mapping is not necessarily a 1-to-1 mapping (i.e. the database table is exposed as a Schema table). For example, it is possible to expose the result of an SQL SELECT statement as a Schema table and to handle any data updates applied to this Schema table using stored procedures. This approach allows to filter data on data access, do additional data integrity checks on data updates, etc., completely transparent to the client application. Also, some database tables are not suited to be exposed as Schema tables.
  • The DataService, a predefined RemObjects SDK service that exposes Schema data. In most cases there is no need to add any code to this service’s definition.
  • The DataStreamer component that serializes data request results and and data update requests. DataAbstract provides two data streamers – one that exposes data using the highly effective Binary format and another that uses the JSON format to exchange data. The latter one allows to exchange data with platforms that we don’t provide a Data Abstract client library for (f.e. PHP or Ruby server code).
  • The DataAdapter, a client-side component that encapsulates the server method’s calls.

Sample Application

Let’s create a simple server and client application and see how the Data Abstract components are used in a real Data Abstract-based application. Luckily, Data abstract provides a simple-to-use project wizard, so an application skeleton can be created in literally 10 seconds. Just follow these steps:

  1. Start Visual Studio and create a new solution using the Data Abstract -> Windows Forms Application template.
    New Project
  2. Select the ‘Client and a New Custom Data Abstract Server’ project kind on the Wizard screen to create both server and client Data Abstract applications, so we’ll be able to investigate both server- and client-side code.
  3. Select the Default Connections -> PCTrade-SQLite database connection. This pre-defined connection points to a sample SQLite database created whith the Data Abstract installation.
    Database Connection
  4. Now we need to select the database tables that will be included in the Schema generated for the server application. Leave all tables selected and proceed to the next wizard page.
    Schema Tables
  5. The last Wizard page allows to set up some additional options for the solution. We need to keep things simple, so uncheck the ‘Add Login Service’ and ‘Add support for Business Rules Scripting’ project options.
    Project Options

After the Finish button is pressed, the new solution containing the Data Abstract server and client applications will be generated.
You can find a detailed description of both server and client application projects in the corresponding Wiki articles:

For now, let’s examine the core Data Abstract components used in the solution and proceed to actually retrieving data from the server.

Server Application

DataService and DataStreamer

First, we need to take a look at the server’s RODL and the DataService definition.
Service Builder
As you can see, the server’s data service descends from the DataAbstractService defined in the core Data Abstract RODL and doesn’t define any new service methods. This allows us to avoid importing the custom interface file generated for this project, because a pre-generated interface for all service methods is already included in the RemObjects.DataAbstract.dll assembly.
Note that the DataService code file doesn’t actually contain any custom method definitions. All methods used in the Data Abstract client-server communication process are already defined in the base DataAbstractService class. Of course it is possible to add event handlers or even to override method definitions inherited from the base DataAbstractService class, yet this is not needed in the current sample application. However, there are some vital settings that have to be set for the Data Abstract Server to function. In our case, these properties were already set by the New Project Wizard.
Open the DataService implementation in design mode.
First you will see the DataStreamer component. It is tied to the Data Service via its ServiceDataStreamer property.
Data-Abstract-Beginners-Guide-Data-Service-Properties
Also note the AcquireConnection and ServiceSchemaName properties. The first one defines whether the database connection should be acquired using the default Connection Manager when the service is accessed by the client app or if a more advanced connection retrieval process should implemented in the user code (this is not needed for simple Data Abstract servers, but for example Relativity Server uses its own connection management engine). The ServiceSchemaName property points to the project file containing the Schema definition. On application startup, Data Abstract will load this file, deserialize the Schema from it and cache the result.

Connection Manager

The Engine.cs file contains definitions of network-communications-related stuff like Server Channel, Session Manager and Message (see the RemObjects SDK Beginners Guide for more information about these components). Additionally, it contains the Connection Manager that will handle connections with the underlying database.
The Connection Manager will load connection definitions from the .daConnection file on server application startup and will provide connection instances (either from its own internal pool or directly from the driver).
Data-Abstract-Beginners-Guide-Engine

Schema

The last (but not least) server application element is the .daSchema file. It contains the mapping between the underlying database and the data structures actually exposed by the server application.
In the simplest case, the database tables are mapped on a 1-to-1 basis to the Schema tables. This the easiest scenario. At the same time, Data Abstract makes it possible to, for example, define a Schema table that exposes data from a complex SQL query involving joins of several tables as a plain table. Given that the needed SQL statements (either stored procedures or plain SQL statements) are defined to handle insert, update and delete operations, the client application will work with the data as if it was a simple plain table. Furthermore, if in the future the data source structure will be changed (for example if a data table containing the needed data will be introduced to the database schema) it would be possible to point the Schema table to this changed data source without changing a line of code in either the server or the client application.
The .daSchema file can be edited using a tool called Schema Modeler. The Schema Modeler can be started either as a standalone application from the Windows Start menu or by double-clicking the .daSchema file in the Solution Explorer.

Additional Information

You can find more about the generated server application project in the following Wiki article.

Client Application

Overview

The client application doesn’t differ much from an ordinary WinForms (in this case) application. It contains the main form, the regular Program.cs file, as well as a usual set of references.
Client-side Data Abstract stuff is contained in the RemObjects.DataAbstract.dll assembly. Also, the RemObjects SDK client-side set of assemblies (i.e. the RemObject.InternetPack.dll, the RemObjects.SDK.dll and the RemObjects.SDK.ZLib.dll) is required for Data Abstract, because the network communication relies on the RemObjects SDK infrastructure.
Note that the client application doesn’t contain a custom interface file. It is not needed because all interface classes and interfaces needed to communicate with the server are already defined in the RemObjects.DataAbstract.dll assembly. Of course, if the client application needs to call some custom server methods, a custom interface file will be required.
Look at the Data Module project element. It contains pre-configured server communication components.
Data Module

The Client Channel and Message components are used to send data to the server and retrieve its responses.
The Data Streamer, Data Adapter and Remote Service components, however, are Data Abstract-specific. They are configured to work together:

  • Remote Service receives requests from the Data Adapter and sends them to the server using Client Channel and Message.
  • Data Streamer is used by the Data Adapter to serialize and deserialize requests (including data table data and data update requests). Data Abstract supports two types of Data Streamers – binary and JSON-based. The binary Data Streamer (implemented in the Bin2DataStreamer class) is the preferred one to use, because it is faster and its use consumes less network traffic. Please note that Data Streamer types used by the client and server applications should match, otherwise data exchange won’t be possible.
  • Data Adapter is basically the core of the client-side Data Abstract infrastructure. It exposes the APIs needed to retrieve data from the server and to send data update requests without the need to explicitly call Data Streamer to serialize the data, call server methods etc. And again, there are two Data Adapter kinds that differ in the way data is accessed – via LINQ request or using plain System.Data.DataTable instances (either typed or untyped). Both kinds of data adapters can be used with the same server application (or even in the same client application).

Additional Information

You can find more about the generated client application project in the following Wiki article.

Data Access via DA LINQ

Now let’s fetch some data from the server and then post some update data back to it. In the following, I’ll show both the LINQ and the DataTable way of accessing the data. Let’s begin with DA LINQ, as it is the more advanced approach. You can consider DA LINQ as a (very simple) ORM that fetches data from the remote server and converts it into objects.
As you can see, the client application contains a TableDefinitions_… file. This mysterious file contains a set of classes that are code representations of Schema tables. Each public Schema table is mapped to one of the classes contained in this file, including all table fields represented as class properties. This means that this file should be regenerated in case the data structure of the Schema tables exposed by the server is changed. This article describes how to manage the table definition classes. I suggest you to read this article later, as for now we already have the needed set of Table Definition classes.
To emphasize that Data Adapters (and any other Data Abstract or RemObjects SDK component) can be configured in code and designer support is just a way to speed up development, the following code will use a Data Adapter defined in code.
So let’s instantiate the Data Adapter, create some data access and data update methods and tie them to the GUI.

1. Data Adapter definition
Define private field

LinqRemoteDataAdapter fLinqDataAdapter;

Add the following code to the constructor (AFTER the InitializeComponent method call):

this.fLinqDataAdapter = new LinqRemoteDataAdapter();
this.fLinqDataAdapter.DataStreamer = this.dataStreamer;
this.fLinqDataAdapter.RemoteService = this.remoteService;

Now the Data Adapter is instantiated and tied to the Data Streamer and Remote Service instances.
2. Data access
The simplest Data Access method would look like this:

public BindingList<Customers> GetData()
{
  var lServerQuery = from x in this.fLinqDataAdapter.GetTable<Customers>() select x;
  return lServerQuery.ToDABindingList();
}

Note how the data is accessed with a simple LINQ statement on the this.fLinqDataAdapter.GetTable() object. Data Abstract does all the work needed to convert the provided LINQ expression into a form that can be understood by the server application, send the request over the network and retrieve the data. The query used here is very simple. More advanced queries are shown by the DA LINQ Sample, including queries with conditions and queries that fetch only a subset of the target’s table columns.

The mysterious BindingList is a class that simplifies data binding. You can read more about this class in the corresponding wiki article. Of course, the data can be loaded into a simple List<T> as well.

3. Data update
The data update method is very simple:

public void UpdateData()
{
  this.fLinqDataAdapter.ApplyChanges();
}

The Data Adapter tracks changes made to the data into a BindingList, so all changes can be applied using a single line of code. More advanced scenarios are out of the scope of this article. You just need to know that it is possible to make data changes using methods like AddRow, UpdateRow and DeleteRow exposed by remote table instances that can be acquired using the GetTable<T> method of the Data Adapter.

4. GUI
Add 2 buttons and a Data Grid View to the main form of the client application.
Data Abstract Client Main Form
Add the following code to the Click handler of the Get Data button:

this.dataGridView1.DataSource = this.fDataModule.GetData();

Add the following code to the Click handler of the Update Data button:

this.fDataModule.UpdateData();

Run both server and client applications and try to fetch data from the server, update some fields in the data grid and then push the updated data to the server. And that’s it. You have created a network server and client application and added load and save data features to the client application using just a few lines of code.
Data Abstract Client Main Form

Data Access via DataTables

While DA LINQ is the more preferred way of accessing data, Data Abstract also exposes a more old-fashioned data access interface, based on the System.Data.DataTable instances, both strongly typed (corresponding to the server Schema) and untyped ones. This article describes how to manage the strongly typed dataset definitions.

In the following part of the tutorial, we’ll use the untyped dataset, for simplicity reasons.

So let’s again instantiate the Data Adapter, create some data access and data update methods and tie them to the GUI.

1. Data Adapter definition
Define private field

RemoteDataAdapter fDataAdapter;

Add the following code to the constructor (AFTER the InitializeComponent method call):

this.fDataAdapter = new RemoteDataAdapter ();
this.fDataAdapter.DataStreamer = this.dataStreamer;
this.fDataAdapter.RemoteService = this.remoteService;

As you can see, the instantiation of the Data Adapter and its setup are very similar to the LINQ Data Adapter.

2. Data access
In the case of the table-based Data Access, the simplest data access method would look like this:

public System.Data.DataTable GetDataTable()
{
  System.Data.DataSet lDataSet = new System.Data.DataSet();
  this.fDataAdapter.Fill(lDataSet, new String[] { "Customers" }, true);
  return lDataSet.Tables[0];
}

This code fetches only the Customers data table from the server.

3. Data update
The data update method is very simple:

public void UpdateData(System.Data.DataTable table)
{
  this.fDataAdapter.Update(table.DataSet);
}

Note that unlike the LINQ Data Adapter, the Table Data Adapter relies on the .NET DataSet to track data changes.

4. GUI
Change the Click handler of the Get Data button to

this.dataGridView1.DataSource = this.fDataModule.GetDataTable();

Also change the Click handler of the Update Data button to

this.fDataModule.UpdateData((System.Data.DataTable)this.dataGridView1.DataSource);

Run both server and client applications and try to fetch data from the server, update some fields in the data grid and then push the updated data to the server.
As you can see, the table-based access is similar to the DA LINQ-based one, but still differs from it in some details. It is up to you to choose the approach to use, as both of them are valid and fully supported by Data Abstract.

Conclusion

This article only scratches the surface of the Data Abstract framework world. Again (as in the RemObjects SDK Beginners Guide) many features weren’t touched or even mentioned to simplify the article.

Search our Wiki for the questions you are interested in. If for some reason you can’t find the info you need, don’t hesitate to call on our support via RemObjects Connect or drop an email to support@remobjects.com.
I would also be glad to hear your suggestions on what to describe next – Relativity Server, Olympia, or something else?

Avatar of marc

by marc

Announcing Oxygene 6.1

September 9, 2013 in .NET, Cocoa, Elements, Java

We’re thrilled to announce the immediate availability of Oxygene 6.1, the next feature release for Oxygene after the introduction of Oxygene for Cocoa earlier this year.

Like most of our monthly updates, this “August 2013″ release contains a vast number of fixes, improvements and enhancements all across the board, and for all three platforms. It also provides a small handful of new major features that we are really excited about and think will make a great difference in your day-to-day work using Oxygene.

First off, 6.1 marks the introduction of our Refactoring engine for Oxygene. We’re starting out small, with one very useful refactoring: the ability to safely rename identifiers solution-wide. But this also lays the groundwork for more refactorings to be added in the near future.

We have also vastly expanded the Go To Definition feature of the IDE to work for external references. This makes it easier than ever to have a peak at the declaration of the classes you are using, from .NET classes such as System.String to Cocoa ones such as UITableView. Just right-click, choose Go To Definition, and Oxygene will bring up the class declaration – in full Pascal syntax, of course – ready for you to review, or to copy method headers from.

Cocoa developers will love to hear that we added even better support for Deployment Targets to the compiler, with improved weak linking, and optional warnings when your code uses classes that may not be available in the lowest deployment target SDK you selected for your project. This goes way beyond what Xcode offers, and – especially with iOS 7 coming up now – will make your life supporting apps on new and older OS versions so much easier.

Of course that’s not all. There’s also support for optional interface methods in Cocoa, unsigned integer types on Java, and much more. You can find the full list of changes on our What’s New and Change Logs pages.

How to get Oxygene 6.1

As always, Oxygene 6.1 is a free update to all active subscribers, and can be downloaded now.

If your subscription has elapsed, now is a great time to renew to get access to the latest release, and all the good stuff we have cooking for the near future.

Oxygene for Prism Customers

Oxygene 6.1 is also the first release that is no longer available from Embarcadero under the Prism brand, and it will not accept Prism XE3.2 serial numbers. But as a reminder: we are committed to honoring SA contracts Embarcadero might have sold you with the promise of Prism coverage (i.e. before April 23) . Please email sales@remobjects.com with your SA details, and we’ll sort you out with ongoing access to Oxygene for .NET for the remainder of your SA period.

Of course, if you do not have SA, or if you want to take advantage of Oxygene on the Cocoa and Java/Android platforms as well, you can always renew or cross-grade to the full Oxygene package at any time.

More to Come

2013 has been a great year for Oxygene so far, but we’re not done yet. We’ve got more amazing things planned for the rest of the year, and beyond. So make sure to stay up to date with your subscription.

Happy coding!

marc hoffman,
Chief Architect
RemObjects Software

Avatar of marc

by marc

Duck Typing in Action

July 31, 2013 in .NET, Cocoa, Cooper, Elements, Nougat

I came across a really awesome use of Duck Typing yesterday, and i wanted to share this with you, since i think Duck Typing is one of those features in Oxygene that are incredibly powerful, but underrated – probably even unknown to many users.

This is actual code that is live on our website, and it’s driving the downloads lists for licensed products and betas.

Both download pages are driven by the same .ascx, which runs a query to get the products a user has access to, and then compares it to the available downloads (passed in as aFiles), to determine what files to show. The code looks something like this:

method DynamicDownloadList.PrintProductFiles(aFiles: sequence of BetaFile; aBeta: Boolean);
begin
  if aBeta then begin
 
    var lProducts := from p in DataAccess.Linq.GetTable<ByUser_BetaProducts>(...) 
                       order by p.DisplayOrder;
    // loop and print out files
 
  end                                    
  else begin
 
    var lProducts := from p in DataAccess.Linq.GetTable<ByUser_LicensedProducts>(...) 
                       order by p.DisplayOrder;     
    // loop and print out files
 
  end;                                    
 
end;

The code that i’ve abbreviated behind the “//loop and print out files” comment was actually just 5 lines, but it was mostly identical for both beta and final downloads. I still had to duplicate it, because the two LINQ queries, of course, returned sequences of different types. Which is kind of a bummer, if you think about it – these are two queries (actually, Data Tables defined in the DA server that apply quite a bit of complex logic) that return the same kind of data, but due to the way LINQ works, because they are different tables, the resulting objects are of different classes.

So even though both ByUser_BetaProducts and ByUser_LicensedProducts contain fields like ProductID, Name, ImageName, and so on, it’s not really easy to write code that can be shared and work against either version. (To boot, these classes are auto-generated by LINQ, so it’s not like i can just add a common interface to the ancestry list, either.)

Yesterday i set out to expand the logic for the download display a bit (in particular to improve how the unified “Oxygene” download shows for people who own all three platforms), and i found the duplicate code turning too complex to stay duplicated. Sometime it’s fine to copy/paste 3-5 simple lines of code into two places, but this was getting more sophisticated than i liked sharing and maintaining in two places.

Duck Typing to the rescue!

So what i needed to do was write code that could work on two classes that have no common ancestor and no shared interface, but look “similar”. Exactly what Duck Typing was made for!

First, i went ahead and declared the following interface:

type
  IByUserProducts = public soft interface 
    property ProductID: System.Guid read;
    property Name: System.String read;
    property ImageName: System.String read;
    property OptionalMessage: System.String read;
    property DateExpires: nullable System.DateTime read;
  end;

that defined all the members from the query i needed access to.

Next, i adjusted the LINQ code just ever so slightly:

method DynamicDownloadList.PrintProductFiles(aFiles: sequence of BetaFile; aBeta: Boolean);
begin
  if aBeta then begin
 
    var lProducts := from p in DataAccess.Linq.GetTable<ByUser_BetaProducts>(...) 
                       order by p.DisplayOrder 
                       select duck<IByUserProducts>(p, DuckTypingMode.Weak);
    // loop and print out files
 
  end                                    
  else begin
 
    var lProducts := from p in DataAccess.Linq.GetTable<ByUser_LicensedProducts>(...) 
                       order by p.DisplayOrder 
                       select duck<IByUserProducts>(p);
    // loop and print out files
 
  end;                                    
 
end;

The only thing i changed is that at the end of the from clauses i added an extra select operator to change what the LINQ query returns: duck-typing the specialized class returned from DA into the custom IByUserProducts interface i declared.

Now, instead of returning sequences of ByUser_BetaProducts and ByUser_LicensedProducts respectively, both queries return the same type: a sequence of IByUserProducts.

This, in turn, means that i could take all the code from “// loop and print out files” and move it into a separate function, called from both branches.

Presto: shared code!

DuckTypingMode.Weak

If you’re eagle-eyed, you might have noticed that i’m passing DuckTypingMode.Weak to the duck() function in the first branch, but not the second. What does that do?

Simply put, i lied when said that the two queries returned the exact same set of fields. In fact, the query for release products returns a few extra fields, including the expiration date (which i need to gray out newer downloads if a subscription expired – in contrast to beta downloads, where the whole product just disappears).

DuckTypingMode.Weak allows the duck typing to IByUserProducts to succeed, even though the underlying class does in fact not fully qualify for the interface, because it’s missing the DateExpires property. Oxygene will instead inject a stub that will throw an exception if DateExpires were to be called.

But that’s fine. All i need to do in my now shared code is check the aBeta flag, and make sure i don’t actually call DateExpires when i know it’s not there, and i’m all good!

Summary

To summarize, Duck Typing is an awesome way in Oxygene to let you write code against classes that have the same (or similar) API, but don’t have a common ancestry or shared interfaces.

Of course, if you have full control over the class hierarchy yourself, the easiest (and cleanest way) to achieve this is to just define an interface and have the classes implement it. But sometimes, as in this example, the actual classes are out of your hand. Duck Typing lets you get around this nicely and safely.

Soft Interfaces

You might have noticed that i used the soft keyword when defining the interface, above. This was actually not fully necessary, as the duck() function will work with any kind of interface.

Soft interfaces approach duck typing from the opposite end: by defining the interface as “soft”, i don’t actually need the duck() call, as soft interfaces carry with them the information that they may automatically be duck-typed too, with a simple cast. As such, a simple select p as IByUserProducts would do to convert the types.

However, soft interfaces use the default (static) duck-typing mode by default, not the weak duck-typing. So this approach would have worked for the Beta branch of my code, which is why i chose to explicitly call duck() in both cases, for clarity. (Yes, i could/should drop the unnecessary soft keyword then, but i left it in to have an excuse to talk about it here ;).

You can read more about Duck Typing and Soft Interfaces on our wiki.

Avatar of marc

by marc

Announcing the Oxygene 6 “July 2013″ Update

July 30, 2013 in .NET, Cocoa, Cooper, Elements, iOS, Java, Nougat, Oxygene, Platforms, Visual Studio, Windows


Oxygene "July 2013"

We’re thrilled to inform you that the “July 2013″ update for Oxygene 6 is available now.

The team has been incredibly hard at work since we shipped Oxygene 6 in May, both on this update and on the next feature release coming up in August, and the “July 2013″ update brings with it a good ~140 fixes and improvements across all three editions and across the entire toolchain, from compiler to IDE.

Even though we consider this update a “bug-fix release”, we could not stop ourselves from including two major compiler/language enhancements, as well: On the Java/Android side, the Oxygene language has gained full support for unsigned integer types — a feature not available in the Java language and not officially supported by the Java Runtime, we know that a lot of you who use Oxygene on Java have been looking forward to this. On the Cocoa side, the compiler has been updated with support for Oxygene’s trademark Future Types (one of my favorite features), based on GCD under the hood.

With these two changes, we’re taking another big step towards bringing the Oxygene language closer together on all three platforms.

What’s Next?

We’ve also been busy at work for the upcoming 6.1 release (for which alpha/beta builds have been available for a while now) and beyond. Check out my blog post for more details and some hints at what is coming up. We’re very excited.

Prism

Embarcadero Prism customers, please note that the “July 2013″ release will be the last update made available to you under the Prism brand, and the last release to accept Embarcadero serial numbers.

Please make sure that you have your Prism XE3.2 serial number registered with us, so that we know about you and can contact you about moving forward. As mentioned in the past, we will honor existing SA agreements you may have with Embarcadero beyond July – but we can only do that if we know who you are ;).

As always, if you have any questions or concerns at all, please contact us at sales@remobjects.com.

Yours,
marc hoffman
Chief Architect

Avatar of Anton

by Anton

NetworkServer – an easily configurable RemObjects SDK server component

July 16, 2013 in .NET, Data Abstract

Introduction

In the previous article I’ve described how to create a RemObjects SDK server and set up the needed server components and tie them together.

The main purpose of the RemObjects SDK and Data Abstract frameworks is to simplify the development of distributed applications, yet some of the tasks needed to create a server application are the same for each server (f.e. server startup code, network component with server channel, messages, session manager etc).

Last year we introduced the ApplicationServer helper class (a unified base class for RemObjects SDK-based servers), so you can concentrate on the server’s business logic, not on writing the same (most of the time) server application startup code with all these checks like “are other instances of the server already running”, “do we need to start as a Windows Service” etc.

Now it is the time to make one more step forward and take a look at another core server application part that is again implemented in the same way as most of the server applications – the network connectivity part.

Network connectivity components include the server channel, one or more server messages, the session manager, event sinks, the event queue manager, the ZeroConf support component, etc. It is sometimes boring and error-prone to properly set them all up manually, and f.e. changing the server channel type can be a lot harder than it ought to be.

So we decided to implement and implemented a feature called ‘Server Reconfiguration System’. In short, this new feature allows to set the server connectivity parameters via its configuration file:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="ServerConfiguration" type="RemObjects.SDK.Server.Configuration.ServerConfigurationSection,RemObjects.SDK.Server" />
  </configSections>
  <ServerConfiguration>
    <ServerChannel type="superhttp" port="8101" enableZeroConf="true" />
    <ServerMessages>
      <ServerMessage type="bin" />
      <ServerMessage type="soap" />
    </ServerMessages>
    <SessionManager type="Memory" />
  </ServerConfiguration>
</configuration>

So there is no need anymore to rebuild the server application to change the Server Channel port, its type (i.e. protocol), or even to change the session storage from memory to Olympia Server.
And for sure, the generated components can be accessed via code and customized as needed.

Let’s take a look at this new feature in action. As the only difference is how the server network connectivity is configured in step 7, please refer to the RemObjects SDK Beginners Guide for steps 1 – 6.

Server Application

7. Open the code-behind file for the main form (remember that our server app is intentionally primitive, so no properly layered architecture or ‘Run As Windows Service’ support is available here) and add the following private field:

private RemObjects.SDK.Server.INetworkServer server;

Also modify the form constructor:

public Form1()
{
    InitializeComponent();

    this.server = new RemObjects.SDK.Server.NetworkServer();
    this.server.LoadDefaultConfiguration();
    this.server.Start();
}

Now we have to provide the license information for the server components. To do this, add a file named licenses.licx to the server application project and set its Build Action to Embedded Resource. This file should contain the following text:

RemObjects.SDK.Server.IpTcpServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.IpSuperHttpServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.IpHttpServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.NamedPipeServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.LocalServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.HttpSysServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.HttpSysSuperHttpServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.SuperTcpServerChannel, RemObjects.SDK.Server
RemObjects.SDK.Server.EventSinkManager, RemObjects.SDK.Server
RemObjects.SDK.Server.MasterServerSessionManager, RemObjects.SDK.Server
RemObjects.SDK.Server.MemoryMessageQueueManager, RemObjects.SDK.Server
RemObjects.SDK.Server.MemorySessionManager, RemObjects.SDK.Server
RemObjects.SDK.Server.OlympiaMessageQueueManager, RemObjects.SDK.Server
RemObjects.SDK.Server.OlympiaServerSessionManager, RemObjects.SDK.Server

At build time the license compiler will embed the needed license information into the server application based on the class names provided in this file.

The server application can now be started. It will use the default settings (i.e. the Http Server Channel will be listening on port 8099 and Binary Message will be used to communicate with the client applications).

8. Add the Application Configuration File item to the server app project and add the following settings:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="ServerConfiguration" type="RemObjects.SDK.Server.Configuration.ServerConfigurationSection,RemObjects.SDK.Server" />
  </configSections>
  <ServerConfiguration>
    <ServerChannel type="superhttp" port="8101" enableZeroConf="true" />
    <ServerMessages>
      <ServerMessage type="bin" />
      <ServerMessage type="soap" />
    </ServerMessages>
    <SessionManager type="Memory" />
  </ServerConfiguration>
</configuration>

Note: To ensure that the .NET application config file handlers will be able to properly load custom config sections, set the Copy Local property of all referenced RemObjects SDK assemblies to true.

After restart the server application will expose its services via the SuperHttp Server Channel listening on port 8101. And this without a single code line changed.

Now it is possible to change the Server Channel protocol (HTTP, SuperHTTP, TCP, SuperTCP), the port it is listening to and other options without the need to rebuild the server application.

A full list of available options will be provided in the corresponding Wiki article.

Conclusion

The introduction of the NetworkServer class and the corresponding infrastructure allows to easily create highly configurable RemObjects SDK server applications.