DuoCode 1.1: Which edition is right for you?

Edit: We hear you! We’ve updated the terms following your feedback. Happy coding!

We’re so excited to have released DuoCode 1.1 with support for the RTM of Visual Studio 2015 and with the latest official release of Roslyn (1.0.0.50618). Get it here! Lots of improvements (and some bug fixes).

And finally, we’re ready to unveil the full pricing details for DuoCode, and we’ve got great news for open-source developers and students - we’ve got a free community edition for you.
And commercial developers have a free trial!

Which edition is right for you?

DuoCode has 3 editions that you can purchase. We’ve designed the editions to be quite similar to Visual Studio 2015 editions.

DuoCode Community

FREE for open-source projects and academic use

We’re so glad to be able to give back to the open-source community, by handing out free licenses for open-source project developers, and for students and instructors.

If you are:
- Leading an open-source project (with OSI license), hosting the project’s code on a public repository such as github
- OR You’re an active student holding an ISIC card or student email
- OR You’re a registered instructor (teaching staff member) in an educational organization
- Your solution has up to 5 projects
- You don’t perform paid consulting or distribute paid versions of the project
- You’re using Visual Studio Community or Professional

You can apply on the forms for open source or academic to get your free license of DuoCode. The license is for one-year but you can apply again when the period is over.

DuoCode Professional

Now on sale (and with free trial!)

If you are:
- Working on a commercial project
- Your organization has no more than 8 DuoCode developers
- Your organization is non-governmental

You can purchase DuoCode Professional. It is now on sale for $149. Each computer running DuoCode requires a license.
You’ll get the full unrestricted DuoCode compiler with free upgrades (of minor versions).

We’ve got a FREE TRIAL of the professional edition. You don’t need to do anything - just download and install DuoCode and your 30-day trial will begin automatically.
When the trial period is over, you can purchase a license to continue working.

DuoCode Enterprise

This edition is for you if your organization doesn’t fit in the other categories, or if you require a support package.

If you are:
- Working on a commercial project
- Your organization is a governmental organizaion or has more than 8 developers which will be working with DuoCode

Contact us to get details about the Enterprise edition of DuoCode. You’ll get the full unrestricted DuoCode compiler with support package and with free upgrades (including major versions).

Questions?

Contact us and we’d be happy to assist.
We’re looking forward to have you as a customer for DuoCode!

Happy coding!
 -The DuoCode Team

Here's your game changer: DuoCode 1.0 bridges the gap between C# and TypeScript!

This just in: DuoCode 1.0 has been released! And now, with 100% more TypeScript support!

C# <3 TypeScript!

Ever wanted to use .NET types or methods, like StringBuilder or String.Format in your TypeScript code? With DuoCode, now you can!

We are happy to unveil our newest addition to DuoCode - TypeScript definition (.d.ts) generation for C# types, allowing you to create hybrid C#/TypeScript applications in a single project!

Let’s get started!

Create a new TypeScript Application project from a DuoCode template:



This will create a DuoCode-enabled TypeScript application with a twist: alongside the application code (app.ts file) you will find a pure C# class, RomanUtils.cs, containing utility methods to convert a number into its Roman representation:



When you run the sample, you’ll see it in action in a browser window:



How does it work?

When you compile the project, our DuoCode compiler does what it does best - translates the C# code into JavaScript, but now it also emits a matching .d.ts definition for the generated code:

/// <reference path="./mscorlib.d.ts" />

declare module TypeScriptHtmlApp {
    // TypeScriptHtmlApp.RomanUtils
    export interface RomanUtilsTypeFunc extends TypeFunction {
        ConvertNumberToRoman(number: int): string;
        ConvertRomanToNumber(text: string): int;
    }
    var RomanUtils: RomanUtilsTypeFunc;
}

This is the definition generated from the C# code in RomanUtils.cs, and placed next to it in the file TypeScriptHtmlApp.d.ts. Adding the reference to this definition to the main app.ts file allows using it straight away, enjoying full code-completion, syntax highlighting and live error checking support, provided by Visual Studio!

This means you can now write C# in your TypeScript project, recompile it, and immediately use it from TypeScript! In addition, you will enjoy all the goodness already provided by DuoCode, such as debugging the original C# code (via generated source-maps), Base Class Library (BCL) support via mscorlib, and more.

You can control the generation output (ECMAScript 3/5/6, similar to TypeScript) in the project’s Properties dialog, under the DuoCode tab.

Known issues

There are a few issues that currently exist. We plan to address them in the next version release:

  • After creating a project, please rebuild the project once, and reopen the file app.ts to eliminate any editor warnings that might appear.

  • Generated TypeScript definitions currently support public C# types only.

  • Some ReSharper warnings may appear, please ignore those for now (the code compiles fine).

  • Requires TypeScript 1.4 - Visual Studio 2013 users can install an updated version from the Extension Gallery.

DuoCode Release and Trial information

With this version we’re getting ready for an official release very soon. We’ve bumped the version number to 1.0, and when you install the new Visual Studio Extension or an updated NuGet package, DuoCode will begin a 30-day trial. After the trial period is over, you will have to purchase a license to continue using DuoCode.

License and pricing information will be posted within a few days!

Happy coding!
 -The DuoCode Team

Just released: DuoCode 0.6 with Mono 4 and Visual Studio 2015 RC support!

Big news today! We have just released DuoCode 0.6 - with full support for Mono 4, support for Visual Studio 2015 RC and several important bugfixes! Check your Visual Studio Extensions Gallery for updates, or download the new version from our website.

Mono / xbuild support

This is the first release where we officially support Mono 4! We’ve tested our compiler on Mono running on Windows, Linux (Ubuntu) and OSX - all tests pass with flying colors! (actually, just one color: green)



Your DuoCode projects are now truly cross-platform with the support for xbuild (Mono’s MSBuild alternative) - build your projects from the command line on all platforms!

Try DuoCode in your browser!

In addition, we’ve released Try DuoCode - an online playground for trying out DuoCode right in your browser - without downloading anything. You can use it to convert your C# code into JavaScript on the fly, then run and debug in your browser’s developer tools!



Let us know what you think!

Happy coding!
 –The DuoCode Team

DuoCode 0.5 beta is here!

Phew! It’s finally here - a brand new beta release of DuoCode! Here’s what we got for you:

What’s new in 0.5?


Advanced configuration

We’ve added a new DuoCode project property page to further control the compilation process. It is available for all DuoCode projects on Visual Studio 2013 and above.



Debugging

We’ve also made debugging support available on Visual Studio 2013. When using Internet Explorer, you can debug your project straight from the IDE!

In addition, we’ve added support for Chrome (V8) stack-trace API, (via node-source-maps-support) allowing you to get complete C# call stack for exceptions right in the browser:



Publishing

We’ve added support for Web publishing from Visual Studio - Web, FTP, file system and publishing to Azure now work as expected!

Shared projects

DuoCode now supports Shared Projects, a feature that was added in Visual Studio 2013 to assist cross-platform development. You can target several platforms, such as Xamarin and Apache Cordova with a single solution!


Compiler improvements

We’ve made lots of improvements to the DuoCode compiler, with several new features and lots of bugfixes, here are the highlights:

  • Added more binding definitions for Node.js v0.12.2
  • Added support for many more .NET types, such as System.Array, System.Guid, System.IO.Path, as well as improved an optimizied various collection types (List<T>, Array<T>, Dictionary<T,K>)
  • Added support for showing full C# call-stack in Chrome (V8)
  • Improved struct support, including ValueType.Equals() and GetHashCode() generation
  • Improved runtime reflection support (Activator.CreateInstance, MemberInfo.Invoke)
  • Improved ReSharper support in DuoCode projects
  • and many more bugfixes and improvements!

So go ahead, download DuoCode 0.5 beta now!

As always, we’d love to hear your thoughts about DuoCode! Please let us known about any issues you might encounter. You can contact us via support forums or on twitter!

Happy coding!
 –The DuoCode Team

DuoCode 0.4 beta is now available!

We’ve been working tirelessly to bring you the first public beta of DuoCode - our Roslyn-powered C# to JavaScript compiler!

In this release, we've switched from a standalone executable installer to a Visual Studio Extension (VSIX) distribution, which is incompatible with the previous versions of DuoCode. Please remove any previous installation of DuoCode from Programs and Features in Control Panel before installing the DuoCode 0.4 beta.

Getting Started

Head over to the DuoCode website and download the DuoCode Visual Studio extension (you can also install it from the Visual Studio Gallery using Extensions and Updates under the Tools menu in Visual Studio). This will install the necessary project templates for you to get started.

After installing the DuoCode extension, go to File - New Project, under Visual C# you will see the DuoCode entry. You will find the project templates for several kinds of projects: a Class Library, WebGL and Node apps, as well as a Tic-Tac-Toe game and a Ray Tracer demo:

Once a new project is created, simply press F5 to compile and start the project. DuoCode will take care of the rest!

Technicalities

The DuoCode compiler is now distributed as a NuGet package. During the compilation process, the DuoCode compiler (called dcc.exe) is executed by MSBuild. This means that DuoCode is ready to be included in your project, and is build-server friendly!

The result of the compilation is a scripts directory, containing the resulting .js file for the assembly, as well as mscorlib.js, which is the DuoCode implementation of the core libraries. In addition, DuoCode generates source map files, allowing you to debug your C# code right inside the browser!

Questions? Issues? Let us know!

This is a beta, and there might be things that don’t work correctly. Please let us know about them, so we can fix them!

Don’t hesitate to contact us about any questions you might have, or issues you may encounter at our support website, or by email to support@duoco.de.

Don’t forget to download DuoCode 0.4 beta!

Happy coding!
 -The DuoCode Team

Hello DuoCode - translating C# to JavaScript!

Once upon a time there was created a wonderful, general purpose programming language called C#. Many developers around the world embraced C#, and began writing all of their applications in C#, which ran on the user’s personal computers, and everyone was happy. Over the years, however, the landscape shifted - everything became more mobile, and there came a need to run some of those projects on the web. As it happened, the language of the web is JavaScript, and while it is ideal for writing applications that run in the browser, it’s not always possible (or viable) to rewrite significant parts of core business logic in JavaScript. There have been many attempts over the years to create languages that translate to JavaScript (TypeScript, CoffeeScript, to name a few), but none really provide the raw power and tooling, available to C# developers. Until now!

Enter DuoCode.

With DuoCode, our goal from the start was to create the best and most complete C# to JavaScript compiler, using the best technology available to date: the .NET Compiler Platform, formerly known as Microsoft “Roslyn”. Roslyn allows us to fully “understand” C# and all of its features (including the new C# 6 language features), and accurately convert them to corresponding JavaScript. With DuoCode, you use things like Generics, Reflection, LINQ and dynamic, while still enjoying full Visual Studio support for IntelliSense, syntax highlighting, and even debugging your original C# code in your browser!

Let’s start with our *Hello World” example. Given the following C# code:

// Original C# code
using System;
using DuoCode.Dom;
using static DuoCode.Dom.Global; // C# 6.0 'using static' syntax

namespace HelloDuoCode
{
  static class Program
  {
    public class Greeter
    {
      private readonly HTMLElement element;
      private readonly HTMLElement span;
      private int timerToken;

      public Greeter(HTMLElement el)
      {
        element = el;
        span = document.createElement("span");
        element.appendChild(span);
        Tick();
      }

      public void Start()
      {
        timerToken = window.setInterval((Action)Tick, 500);
      }

      public void Stop()
      {
        window.clearTimeout(timerToken);
      }

      private void Tick()
      {
        span.innerHTML = string.Format("The time is: {0}", DateTime.Now);
      }
    }

    static void Run()
    {
      System.Console.WriteLine("Hello DuoCode");

      var el = document.getElementById("content");
      var greeter = new Greeter(el);
      greeter.Start();
    }
  }
}

Compiling the above code will produce the following JavaScript:

// JavaScript code generated by DuoCode
var HelloDuoCode = this.HelloDuoCode || {};
var $d = DuoCode.Runtime;
HelloDuoCode.Program = $d.declare("HelloDuoCode.Program", System.Object, 0, $asm, function($t, $p) {
    $t.Run = function Program_Run() {
        System.Console.WriteLine$10("Hello DuoCode");

        var el = document.getElementById("content");
        var greeter = new HelloDuoCode.Program.Greeter.ctor(el);
        greeter.Start();
    };
});
HelloDuoCode.Program.Greeter = $d.declare("Greeter", System.Object, 0, HelloDuoCode.Program, function($t, $p) {
    $t.$ator = function() {
        this.element = null;
        this.span = null;
        this.timerToken = 0;
    };
    $t.ctor = function Greeter(el) {
        $t.$baseType.ctor.call(this);
        this.element = el;
        this.span = document.createElement("span");
        this.element.appendChild(this.span);
        this.Tick();
    };
    $t.ctor.prototype = $p;
    $p.Start = function Greeter_Start() {
        this.timerToken = window.setInterval($d.delegate(this.Tick, this), 500);
    };
    $p.Stop = function Greeter_Stop() {
        window.clearTimeout(this.timerToken);
    };
    $p.Tick = function Greeter_Tick() {
        this.span.innerHTML = String.Format("The time is: {0}", $d.array(System.Object, [System.DateTime().get_Now()]));
    };
});

And we’ll get something that looks like this:

This example shows several key features of DuoCode:

  • The new C# 6 using static syntax is supported
  • Original C# code will be visible/debuggable in the developer tools (after enabling source-maps integration)
  • Can work with DOM elements
  • Functioning timer

But this is just the beginning! Let’s dig deeper!

Tic-Tac-Toe

Included in the project templates is a small tic-tac-toe game, written entirely in C#!

The game code uses language features such as enums and indexers:

public enum Player
{
    None = 0,
    X = 1,
    O = -1
}

public sealed class Board
{
    public static Player Other(Player player)
    {
        return (Player)(-(int)player);
    }

    private readonly Player[] Squares;

    public readonly int Count;

    public Player this[int position]
    {
        get
        {
            return Squares[position];
        }
    }

    public Board() // empty board
    {
        Squares = new Player[9];
    }

    private Board(Board board, Player player, int position) :
      this()
    {
        Array.Copy(board.Squares, Squares, 9);
        Squares[position] = player;

        Count = board.Count + 1;
    }

    public bool Full { get { return Count == 9; } }

    public Board Move(Player player, int position)
    {
        if (position < 0 ||
            position >= 9 ||
            Squares[position] != Player.None)
        {
            throw new Exception("Illegal move");
        }

        return new Board(this, player, position);
    }

    public Player GetWinner()
    {
        if (Count < 5)
            return Player.None;

        Player result;
        bool winning =
          IsWinning(0, 1, 2, out result) ||
          IsWinning(3, 4, 5, out result) ||
          IsWinning(6, 7, 8, out result) ||
          IsWinning(0, 3, 6, out result) ||
          IsWinning(1, 4, 7, out result) ||
          IsWinning(2, 5, 8, out result) ||
          IsWinning(0, 4, 8, out result) ||
          IsWinning(2, 4, 6, out result);

        return result;
    }

    private bool IsWinning(int p0, int p1, int p2, out Player player)
    {
        int count = (int)Squares[p0] + (int)Squares[p1] + (int)Squares[p2];
        player = count == 3 ? Player.X : count == -3 ? Player.O : Player.None;
        return player != Player.None;
    }
}

And we’re rendering DOM elements from the program’s Main() method:

public static void Main(string[] args)
{
  for (var i = 0; i < 9; i++)
  {
    Dom.HTMLInputElement checkbox = GetCheckbox(i);
    checkbox.checked_ = false;
    checkbox.indeterminate = true;
    checkbox.disabled = false;
    checkbox.onclick = OnClick;
  }

  if (new Random().Next(2) == 0)
    ComputerPlay();

  UpdateStatus();
}

private static dynamic OnClick(Dom.MouseEvent e)
{
  int position = int.Parse(((Dom.HTMLInputElement)e.target).id[1].ToString());

  try
  {
    board = board.Move(Player.X, position);
  }
  catch
  {
    Dom.Global.window.alert("Illegal move");
    return null;
  }

  Dom.HTMLInputElement checkbox = GetCheckbox(position);
  checkbox.disabled = true;
  checkbox.checked_ = true;

  if (!board.Full)
    ComputerPlay();

  UpdateStatus();

  return null;
}

private static Dom.HTMLInputElement GetCheckbox(int index)
{
  string name = "a" + index.ToString();
  Dom.HTMLInputElement checkbox = Dom.Global.document.getElementById(name).As<Dom.HTMLInputElement>();
  return checkbox;
}

WebGL

Want to write WebGL apps? No problem! Let’s take the following C# code:

using DuoCode.Dom;
using System;

namespace WebGL
{
  using GL = WebGLRenderingContext;

  internal static class Utils
  {
    public static WebGLRenderingContext CreateWebGL(HTMLCanvasElement canvas)
    {
      WebGLRenderingContext result = null;
      string[] names = { "webgl", "experimental-webgl", "webkit-3d", "moz-webgl" };
      foreach (string name in names)
      {
        try
        {
          result = canvas.getContext(name);
        }
        catch { }
        if (result != null)
          break;
      }
      return result;
    }

    public static WebGLShader CreateShaderFromScriptElement(WebGLRenderingContext gl, string scriptId)
    {
      var shaderScript = (HTMLScriptElement)Global.document.getElementById(scriptId);

      if (shaderScript == null)
        throw new Exception("unknown script element " + scriptId);

      string shaderSource = shaderScript.text;

      // Now figure out what type of shader script we have, based on its MIME type
      int shaderType = (shaderScript.type == "x-shader/x-fragment") ? GL.FRAGMENT_SHADER :
                       (shaderScript.type == "x-shader/x-vertex")   ? GL.VERTEX_SHADER   : 0;
      if (shaderType == 0)
        throw new Exception("unknown shader type");

      WebGLShader shader = gl.createShader(shaderType);
      gl.shaderSource(shader, shaderSource);

      // Compile the shader program
      gl.compileShader(shader);

      // See if it compiled successfully
      if (!gl.getShaderParameter(shader, GL.COMPILE_STATUS))
      {
        // Something went wrong during compilation; get the error
        var errorInfo = gl.getShaderInfoLog(shader);
        gl.deleteShader(shader);
        throw new Exception("error compiling shader '" + shader + "': " + errorInfo);
      }
      return shader;
    }

    public static WebGLProgram CreateShaderProgram(WebGLRenderingContext gl, WebGLShader fragmentShader, WebGLShader vertexShader)
    {
      var shaderProgram = gl.createProgram();
      gl.attachShader(shaderProgram, vertexShader);
      gl.attachShader(shaderProgram, fragmentShader);
      gl.linkProgram(shaderProgram);

      bool linkStatus = gl.getProgramParameter(shaderProgram, GL.LINK_STATUS);
      if (!linkStatus)
        throw new Exception("failed to link shader");
      return shaderProgram;
    }

    public static WebGLTexture LoadTexture(WebGLRenderingContext gl, string resourceName)
    {
      var result = gl.createTexture();
      var imageElement = Properties.Resources.duocode.Image;
      imageElement.onload = new Func<Event, dynamic>((e) =>
      {
        UploadTexture(gl, result, imageElement);
        return true;
      });

      return result;
    }

    public static void UploadTexture(WebGLRenderingContext gl, WebGLTexture texture, HTMLImageElement imageElement)
    {
      gl.pixelStorei(GL.UNPACK_FLIP_Y_WEBGL, GL.ONE);
      gl.bindTexture(GL.TEXTURE_2D, texture);
      gl.texImage2D(GL.TEXTURE_2D, 0, GL.RGBA, GL.RGBA, GL.UNSIGNED_BYTE, imageElement);
      gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR);
      gl.texParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR_MIPMAP_NEAREST);
      gl.generateMipmap(GL.TEXTURE_2D);
      gl.bindTexture(GL.TEXTURE_2D, null);
    }

    public static float DegToRad(float degrees)
    {
      return (float)(degrees * System.Math.PI / 180);
    }
  }
}

Apply DuoCode magic to it, and you’ll get a WebGL app that runs in your browser!

Debugging

The best part of compiling with DuoCode is the ability to debug your code straight from the browser! We will automatically generate source maps, which allow mapping between the original C# code and the generated JavaScript, allowing you to set breakpoints, inspect variables and step through your code without leaving your browser’s development tools:

Debugging is currently supported only in Visual Studio 2015, using IE, Chrome and Firefox.

Few more examples

Here are a few more examples of DuoCode’s abilities:

Structs

C#:

public struct Point
{
    public readonly static Point Zero = new Point(0, 0);

    public readonly int X;
    public readonly int Y;

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

JavaScript:

HelloDuoCode.Program.Point = $d.declare("Point", null, 62, HelloDuoCode.Program, function($t, $p) {
    $t.cctor = function() {
        $t.Zero = new HelloDuoCode.Program.Point.ctor$1(0, 0);
    };
    $t.ctor = function Point() {
        this.X = 0;
        this.Y = 0;
    };
    $t.ctor.prototype = $p;
    $t.ctor$1 = function Point(x, y) {
        this.X = x;
        this.Y = y;
    };
    $t.ctor$1.prototype = $p;
});

Note: only immutable structs are currently supported.

LINQ

C#:

public static IEnumerable<int> Foo()
{
    return Enumerable.Range(0, 10).Where(x => x % 2 == 0).Select(x => x * 3);
}

JavaScript:

$t.Foo = function Program_Foo() {
    return System.Linq.Enumerable.Select(System.Int32, System.Int32, System.Linq.Enumerable.Where(System.Int32,
        System.Linq.Enumerable.Range(0, 10), $d.delegate(function(x) {
            return x % 2 == 0;
        }, this)), $d.delegate(function(x) {
        return x * 3;
    }, this));
};

Miscellaneous

Generics, params arrays, nullable, method overloading, default values, all supported in DuoCode:

C#:

public class Foo<T> where T : IComparable<T>
{
    public void Bar(int? x, T y, string z = "value")
    {
        System.Console.WriteLine((x ?? -1) + y.ToString() + z);
    }
    public void Bar(string z, params object[] args)
    {
    }
}
// Main
new Foo<int>().Bar(null, 2);

JavaScript:

HelloDuoCode.Program.Foo$1 = $d.declare("Foo`1", System.Object, 256, HelloDuoCode.Program, function($t, $p, T) {
    $t.ctor = function Foo$1() {
        $t.$baseType.ctor.call(this);
    };
    $t.ctor.prototype = $p;
    $p.Bar$1 = function Foo$1_Bar(x, y, z) {
        System.Console.WriteLine$10($d.toString(($d.ncl(x, -1))) + y.ToString() + z);
    };
    $p.Bar = function Foo$1_Bar(z, args) {};
}, [$d.declareTP("T")]);
// Main
new (HelloDuoCode.Program.Foo$1(System.Int32).ctor)().Bar$1(null, 2, "value");

… and we’re just getting started!

Final words

DuoCode is currently in a closed beta. If you want to play with DuoCode, please sign up for an invite on our site. We’re looking forward to release a public beta version very soon!

Please let us know of any issues you might have, as well as suggestions on what you’d like to see in DuoCode! Believe us, wonderful things are coming!

Until then,

Happy coding!
– The DuoCode Team!


This post was adapted, with permission, from an original article in Russian by Andrey Akinshin. The original article is posted here: http://habrahabr.ru/company/enterra/blog/252079/


Contact Us

We’d love to hear from you