5,276,406 members and growing! (17,084 online)
Email Password   helpLost your password?
General Programming » Programming Tips » General     Intermediate License: The Code Project Open License (CPOL)

Object oriented JavaScript class library in C#/.NET style

By EJocys

JavaScript classes ported from .NET
HTML, Javascript, CSS, .NET (.NET, .NET 1.0, .NET 1.1, .NET 2.0, Mono, DotGNU, .NET 3.0, .NET 3.5), ASP, ASP.NET, Ajax

Posted: 12 Dec 2007
Updated: 14 Mar 2008
Views: 31,661
Announcements
Want a new Job?



Search    
Advanced Search
Sitemap
47 votes for this Article.
Popularity: 7.84 Rating: 4.69 out of 5
2 votes, 4.3%
1
1 vote, 2.1%
2
0 votes, 0.0%
3
1 vote, 2.1%
4
43 votes, 91.5%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

Welcome to Object Oriented JavaScript class library in C#/.NET style.

Background

I like coding with JavaScript in object oriented style. But one day I've decided to bring my code into another level and make my JavaScript code to look like C# as much as possible. So I've:

  1. Started to use .NET coding standards on my JavaScripts. You can find them here:
    MSDN - ".NET Framework General Reference: Naming Guidelines".
    http://msdn.microsoft.com/library/en-us/cpgenref/html/cpconnamingguidelines.asp
  2. Ported some basic useful classes and methods from .NET to JavaScript with same class and property names. Some code parts were written from scratch, some parts were borrowed from internet and some parts were ported from C# directly.
  3. I've started to use XML Comments inside JavaScript. They are not supported by VisualStudio 2008 very well but I hope support will be better in future.

NOTE: This library is not finished yet, contains experimental code parts and was posted here for educational purposes only but you can make clear picture where it goes. You can browse through these JavaScript classes and methods here: http://www.jocys.com/Scripts/Classes/Documents/.

Screenshot - JocysComClassBrowser.jpg

Example: HMAC-MD5 checksum

C# code to create HMAC-MD5 checksum:

// Create HMAC-MD5 Algorithm;
System.Security.Cryptography.HMACMD5 hmac = new System.Security.Cryptography.HMACMD5();  
// Convert string to array of bytes.
byte[] key = System.Text.Encoding.UTF8.GetBytes("test key");  
byte[] data = System.Text.Encoding.UTF8.GetBytes("test data");  
// Compute hash.  
byte hashBytes = hmac.ComputeHash(key, data);
// Convert to HEX string.
string hex = System.BitConverter.ToString(hashBytes);
// Convert to GUID so you can store it inside database.
Guid guid = new System.Guid(hashBytes);

Same HMAC-MD5 checksum code written with this JavaScript library:

Include JavaScripts:

  • System.js
  • System.BitConverter.js
  • System.Text.js
  • System.Security.Cryptography.MD5.js
  • System.Security.Cryptography.HMACMD5.js
// Create HMAC-MD5 Algorithm;
var hmac = new System.Security.Cryptography.HMACMD5();  
// Convert string to array of bytes.
var key = System.Text.Encoding.UTF8.GetBytes("test key");  
var data = System.Text.Encoding.UTF8.GetBytes("test data");  
// Compute hash.  
var hashBytes = hmac.ComputeHash(key, data);
// Convert to HEX string.
var hex = System.BitConverter.ToString(hashBytes);
// Convert to GUID so you can store it inside database.
var guid = new System.Guid(hashBytes);
As you can see everything looks prety same.

Example: AES-256 encryption

C# code for AES-256 encryption:

// Turn input string into a byte array.
byte[] input = System.Text.Encoding.Unicode.GetBytes("Plain Text");
// Create an instance of the Rijndael class.
System.Security.Cryptography.RijndaelManaged cipher;
cipher = new System.Security.Cryptography.RijndaelManaged();
// Calculate salt to make it harder to guess key by using a dictionary attack.
byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes("password");
System.Security.Cryptography.HMACSHA1 hmac;
hmac = new System.Security.Cryptography.HMACSHA1(passwordBytes);
byte[] salt = hmac.ComputeHash(passwordBytes);
// Generate Secret Key from the password and salt.
// Note: Set number of iterations to 10 in order for JavaScript example to work faster.
System.Security.Cryptography.Rfc2898DeriveBytes secretKey;
secretKey = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt, 10);
// Create a encryptor from the existing SecretKey bytes by using
// 32 bytes (256 bits) for the secret key and
// 16 bytes (128 bits) for the initialization vector (IV).
byte[] key = secretKey.GetBytes(32);
byte[] iv = secretKey.GetBytes(16);
System.Security.Cryptography.ICryptoTransform cryptor;
cryptor = cipher.CreateEncryptor(key, iv);
// Create new Input.
byte[] inputBuffer = new byte[input.Length];
// Copy data bytes to input buffer.
System.Buffer.BlockCopy(input, 0, inputBuffer, 0, inputBuffer.Length);
// Create a MemoryStream to hold the output bytes.
System.IO.MemoryStream stream = new System.IO.MemoryStream();
// Create a CryptoStream through which we are going to be processing our data.
System.Security.Cryptography.CryptoStreamMode mode;
mode = System.Security.Cryptography.CryptoStreamMode.Write;
System.Security.Cryptography.CryptoStream cryptoStream;
cryptoStream = new System.Security.Cryptography.CryptoStream(stream, cryptor, mode);
// Start the crypting process.
cryptoStream.Write(inputBuffer, 0, inputBuffer.Length);
// Finish crypting.
cryptoStream.FlushFinalBlock();
// Convert data from a memoryStream into a byte array.
byte[] outputBuffer = stream.ToArray();
// Close both streams.
stream.Close();
cryptoStream.Close();
// Convert encrypted data into a base64-encoded string.
string base64String = System.Convert.ToBase64String(outputBuffer);
// base64String = laFf3eKu9tzB2XksJjd8EVM3PA9O30wz0Y+X3nyelW4=

Same AES-256 encryption code written with this JavaScript library:

Include JavaScripts:

  • System.js
  • System.IO.js
  • System.Text.js
  • System.Convert.js
  • System.BitConverter.js
  • System.Security.Cryptography.js
  • System.Security.Cryptography.SHA1.js
  • System.Security.Cryptography.HMACSHA1.js
  • System.Security.Cryptography.RijndaelManaged.js
// Turn input string into a byte array.
var input = System.Text.Encoding.Unicode.GetBytes("Plain Text");
// Create an instance of the Rijndael class.
var cipher = new System.Security.Cryptography.RijndaelManaged();
// Calculate salt to make it harder to guess key by using a dictionary attack.
var passwordBytes = System.Text.Encoding.UTF8.GetBytes("password");
var hmac = new System.Security.Cryptography.HMACSHA1(passwordBytes);
var salt = hmac.ComputeHash(passwordBytes);
// Generate Secret Key from the password and salt.
// Note: Set number of iterations to 10 in order for JavaScript example to work faster.
var secretKey = new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt, 10);
// Create a encryptor from the existing SecretKey bytes by using
// 32 bytes (256 bits) for the secret key and
// 16 bytes (128 bits) for the initialization vector (IV).
var key = secretKey.GetBytes(32);
var iv = secretKey.GetBytes(16);
var cryptor = cipher.CreateEncryptor(key, iv);
// Create new Input.
var inputBuffer = new System.Byte(input.length);
// Copy data bytes to input buffer.
System.Buffer.BlockCopy(input, 0, inputBuffer, 0, inputBuffer.length);
// Create a MemoryStream to hold the output bytes.
var stream = new System.IO.MemoryStream();
// Create a CryptoStream through which we are going to be processing our data.
var mode = System.Security.Cryptography.CryptoStreamMode.Write;
var cryptoStream = new System.Security.Cryptography.CryptoStream(stream, cryptor, mode);
// Start the crypting process.
cryptoStream.Write(inputBuffer, 0, inputBuffer.length);
// Finish crypting.
cryptoStream.FlushFinalBlock();
// Convert data from a memoryStream into a byte array.
var outputBuffer = stream.ToArray();
// Close both streams.
stream.Close();
cryptoStream.Close();
// Convert encrypted data into a base64-encoded string.
var base64String = System.Convert.ToBase64String(outputBuffer);
// base64String = laFf3eKu9tzB2XksJjd8EVM3PA9O30wz0Y+X3nyelW4=

Example: User Interface

function firstButton_Click(){
    Trace.Write("First Button Click");
}

function secondButton_Click(){
    Trace.Write("Second Button Click");
}

function Window_Load(){
    Trace.IsEnabled = true;
    Trace.Write("Start Demo");
    // Create toolbar.
    var toolBar = new System.Web.UI.Interface.ToolBar("MyToolBar");
    // Add toolbar to document.
    document.body.appendChild(toolBar.Node);
    // Create Bar.
    var bar = new System.Web.UI.Interface.Bar("MainBar", document, "Bar Title");
    toolBar.Add(bar);
    // Create first button.
    var firstButton = new System.Web.UI.Interface.Button("FirstButton", document);
    firstButton.SetText("First");
    firstButton.SetImage("Images/Icons/Options-16x16.png");
    firstButton.SetTitle("First Button");
    firstButton.customAction = firstButton_Click;
    bar.Add(firstButton);    
    // Create second button.
    var secondButton = new System.Web.UI.Interface.Button("SecondButton", document);
    secondButton.SetText("Second");
    secondButton.SetImage("Images/Icons/Trace.16x16.png");
    secondButton.SetTitle("Second Button");
    secondButton.customAction = secondButton_Click;
    bar.Add(secondButton);    
}

window.onload = Window_Load;

Will produce this interface on the web page:

JocysComJavaScriptClassesToolBar.png

Benefits

Coding with JavaScript in C# .NET style provides these benefits:

  1. Any C# developer instantly understands purpose of JavaScript code.
  2. You don't need to write help for your new JavaScript classes because Microsoft did it already.
  3. When porting new class from C# to JavaScript you don't need to think how to name it or where to put it. All you need is to look for same class in C# and use same naming.
  4. More JavaScript Classes you have easier it will be to port new ones.
  5. By using C# classes as primary reference it will be much easier for different developers to write and integrate JavaScript classes into one big file library. It is because by looking at some C# class developer knows what type of input and output function must support/produce and he doesn't need to coordinate this with other developers.
  6. And many more...

Requirements

JavaScript have very limited number of types:

JavaScript Object typeof(Object)
Object 'object'
Array 'object'
Function 'function'
String 'string'
Number 'number'
Boolean 'boolean'
null 'object'
undefined 'undefined'

But by combining existing types we can create JavaScript objects similar to C#. For example:

C# Type JavaScript Type
public property declared with "this." prefix: this.Name = new String;
private property declared with "var" prefix: var name = new String;
class this.ClassName = function(){... without "return value;" at the end
void function which has no "return value;" at the end
short/Int16 whole Number from [-2^15, 2^15-1] range.
int/Int32 whole Number from [-2^31, 2^31-1] range.
long/Int64 whole Number from [-2^63, 2^63-1] range (Requires BigInteger class).
byte whole Number from [0, 255] range: var b = 14;
sbyte whole Number from [-128, 127] range: var sb = -14;
bytes[] Array() filed with integers from [0-255] range.
bit Number: 0 or 1
bit[] Array() filed with integers from [0-1] range.
char String which contains single character. Declared with single quotes: var c = 's'
char[] Array() filed single characters: var chars = new Array(1); chars[0] = 's';
object parameter which was declared with "{ }": var o = {};
enum Object with "Enum" sufix and coma separated values: this.TriStateEnum = { Unknown: -2, False: 0, True: 1 }
EventHandler function with parameters "sender" and "e": function(sender, e) or this.Click(sender, e)

NUMBERS: All numbers in JavaScript are 64-bit (8 bytes) floating point numbers (double: 1-bit sign, 11-bits exponent, 52-bits mantissa). There is no Double, Single/Float, Boolean, Int16, UInt16, Int32 or UInt32. But you can use public static methods of System.BitConverter JavaScript class in order to treat same JavaScript number as different type:

// Convert number to [0x00, 0x00, 0xCC, 0xCC] array.
var bytes = System.BitConverter.GetBytes(-859045888, System.TypeCode.Int32);
// Convert bytes back to -859045888.
var n = System.BitConverter.ToInt32(bytes, 0);  
System.BitConverter JavaScript class supports little-endian (default), big-endian byte orders and numeric arrays. System.BitConverter class is very useful in encoding/decoding/encryption/decryption classes. Please note that you need to specify number type when using GetBytes(value, typeCode) method by using System.TypeCode enumeration values (this enumeration is located inside System.js file).

NOTE: You can use <param type="byte[]" name="data">...</param> inside JavaScript XML Comments in order to specify type of input data and <returns type="double">...</returns> - for output.

Files from this JavaScript library can be included on client and server side thanks to special header and footer:

<!--//--><%
//=============================================================================
// Jocys.com JavaScript.NET Classes (In C# Object Oriented Style)
// Created by Evaldas Jocys <evaldas@jocys.com>
//-----------------------------------------------------------------------------
// You can include this script on both sides - server and client:
// Server: <!-- #INCLUDE FILE="ScriptFile.js" -->
// Client: <script type="text/javascript" src="ScriptFile.js"></script>
//=============================================================================
        
JavaScript Code Here...

//==============================================================================
// END
//------------------------------------------------------------------------------
//%>

... and by avoiding Response.Write() or alert() use directly: for example: I can detect if script is running on server side or client side and show message accordingly with this code:

this.IsServerSide = (typeof(Response) == "object");
// If we are on server side then...
if (this.IsServerSide){
    // Write text to output.
    Response.Write(text);
}else{
    // Show popup message.
    alert(text);
}

JavaScript IntelliSense

Visual Studio 2008 have built-in support for JavaScript IntelliSense. This means that if you open System.BitConverter.js file, place cursor at the end of file and type "System.BitConverter." then straight after dot VS 2008 will bring menu containing all available methods and properties of System.BitConverter class:

JocysComJavaScriptIntelliSense.gif

Good news here that Microsoft is moving into right direction. Bad news that JavaScript IntelliSense works only with specific JavaScript coding style and sometimes needs workarounds. In other words it works in mysterious ways or doesn't work at all :). Some extra upgrades are needed on my code I guess.

Installation

Extract source archive into webroot (/) folder of your website.

Example: System.Security.Password

Inside source code you can find examples (/Scripts/Classes/Examples/) including password generator example. You can run it:

Screenshot - SystemSecurityPasswordGeneratorGui.gif

To make a suggestion or report bugs please write to: evaldas@jocys.com

History

  • 2007-12-12 - Created. Some links inside examples were fixed. New source code was uploaded. Alex's Code Syntax Highlighter was updated to 1.5.1 version.
  • 2007-12-15 - New 'System.IO.MemoryStream' class. I will use it later with symmetric encryption algorithms so encryption can be done between two web browser clients without any ActiveX.
    Now you can get byte[] arrays filled with 0 numbers in JavaScript easier:
    var bytes = new System.Byte(10);
    Its same as 'byte[] bytes = new System.Byte[10];' or 'byte[] bytes = new byte[10];' in C#. You can define multi-dimensional arrays filled with zeroes too:
    var bytes = new System.Byte(16,16); bytes[4][5] = 10;
  • 2008-01-13 - Some bugs were fixed and new JavaScript classes were added:
    System.Security.Cryptography.js file:
    - System.Security.Cryptography.Rfc2898DeriveBytes
    - System.Security.Cryptography.ICryptoTransform
    - System.Security.Cryptography.RNGCryptoServiceProvider
    - System.Security.Cryptography.CryptoStream
    System.Security.Cryptography.RijndaelManaged.js file (AES encryption):
    - System.Security.Cryptography.RijndaelManaged
    System.js file (new methods):
    - System.Buffer.BlockCopy
    - System.Array.Reverse
    - System.Array.Clear
    - System.Array.GetMultiDimensional
    - System.Array.FillMultiDimensional
    Examples Created (Scripts/Classes/Examples folder):
    - System.Security.Cryptography.AES.htm
    - System.Security.Cryptography.AES.aspx
    - System.Security.Cryptography.htm
    - System.Security.Cryptography.aspx
    Some interface parts/classes/examples were updated to Office 2007 style:
    - System.Web.UI.Interface.ToolBar.htm
    - System.Web.UI.Interface.TabStrip.htm
    Methods System.BitConverter static class was updated.
  • 2008-01-27 - new Enumerations:
    - System.TypeCode
    New Classes:
    - System.Collections.BitArray
    System.BitConverter (System.BitConverter.js) class was updated with methods:
    - System.BitConverter.GetByte(value, typeCode) - get bytes from Double, Single, Boolean, Int16, UInt16, Int32, UInt32. You need to use values of System.TypeCode to specify how JavaScript must treat number.
    You also can convert byte[] back to numbers by using methods:
    - System.BitConverter.ToDouble(bytes, startIndex)
    - System.BitConverter.ToSingle(bytes, startIndex)
    - System.BitConverter.ToBoolean(bytes, startIndex)
    - System.BitConverter.ToInt16(bytes, startIndex)
    - System.BitConverter.ToUInt16(bytes, startIndex)
    - System.BitConverter.ToInt32(bytes, startIndex)
    - System.BitConverter.ToUInt32(bytes, startIndex)
    Int64 and UInt64 types are not available yet because JavaScript 64-bit (8 bytes) float point number have only 52-bit mantissa which means that it is not possible to work with 64-bit whole numbers properly. I need to finish/port System.Numeric.BigInteger (java.math.BigInteger) class in order to enable 64-bit integers and numbers with unlimited bits.
    Updated Examples:
    - System.BitConverter.htm
    - System.BitConverter.aspx
  • 2008-03-14 - Some bug fixes:
    New Classes:
    - System.Web.UI.HtmlControls.TextBox.CommandLine - Convert input to command line. Will be used later to create plain JavaScript console and in chat applications.
    Examples Updated (Scripts/Classes/Examples folder):
    - System.Web.UI.HtmlControls.TextBox.CommandLine.htm
    - System.Web.UI.ShortKeys/System.Web.UI.ShortKeys.htm - Shows how to override and use custom windows keyboard layout on the web page. Also can capture keys and perform non-default custom actions.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

EJocys



Occupation: Web Developer
Location: United Kingdom United Kingdom

Other popular Programming Tips articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Search Search Messages 
 Layout  Per page   
 Msgs 1 to 15 of 15 (Total in Forum: 15) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralCan I use it with Visual Studio.net 2003?memberRandomYang18:29 29 Jan '08  
AnswerRe: Can I use it with Visual Studio.net 2003? [modified]memberEJocys1:05 30 Jan '08  
GeneralRe: Can I use it with Visual Studio.net 2003?memberRandomYang15:26 31 Jan '08  
GeneralReally awesome! But what about the other approach?memberhartertobak22:38 13 Dec '07  
GeneralRe: Really awesome! But what about the other approach?memberDewey23:08 14 Dec '07  
GeneralRe: Really awesome! But what about the other approach?memberhartertobak5:49 20 Dec '07  
GeneralRe: Really awesome! But what about the other approach?memberBen Daniel17:35 19 Dec '07  
GeneralWhere's the solutionmemberDewey14:19 13 Dec '07  
AnswerRe: Where's the solutionmemberEJocys23:48 13 Dec '07  
GeneralTop workmemberBen Daniel16:05 12 Dec '07  
GeneralRe: Top workmemberThomas Lykke Petersen21:24 13 Dec '07  
GeneralExcellent JobmemberYuancai (Charlie) Ye6:29 12 Dec '07  
GeneralRe: Excellent JobmemberKel_12:48 12 Dec '07  
Generalgreat and big job!memberiBDev5:10 12 Dec '07  
Generalvery nice idea!membertuskilan2:29 12 Dec '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 14 Mar 2008
Editor:
Copyright 2007 by EJocys
Everything else Copyright © CodeProject, 1999-2008
Web17 | Advertise on the Code Project