How to Pass Web.Config Settings to AngularJS
Tuesday, August 5, 2014
In ASP.NET, we typically store settings in web.config
and sometimes in the database. It’s pretty trivial to access these values in server-side code, but what about in client-side JavaScript? We could store JavaScript configurations in a JSON file, but then we'd have configuration settings in different places and there is likely some duplication. Plus there is no easy way to create environment specific configurations like we can if the values were in web.config
(using config transformations).
In my last couple of Angular projects, there needed a way for our Angular apps to access some values in web.config
. To do this, I created an MVC view that returned a JavaScript containing Angular constant with the configuration values; and it’s worked really well.
First, I created a class to hold the settings.
public class SettingsDto
{
public string WebApiBaseUrl { get; set; }
public string WebApiVersion { get; set; }
// ...
}
Then I created an action in my HomeController
to create the DTO and serialize it…
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
// ...
public ActionResult Settings(string angularModuleName = "myApp.settings")
{
var settings = new SettingsDto
{
WebApiBaseUrl = GetAppSetting<string>("WebApiBaseUrl"),
WebApiVersion = GetAppSetting<string>("WebApiVersion")
// ...
};
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var settingsJson = JsonConvert.SerializeObject(settings, Formatting.Indented, serializerSettings);
var settingsVm = new SettingsViewModel
{
SettingsJson = settingsJson,
AngularModuleName = angularModuleName
};
Response.ContentType = "text/javascript";
return View(settingsVm);
}
protected static T GetAppSetting<T>(string key)
{
return (T)Convert.ChangeType(ConfigurationManager.AppSettings[key], typeof(T));
}
To serialize the settings into JSON, I used JSON.NET. Notice I set the contract resolver so that it’ll camel-case the property names; and I set the response content type to “text/javascript”. The resulting JSON is stuffed into a simple SettingsViewModel
…
public class SettingsViewModel
{
public string SettingsJson { get; set; }
public string AngularModuleName { get; set; }
}
Now, here’s the Razor view that generates the JavaScript…
@model MyApp.SettingsViewModel
@{
Layout = null;
}
(function () {
angular.module('@Model.AngularModuleName', [])
.constant('settings', @Html.Raw(Model.SettingsJson));
})();
When we access /home/settings
, we’ll be returned this bit of JavaScript…
(function () {
angular.module('myApp.settings', [])
.constant('settings', {
webApiBaseUrl: "https://foo.com/bar",
webApiVersion: "v2"
});
})();
To use this, simply load the script…
<script src="~/home/settings"></script>
Then add the settings as a dependency in our app, and we can inject it into our controllers, services, and config blocks…
angular.module('myApp', ['myApp.settings'])
.controller('myController', ['settings', function (settings) {
var webApiBaseUrl = settings.webApiBaseUrl;
// ...
}]);
In ASP.NET, we typically store settings in web.config
and sometimes in the database. It’s pretty trivial to access these values in server-side code, but what about in client-side JavaScript? We could store JavaScript configurations in a JSON file, but then we'd have configuration settings in different places and there is likely some duplication. Plus there is no easy way to create environment specific configurations like we can if the values were in web.config
(using config transformations).
In my last couple of Angular projects, there needed a way for our Angular apps to access some values in web.config
. To do this, I created an MVC view that returned a JavaScript containing Angular constant with the configuration values; and it’s worked really well.
First, I created a class to hold the settings.
public class SettingsDto
{
public string WebApiBaseUrl { get; set; }
public string WebApiVersion { get; set; }
// ...
}
Then I created an action in my HomeController
to create the DTO and serialize it…
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
// ...
public ActionResult Settings(string angularModuleName = "myApp.settings")
{
var settings = new SettingsDto
{
WebApiBaseUrl = GetAppSetting<string>("WebApiBaseUrl"),
WebApiVersion = GetAppSetting<string>("WebApiVersion")
// ...
};
var serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var settingsJson = JsonConvert.SerializeObject(settings, Formatting.Indented, serializerSettings);
var settingsVm = new SettingsViewModel
{
SettingsJson = settingsJson,
AngularModuleName = angularModuleName
};
Response.ContentType = "text/javascript";
return View(settingsVm);
}
protected static T GetAppSetting<T>(string key)
{
return (T)Convert.ChangeType(ConfigurationManager.AppSettings[key], typeof(T));
}
To serialize the settings into JSON, I used JSON.NET. Notice I set the contract resolver so that it’ll camel-case the property names; and I set the response content type to “text/javascript”. The resulting JSON is stuffed into a simple SettingsViewModel
…
public class SettingsViewModel
{
public string SettingsJson { get; set; }
public string AngularModuleName { get; set; }
}
Now, here’s the Razor view that generates the JavaScript…
@model MyApp.SettingsViewModel
@{
Layout = null;
}
(function () {
angular.module('@Model.AngularModuleName', [])
.constant('settings', @Html.Raw(Model.SettingsJson));
})();
When we access /home/settings
, we’ll be returned this bit of JavaScript…
(function () {
angular.module('myApp.settings', [])
.constant('settings', {
webApiBaseUrl: "https://foo.com/bar",
webApiVersion: "v2"
});
})();
To use this, simply load the script…
<script src="~/home/settings"></script>
Then add the settings as a dependency in our app, and we can inject it into our controllers, services, and config blocks…
angular.module('myApp', ['myApp.settings'])
.controller('myController', ['settings', function (settings) {
var webApiBaseUrl = settings.webApiBaseUrl;
// ...
}]);