RC1 of the
ASP.NET MVC framework adds a new ActionResult, JavaScriptResult. This class takes a string and returns a response with the string with the required ContentType.
So now theres a built in (very simple) ActionResult for returning JavaScript what about generating the JavaScript string on the server to return?
One thing I do alot is to recreate service side enums on the client in JavaScript, so rather than checking values I can use names, which improves the readability of the javascript. However this requires both the server and the client to be kept in sync, which can be a pain.
To resolve this issue I’ve created a JavaScriptGenerator class which handles serialization of objects and Enum types as variables and generates the JavaScriptResult, as well as a helper method to take a controller name and action name and insert the required <script .. /> tag into the markup.
Note I’ve created my own JavaScriptHelper class, similar to HtmlHelper, that I extend with extension methods the are javascript specific. I’ve also got a bunch of other extension methods for registering variables in the html itself as well as adding the <script /> tag for a specified filename.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace LukeSmith.Web.Mvc.JavaScript
{
public class JavaScriptGenerator
{
private StringBuilder builder;
///
/// Initializes a new instance of the class.
///
public JavaScriptGenerator()
{
builder = new StringBuilder();
}
///
/// Generates a javascript variable from enum.
///
/// The name to give the javascript variable.
/// Type of the enum.
///
/// Current instance of the .
///
///
public JavaScriptGenerator GenerateVariableFromEnum(string name, Type enumType)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
if (enumType.IsEnum)
{
Array values = Enum.GetValues(enumType);
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary dictionary =new Dictionary();
foreach (var value in values)
{
string enumName = Enum.GetName(enumType, value);
dictionary.Add(enumName, value);
}
builder.Append(string.Format("var {0} = {1};", name, serializer.Serialize(dictionary)));
}
else
{
throw new InvalidOperationException("Cannot generate JavaScript code when enumType is not an Enum.");
}
return this;
}
///
/// Generates a javascript variable from an object.
///
/// The name to give the javascript variable.
/// The value.
///
/// Current instance of the .
///
public JavaScriptGenerator GenerateVariableFromObject(string name, object value)
{
List converters = new List();
return this.GenerateVariableFromObject(name, value, converters);
}
///
/// Generates a javascript variable from an object.
///
/// The name to give the javascript variable.
/// The value.
/// The to use to convert the .
///
/// Current instance of the .
///
public JavaScriptGenerator GenerateVariableFromObject(string name, object value, JavaScriptConverter converter)
{
List converters = new List();
converters.Add(converter);
return this.GenerateVariableFromObject(name, value, converters);
}
///
/// Generates a javascript variable from an object.
///
/// The name to give the javascript variable.
/// The value.
/// An of to use to convert the .
///
/// Current instance of the .
///
public JavaScriptGenerator GenerateVariableFromObject(string name, object value, IEnumerable converters)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(converters);
builder.Append(string.Format("var {0} = {1};", name, serializer.Serialize(value)));
return this;
}
///
/// Generates the .
///
///
public JavaScriptResult Generate()
{
return new JavaScriptResult() { Script = this.ToString() };
}
///
/// Returns a that represents the current .
///
///
/// A that represents the current .
///
public override string ToString()
{
return builder.ToString();
}
}
}
And the code for the helper method
public static string ScriptInclude(this JavaScriptHelper javaScriptHelper, string actionName, string controllerName)
{
UrlHelper helper = new UrlHelper(javaScriptHelper.ViewContext.RequestContext);
string url = helper.Action(actionName, controllerName);
return string.Format("{1}", url, Environment.NewLine);
}