.NET SDK for DreamFactory API

ToddAppleton

Hey, .NET fans! We're pleased to announce the immediate availability of a new SDK interface for connecting your .NET apps to databases or other services via the DreamFactory Services Platform (DSP). Like all of our SDKs (we also offer ones for iOS, Android, and JavaScript), this one offers user-friendly wrapper functions for commonly-used API calls. You don't have to spend days learning the details of the API - the SDK takes care of that for you. While recommended, there's no requirement to use the SDK for your .NET apps. All you need is a way to make the HTTP calls to your DSP.

The SDK is available from GitHub or it can be installed from nuget.org. The README on GitHub offers lots of details about installing or building from source code. The SDK is built with .NET 4.5 but you can easily build with .NET 4.0 if needed. It comes with a unirest-net implementation of IHttpFacade - the UnirestHttpFacade class. You can also define your own implementation to use with the DreamFactory API by providing a custom IHttpFacade.

Let's look at a few examples of how to authenticate to your DSP and make some CRUD calls to its default MySQL database. There's demo code available in the GitHub repo for all of these functions.



Login

namespace DreamFactory.Demo.Demo
{
    using System;
    using System.Threading.Tasks;
    using DreamFactory.Api;
    using DreamFactory.Model.User;
    using DreamFactory.Rest;

    public class LoginDemo : IRunnable
    {
        public async Task RunAsync(IRestContext context)
        {
            IUserApi userApi = context.Factory.CreateUserApi();

            try
            {
                Session session = await userApi.LoginAsync(Program.DefaultApp, Program.Email, Program.Password);
                Console.WriteLine("Logged in as {0}", session.display_name);
            }
            catch (Exception)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Unfortunately, something went wrong.");
                Console.WriteLine("Please check the following:");
                Console.WriteLine("\t- your DSP is listening: {0}", Program.BaseAddress);
                Console.WriteLine("\t- you have created user '{0}' with password '{1}'", Program.Email, Program.Password);
                Console.WriteLine();
                Console.ResetColor();

                throw;
            }
        }
    }
}

Create 'staff' Table and CRUD Some Records

namespace DreamFactory.Demo.Demo
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Threading.Tasks;
    using DreamFactory.Api;
    using DreamFactory.Model.Builder;
    using DreamFactory.Model.Database;
    using DreamFactory.Rest;

    public class DatabaseDemo : IRunnable
    {
        private const string TableName = "staff";

        public async Task RunAsync(IRestContext context)
        {
            // Getting database interface
            IDatabaseApi databaseApi = context.Factory.CreateDatabaseApi("db");

            // List available tables
            List tables = new List(await databaseApi.GetTableNamesAsync());
            Console.WriteLine("Existing tables: {0}", tables.ToStringList());

            // Delete staff table if it exists
            if (tables.Contains(TableName))
            {
                Console.WriteLine("Deleting table {0}...", TableName);
                if (await databaseApi.DeleteTableAsync(TableName))
                {
                    Console.WriteLine("Table deleted.");
                }
            }

            Console.WriteLine("Creating {0} table schema...", TableName);
            TableSchema staffTableSchema = CreateTestTableSchema();
            await databaseApi.CreateTableAsync(staffTableSchema);

            // Describe table
            staffTableSchema = await databaseApi.DescribeTableAsync(TableName);
            Console.WriteLine("Got {0} table schema, table's label is {1}", TableName, staffTableSchema.label);

            // Create new record
            Console.WriteLine("Creating {0} records...", TableName);
            List records = CreateStaffRecords().ToList();
            records = new List(await databaseApi.CreateRecordsAsync(TableName, records, new SqlQuery()));

            SqlQuery query = new SqlQuery { filter = "age > 30", order = "age", fields = "*" };
            var selection = await databaseApi.GetRecordsAsync(TableName, query);
            var ages = selection.Select(x => x.age.ToString(CultureInfo.InvariantCulture)).ToStringList();
            Console.WriteLine("Get records with SqlQuery: ages={0}", ages);

            // Deleting one record
            Console.WriteLine("Deleting second record...");
            await databaseApi.DeleteRecordsAsync(TableName, records.Skip(1).Take(1));

            // Get table records
            records = new List(await databaseApi.GetRecordsAsync(TableName, new SqlQuery()));
            Console.WriteLine("Retrieved {0} records:", TableName);
            foreach (StaffRecord item in records)
            {
                Console.WriteLine("\t{0}", item);
            }
        }

        private static IEnumerable CreateStaffRecords()
        {
            yield return new StaffRecord { first_name = "Andrei", last_name = "Smirnov", age = 35, active = true };
            yield return new StaffRecord { first_name = "Mike", last_name = "Meyers", age = 33, active = false };
            yield return new StaffRecord { first_name = "Selena", last_name = "Gomez", age = 24, active = false };
        }

        private static TableSchema CreateTestTableSchema()
        {
            ITableSchemaBuilder builder = new TableSchemaBuilder();
            return builder.WithName(TableName).WithFieldsFrom().WithKeyField("uid").Build();
        }

        // ReSharper disable InconsistentNaming
        internal class StaffRecord
        {
            public int uid { get; set; }
            public string first_name { get; set; }
            public string last_name { get; set; }
            public int age { get; set; }
            public bool active { get; set; }

            public override string ToString()
            {
                return string.Format("{0}: name = {1} {2}, age = {3}, active = {4}", uid, first_name, last_name, age, active);
            }
        }
    }
}

Logout

namespace DreamFactory.Demo.Demo
{
    using System;
    using System.Threading.Tasks;
    using DreamFactory.Api;
    using DreamFactory.Rest;

    public class LogoutDemo : IRunnable
    {
        public async Task RunAsync(IRestContext context)
        {
            IUserApi userApi = context.Factory.CreateUserApi();
            bool success = await userApi.LogoutAsync();
            Console.WriteLine("Logged out, success={0}", success);
        }
    }
}

The SDK also supports operations on other resources like files, email, and system objects. To try it out first you need to create a DSP using one of the methods listed in the 'Usage Options' sidebar on the wiki. Then edit the SDK source code to point to your DSP. See the README for instructions on how to run the demo code in Visual Studio. Give it a try and let us know what you think!