Converting multiple C# enums to JavaScript
My last solution to turn C# enums to JavaScript was simple but needed some additional work to support multiple enums better. After some playing with different approaches I found simple one that works okay for me. This blog post describes my simple solution that turns multiple C# enums to JavaScript with one shot.
- ASP.NET Core: Converting C# enums to JavaScript
- ASP.NET Core: Building enum provider to convert C# enums to JavaScript
- Converting multiple C# enums to JavaScript
NB! This post is like chapter two to my previous enums post Converting C# enums to JavaScript. The code in this and current post is for ASP.NET MVC.
JavaScriptEnum attribute
Solutions where enums are used doesn’t use just one enum usually. Usually there are many enums in server-side code. Some of these are needed also in client-side but not all of them. So, we need some way to find all enums in our code that we need also in JavaScript. Easiest way to mark some enums to be available in JavaScript is using dummy attribute.
public class JavaScriptEnumAttribute : Attribute
{
}
We need this attribute only to detect enums that must be available in JavaScript.
Converting enum to JavaScript string
As a next thing we need a way to turn enum to JavaScript object. The code from previous enums post needs some refactoring – we need enum JavaScript as regular string and not as MvcHtmlString. Modified version of EnumToString() externsion method is here.
public static class HtmlEnumExtensions
{
public static MvcHtmlString EnumToString<T>(this HtmlHelper helper)
{
return new MvcHtmlString(EnumToString<T>());
}
private static string EnumToString<T>()
{
return EnumToString(typeof(T));
}
private static string EnumToString(Type enumType)
{
var values = Enum.GetValues(enumType).Cast<int>();
var enumDictionary = values.ToDictionary(value => Enum.GetName(enumType, value));
return JsonConvert.SerializeObject(enumDictionary);
}
}
Now all methods that need enum’s JavaScript representation can get enum as JavaScript without any formatting. Just plain JSON string with enum.
Converting marked enums to JavaScript
To solve the problem of converting multiple enums to JavaScript with one shot we need new extension method. This method detects all needed enums by JavaScriptEnum attribute and returns MvcHtmlString with given JavaScript.
public static MvcHtmlString JavaScriptEnums(this HtmlHelper helper)
{
var query = from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
from r in t.GetCustomAttributes<JavaScriptEnumAttribute>()
where t.BaseType == typeof(Enum)
select t;
var buffer = new StringBuilder(10000);
foreach (var jsEnum in query)
{
buffer.Append("var ");
buffer.Append(jsEnum.Name);
buffer.Append(" = ");
buffer.Append(EnumToString(jsEnum));
buffer.Append("; \r\n");
}
return new MvcHtmlString(buffer.ToString());
}
This method declares JavaScript variables with same names as enums that have JavaScriptEnum attribute.
Using JavaScriptEnums extension method
To demonstrate how to use JavaScriptEnums() extension method let’s create new ASP.NET MVC application with two enums.
[JavaScriptEnum]
public enum PaymentTypeEnum
{
CreditCard,
Check,
Cash
}
[JavaScriptEnum]
public enum CustomerStatusEnum
{
Regular,
Gold,
Platinum
}
Let’s call this method in the header of layout page.
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
<script>
@Html.JavaScriptEnums()
</script>
</head>
And here is the result.
<script>
var PaymentTypeEnum = { "CreditCard": 0, "Check": 1, "Cash": 2 };
var CustomerStatusEnum = { "Regular": 0, "Gold": 1, "Platinum": 2 };
</script>
If it is possible to modify the code above and create controller action that returns enums as JavaScript. Of course, then we get one additional call to server.
Wrapping up
After some playing with enums we have now decent solution to turn selected C# enums in our code to JavaScript with one shot. We used Enum class methods and a little bit reflection to work with enums. Marking enums with marker attribute was perhaps not the best idea if we consider shared libraries but for simpler web application it works well. By usinh HtmlHelper extension method for enums we followed current ASP.NET MVC extending style and our code is easy to understand and follow also for our fellow developers.
I believe you should use const[0] to create a global constants for enums, also JS being what it is, it will be good to freeze[1] enum objects to prevent them from accidental modification.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
[1] https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze