Константы совместного использования между С# и Javascript в MVC Razor
Я хотел бы использовать строковые константы с обеих сторон, в С# на сервере и в Javascript на клиенте.
Я инкапсулирую мои константы в класс С#
namespace MyModel
{
public static class Constants
{
public const string T_URL = "url";
public const string T_TEXT = "text";
. . .
}
}
Я нашел способ использовать эти константы в Javascript, используя синтаксис Razor, но мне это выглядит странно:
@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) { ...
Есть ли более "элегантный" способ обмена константами между С# и Javascript?
(Или, по крайней мере, более автоматический, поэтому мне не нужно вносить изменения в два файла)
Ответы
Ответ 1
То, как вы его используете, опасно. Представьте, что некоторые из ваших констант содержали цитату или, что еще хуже, другие опасные символы = > , которые нарушали бы ваши javascripts.
Я бы рекомендовал вам написать действие контроллера, которое будет обслуживать все константы как 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 + ";");
}
а затем в вашем макете ссылку script:
<script type="text/javascript" src="@Url.Action("Constants")"></script>
Теперь, когда вам нужна константа в ваших сценариях, просто используйте ее по имени:
<script type="text/javascript">
alert(constants.T_URL);
</script>
Ответ 2
Вы можете использовать HTML-помощник для вывода script необходимого и использовать отражение, чтобы захватить поля и их значения, чтобы он автоматически обновлялся.
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());
}
Ответ 3
Моя версия для создания объекта javascript с именами из констант С#, которые неизменяемы:
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());
}
Используется как в Razor:
@(HtmlHelpers.GetConstants<MyApp.Infrastructure.ApplicationConstants.SomeConstants>())
Ответ 4
Вместо сохранения ваших постоянных данных в классе С# сохраните его в статическом файле config/constants.
// 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);
Просто сохраните его как некоторый формат файла (json, xml, cvs, whatever), а затем загрузите его как с клиента, так и с сервера.
Это означает, что вы либо создаете класс в С# на ходу во время выполнения с использованием отражения черной магии, либо просто имеете хеш-таблицу/словарь, содержащий ваши константы под клавишами.
jQuery.getJSON
, JsonReaderWriterFactor