'Share constants between C# and Javascript in MVC Razor

I'd like to use string constants on both sides, in C# on server and in Javascript on client. I encapsulate my constants in C# class

namespace MyModel
{
        public static class Constants
        {
            public const string T_URL = "url";
            public const string T_TEXT = "text";
     . . .
        }
}

I found a way to use these constants in Javascript using Razor syntax, but it looks weird to me:

@using MyModel
        <script type="text/javascript">

            var T_URL = '@Constants.T_URL';  
            var T_TEXT = '@Constants.T_TEXT';
     . . .
            var selValue = $('select#idTagType').val();
            if (selValue == T_TEXT) { ... 

Is there any more "elegant" way of sharing constants between C# and Javascript? (Or at least more automatic, so I do not have to make changes in two files)



Solution 1:[1]

You can use an HTML helper to output the script necessary, and use reflection to grab the fields and their values so it will automatically update.

    public static HtmlString GetConstants(this HtmlHelper helper)
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();

        sb.AppendLine("<script type=\"text/javascript\">");

        foreach (var prop in typeof(Constants).GetFields())
        {
            sb.AppendLine(string.Format("    var {0} = '{1}'", prop.Name, prop.GetValue(null).ToString()));
        }

        sb.AppendLine("</script>");
        return new HtmlString(sb.ToString());
    }

Solution 2:[2]

Rather then storing your constant data in a C# class, store it in a static config/constants file.

// Constants.json
{
    "T_URL": "url",
    "T_TEXT": "text"
}

// Constants.cs

// load the json from a file stream into a constants object

// Constants.js

window.Constants = $.getJSON(url);

Simply store it as some file format (json, xml, cvs, whatever) then load it up from both the client & server.

This means your either creating a class in the C# on the fly at runtime using black magic reflection or just have a hashtable / dictionary containing your constants under keys.

jQuery.getJSON, JsonReaderWriterFactor

Solution 3:[3]

My version to create a namespaced javascript object from my C# constants that is immutable:

public static HtmlString GetConstants<T>()
        {
            StringBuilder jsConstant = new StringBuilder();
                jsConstant.Append("myApp." + typeof(T).Name + " = Object.freeze({");
            foreach(var item in typeof(T).GetFields())
            {
                jsConstant.Append(string.Format("{0}:'{1}'",item.Name,item.GetValue(null).ToString()) + ",");
            }
            jsConstant.Remove(jsConstant.Length - 1, 1);
            jsConstant.Append("})");
            return new HtmlString(jsConstant.ToString());
        }

Used like this in Razor:

@(HtmlHelpers.GetConstants<MyApp.Infrastructure.ApplicationConstants.SomeConstants>())

Solution 4:[4]

Another option is to add the constant as a data- value to the button/link calling the JavaScript code.

Your view:

<button data-url="@T_URL" ...>

Your script:

$('button').click(function(event) {
    var url = $(this).data('url');
    ...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jay
Solution 2
Solution 3 bigbadmad
Solution 4 Jonathan E. Landrum