Я использую движок Razor уже несколько дней, и мне это очень нравится. С самого начала я заметил одну большую проблему: все строки закодированы в HTML. Для нашего использования это становится довольно раздражающей «особенностью», когда мы имеем дело со строками JSON. Например, с учетом простогоСтрока JSON, ["1", "2", "3", "4"]
Фактический кодированный HTML-код этого результата стал ["1", "2", "3", "4"]
Кавычки были экранированы, что не является желаемым выводом. Если нам нужно отправить обратно HTML или XML, мы должны были бы затем индивидуально экранировать их. В целом, это довольно раздражает, так какнам бы пришлось обернуть его внутри HtmlString, как показано в этом сообщении StackOverflow.
В нашем сценарии мы генерируем JSON / XML из C #, поэтому большую часть времени наши сериализованные данные находятся внутри ViewModelЧто привело бы к тому, что мы делаем что-то вродеe, @ (new HtmlString (View.Foo)) @ (new HtmlString (View.Bar))
Как видите, это может стать довольно громоздким.Поэтому я решил сделать плагиат часть MVC для создания RawView.В конце концов, использование будет следующим: @ RawView.Foo @ RawView.Bar
Я также решил разрешить использование оператора индекса в случае необходимости зацикливаться на нем со спискомключи.// Предполагая, что у нас есть Foo, Bar и Baz в нашей ViewModel @ {List keys = new List {"Foo", "Bar", "Baz"};foreach (var key in keys) {@RawView [key]}}
Чтобы добиться этого, мне нужно будет дублировать DynamicViewDataDictionary.Естественно, я назвал его DynamicRawViewDataDictionary, открытый класс DynamicRawViewDataDictionary: DynamicObject {private readonly Func viewThunk;public DynamicRawViewDataDictionary (Func viewThunk) {this.viewThunk = viewThunk;}
private ViewDataDictionary ViewData
{
get
{
ViewDataDictionary viewData = this.viewThunk();
return viewData;
}
}
public object this[string key]
{
set { setData(key, value); }
get { return getData(key); }
}
public override IEnumerable<string>
GetDynamicMemberNames () {return ViewData.Keys;}
public override bool TryGetMember(GetMemberBinder binder,
out object result) {result = getData (binder.Name);вернуть истину;}
public override bool TrySetMember(SetMemberBinder binder,
значение объекта) {setData (binder.Name, value);вернуть истину;}
private object getData(string key)
{
object value = ViewData[key];
if (value is string)
{
return new HtmlString(value.ToString());
}
return value;
}
private void setData(string key, object value)
{
ViewData[key] = value;
}
}
Причина дублирования заключается в том, что DynamicViewDataDictionary является внутренним запечатанным классом.Я никак не мог обойти это ограничение, кроме копирования и вставки.Очевидное изменение, которое я внес в этот класс, - это метод getData.Я проверил, является ли объект строкой, если это так, я обернул его HtmlString ().
Теперь мне нужно использовать это внутри WebViewPage, так как все представления, я должен иметьнастраиваемая версия WebViewPage, а также.Хорошо, что MS не сделала этот класс внутренним, так что я могу легко унаследовать его.Мне нужно было сделать универсальную и неуниверсальную версию, я просто поместил оба из этого в один файл.открытый абстрактный класс CustomWebViewPage: WebViewPage {private DynamicRawViewDataDictionary _rawData;public dynamic RawView {get {if (_rawData == null) {_rawData = new DynamicRawViewDataDictionary (() => ViewData);} return _rawData;}}}
public abstract class CustomWebViewPage : WebViewPage
{
private DynamicRawViewDataDictionary _rawData;
public dynamic RawView
{
get
{
if (_rawData == null)
{
_rawData = new DynamicRawViewDataDictionary(() =>
ViewData);} return _rawData;}}}
Чтобы последний штрих действительно сделал эту работу, в верхней части файла cshtml у вас должно быть что-то вроде @inherits Namespace.To.CustomWebViewPage
// или @наследует Namespace.To.CustomWebViewPage
Теперь, когда файл cshtml наследуется от нового CustomWebViewPage, он должен иметь доступ к RawView, который обернет все строки HtmlString.
После того, как это будет сделано, вам все равно нужно будет убедиться, чтоваших новых представлений наследует от CustomWebViewPage.Я настоятельно рекомендую использовать пользовательские шаблоны кода в вашем проекте MVC для создания представления.Это поможет с автоматизацией многих мирских задач.