Share constants between C# and Javascript in MVC Razor

Solution 1:

The way you are using it is dangerous. Imagine some of your constants contained a quote, or even worse some other dangerous characters => that would break your javascripts.

I would recommend you writing a controller action which will serve all constants as javascript:

public ActionResult Constants()
{
    var constants = typeof(Constants)
        .GetFields()
        .ToDictionary(x => x.Name, x => x.GetValue(null));
    var json = new JavaScriptSerializer().Serialize(constants);
    return JavaScript("var constants = " + json + ";");
}

and then in your layout reference this script:

<script type="text/javascript" src="@Url.Action("Constants")"></script>

Now whenever you need a constant in your scripts simply use it by name:

<script type="text/javascript">
    alert(constants.T_URL);
</script>

Solution 2:

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 3:

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 4:

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>())