Skip to content

Instantly share code, notes, and snippets.

@tylerlong
Last active June 12, 2016 21:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tylerlong/83734063cafeb523684229f2014da646 to your computer and use it in GitHub Desktop.
Save tylerlong/83734063cafeb523684229f2014da646 to your computer and use it in GitHub Desktop.
C# SDK 1.0.0

RingCentral C# SDK 1.0.0 has been released

It is the first major release of the C# SDK. It contains lots of bug fixes, improvements as well as some new features.

Portable Class Library

Portable class libraries can help you to reduce the time and costs of developing and testing code. Use this project type to write and build portable .NET Framework assemblies, and then reference those assemblies from apps that target multiple platforms such as Windows, Xamarin.iOS and Xamarin.Android.

Before 1.0.0, we have different SDK projects for different platforms. On some platforms, users even have to compile the code themselves. We turned to PCL (Portable Class Library) with the 1.0.0 release. No matter what platform you are targeting, you can install our SDK via NuGet: Install-Package RingCentralSDK, no more manual compiling and dependency management.

The biggest challenge for us when switching to PCL is to find libraries which are PCL compatible. Our SDK is built upon some open source libaries which also have to be PCL compatible. For example: we were using PCLCrypto for message decryption. We found that the code didn't work on iOS. We spent days of time to debug and finally we came to the conclusion that PCLCrypto didn't work on iOS. It should work but for some weird reason we failed to make it working. We did a lot more experiments and testing and we switched to BouncyCastle for decryption which worked like a charm on all the platforms including iOS.

Another challenge is the inconsistence between .NET on windows and Mono on other platforms. For example, the SDK provides the ability to send fax. And the content of the fax is of content type: multipart/mixed. In order to compose a multipart/mixed message, we need a boundary string. In lots of places we use a hard-coded string Boundary_1_14413901_1361871080888 as the boundary string and it works pretty well. But it turned on that the Mono implementation of .NET specification didn't like it and we always got exceptions. The root cause of this issue was very hard to figure out because Mono was supposed to behave exactly the same as Microsoft .NET.

New features & improvements

OAuth 2 Authorization Code Flow

Authorization code flow which is also known as "a 3-legged authorization flow" protects users information and lets them control what they share with your app. You are required to use this flow if your app is a web app and will be used by more than one user.

The C# SDK provides two helper methods to make the implementation of Authorization Code Flow a piece of cake. The first helper method is for generating the authorization URI:

var authroizeUri = sdk.Platform.AuthorizeUri(redirectUri, myState);

Open authroizeUri in browser and let user login and authrize your app. Then user will be redirected to redirectUri where you can get the authCode from its url.

With authCode obtained, simply call the second helper method to do the authencation:

sdk.Platform.Authenticate(authCode, redirectUri)

Live testing

Previously we only did mock tests which we found were not sufficient to mock all the real world situations. It is necessary to do testings against real API server in live to make sure the server and the SDK is actually behaving as expected.

In C# SDK 1.0.0, we have RingCentral.Test.Real in addition to RingCentral.Test.Mock. The former is live testing while the latter is mock testing.

API simplification

Before 1.0.0, you need the following code in order to create a new subscription:

var subscription = new SubscriptionServiceImplementation(){ _platform = ringCentral };

1.0.0 has simplified the code to:

var subscription = sdk.CreateSubscription();

Before 1.0.0, if you want to do HTTP method tunneling, you need to change the HTTP header directly:

request.SetXhttpOverRideHeader("POST");

1.0.0 provides more convenient way:

request.HttpMethodTunneling = true;

Do things the C# way

Properties vs. Methods

In C#, methods represent actions and properties represent data. Properties are meant to be used like fields, meaning that properties should not be computationally complex or produce side effects. When it does not violate the following guidelines, consider using a property, rather than a method, because less experienced developers find properties easier to use.

We've changed lots of methods to properties to simplify the code. examples: sdk.Platform instead of sdk.GetPlatform(), response.Status instead of response.GetStatus().

Events vs. Callbacks

Unlike other programming languages, C# has a special keyword named event. An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object. Events provide a generally useful way for objects to signal state changes that may be useful to clients of that object.

Unlike callbacks, events are good for recurring notifications that can be received by an arbitrary number of listeners. We take advantages of C# events when we are writing code for Pubnub subscription. Here is some sample code:

subscription.NotificationEvent += (sender, args) => {
    Console.WriteLine(args.Message);
};

Coding Conventions

In C#, we use pascal casing for constants. So the following doesn't comply to C# coding style:

public const string SANDBOX_SERVER = "https://platform.devtest.ringcentral.com";

While the following is good:

public const string SandboxServer = "https://platform.devtest.ringcentral.com";

It is considered a bad practice to omit curly braces:

if (_enableSSL) _pubnub = new Pubnub(publishKey, subscribeKey, "", "", _enableSSL);
else _pubnub = new Pubnub(publishKey, subscribeKey);

We've made it easier to read by changing it to the following:

if (_enableSSL)
{
    _pubnub = new Pubnub(publishKey, subscribeKey, "", "", _enableSSL);
}
else
{
    _pubnub = new Pubnub(publishKey, subscribeKey);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment