Have you ever had an enum in your server code that you wanted to access in client side code? Or wanted the safety of compile time errors when there are discrepancies between your server-side and client-side code? Or had a C# Data Transfer Object (DTO) that you wanted to enable Intellisense for in JavaScript? I hadn't found a good solution either ... until now.
Compiling C# to What!?
Compiling C# code into JavaScript may seem foreign, but Script# is a mature technology that is absolutely worth a look. Our team has been using it very happily for about three months. We've found a number of benefits including:
To the Command Line
Typically to get going with Script# you:
How-To
The how-to looks something like this:
Now for completeness if you put a simple static method in Class1.cs, something like this:
namespace MyScriptSharp
{
publicclassClass1
{
publicstaticstring HelloWorld()
{
return"Hello World!";
}
}
}
Then run the batch file you should get something like this:
Type.registerNamespace('MyScriptSharp');
////////////////////////////////////////////////////////////////////////////////
// MyScriptSharp.Class1
MyScriptSharp.Class1 = function MyScriptSharp_Class1() {
}
MyScriptSharp.Class1.helloWorld = function MyScriptSharp_Class1$helloWorld() {
return'Hello World!';
}
MyScriptSharp.Class1.registerClass('MyScriptSharp.Class1');
Obviously you could get these results faster with approach #1. But now you have a lot more control.
Summary
The main downside to this approach is maintaining the batch file is a bit of a hassle. But the upsides are that you can include any file from your server-side C# code. And any changes in that server-side code are automatically reflected in your JavaScript. And any breaking changes in your server-side code generate compile time errors in your client side code. And furthermore none of your team members need to install Script#. For our team it's an easy tradeoff. What about for yours? Please share your thoughts in the comments or on twitter.
Compiling C# to What!?
Compiling C# code into JavaScript may seem foreign, but Script# is a mature technology that is absolutely worth a look. Our team has been using it very happily for about three months. We've found a number of benefits including:
- Consistently working Intellisense
- Better encapsulation
- Simpler Object Orientation
- Easier deployment (Script# compiles multiple files to a single, optionally minified file)
- Safer refactoring
- Simpler unit testing
- Type safety; and
- Design time syntax checking (no more mistyping a variable and accidentally declaring it to the global scope)
To the Command Line
Typically to get going with Script# you:
- Install the Script# Visual Studio plug-in
- File -> New project
- Select "Script Library" and
- Compile to generate JavaScript
How-To
The how-to looks something like this:
- Download and install Script#
- Add a Class Library (not a Script# project)
- Project properties -> Build -> Advanced -> "Do not reference mscorlib"
- Ideally move the Script# files (C:\Program Files (x86)\ScriptSharp) locally to the solution and check them into source control to a Libs or something similar
- Remove all references, but add: ScriptSharp.dll, ScriptSharp.Web.dll, Script.Jquery
- Edit your .csproj to manually reference Script#'s mscorlib (right click, Unload project, Edit MyProject.csproj)
<ReferenceInclude="mscorlib, Version=0.7.0.0, Culture=neutral, PublicKeyToken=8fc0e3af5abcb6c4, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
<HintPath>..\Libs\ScriptSharp\v1.0\mscorlib.dll</HintPath>
</Reference> - Modify AssemblyInfo.cs and remove the following lines:
[assembly: ComVisible(false)]
[assembly: Guid("b5e2449f-193c-46d1-9023-9143618d8491")] - Modify AssemblyInfo.cs and add the following:
[assembly: ScriptAssembly("ScriptSharpDemoAssembly")] - Ensure it compiles in Visual Studio
- Create a batch script or PowerShell script that compiles using ssc.exe like this:
..\Libs\ScriptSharp\v1.0\ssc.exe ^
/debug ^
/out:MyScriptSharp.js ^
/ref:"..\Libs\ScriptSharp\v1.0\Framework\mscorlib.dll" ^
.\Properties\AssemblyInfo.cs ^
.\Class1.cs
Now for completeness if you put a simple static method in Class1.cs, something like this:
namespace MyScriptSharp
{
publicclassClass1
{
publicstaticstring HelloWorld()
{
return"Hello World!";
}
}
}
Then run the batch file you should get something like this:
Type.registerNamespace('MyScriptSharp');
////////////////////////////////////////////////////////////////////////////////
// MyScriptSharp.Class1
MyScriptSharp.Class1 = function MyScriptSharp_Class1() {
}
MyScriptSharp.Class1.helloWorld = function MyScriptSharp_Class1$helloWorld() {
return'Hello World!';
}
MyScriptSharp.Class1.registerClass('MyScriptSharp.Class1');
Obviously you could get these results faster with approach #1. But now you have a lot more control.
Summary
The main downside to this approach is maintaining the batch file is a bit of a hassle. But the upsides are that you can include any file from your server-side C# code. And any changes in that server-side code are automatically reflected in your JavaScript. And any breaking changes in your server-side code generate compile time errors in your client side code. And furthermore none of your team members need to install Script#. For our team it's an easy tradeoff. What about for yours? Please share your thoughts in the comments or on twitter.