Allow the BuildModel method in the DefaultViewService class to be overridden in the derived classes
The issue
Marking the BuildModel method as a virtual method is crucial for extending the tokens of the HTML assets that can be populated by the view service.
The scenario
I'm trying to implement a LocalizedViewService that inherits the DefaultViewService, read the current culture from the current thread and injects the current language code and the text direction to the _layout.html asset like that:
<html lang="{languageCode}" dir="{languageTextDirection}" ng-app="app" ng-controller="LayoutCtrl">
Making BuildModel virtual would lead to the following clean implementation:
public class LocalizedViewService : DefaultViewService
{
public LocalizedViewService(LocalizedViewServiceOptions config, LocalizedViewLoader viewLoader)
: base(config, viewLoader)
{
}
protected override object BuildModel(CommonViewModel model, string page, IEnumerable<string> stylesheets, IEnumerable<string> scripts)
{
var currentUiCulture = Thread.CurrentThread.CurrentUICulture;
var languageCode = currentUiCulture.TwoLetterISOLanguageName;
var languageTextDirection = currentUiCulture.TextInfo.IsRightToLeft ? "rtl" : "ltr";
var data = base.BuildModel(model, page, stylesheets, scripts) as Dictionary<string, object>;
data.Add("languageCode", languageCode);
data.Add("languageTextDirection", languageTextDirection);
return data;
}
}
Unfortunately, for some reason the BuildModel method is not allowed to be overridden. And this makes it very difficult to extent the model, leading to override the Render method just to add couple of properties to the dictionary model which seems completely wrong.
public class LocalizedViewService : DefaultViewService
{
public LocalizedViewService(LocalizedViewServiceOptions config, LocalizedViewLoader viewLoader)
: base(config, viewLoader)
{
}
protected object BuildModelWithLanguageInfo(CommonViewModel model, string page, IEnumerable<string> stylesheets, IEnumerable<string> scripts)
{
var data = base.BuildModel(model, page, stylesheets, scripts);
//Extend data object & add language & dir info
var dynamicData = data.ToDynamic();
var currentUiCulture = Thread.CurrentThread.CurrentUICulture;
dynamicData.languageCode = currentUiCulture.TwoLetterISOLanguageName;
dynamicData.languageTextDirection = currentUiCulture.TextInfo.IsRightToLeft ? "rtl" : "ltr";
return dynamicData;
}
protected override async Task<Stream> Render(CommonViewModel model, string page, IEnumerable<string> stylesheets, IEnumerable<string> scripts)
{
var data = BuildModelWithLanguageInfo(model, page, stylesheets, scripts);
string html = await LoadHtmlTemplate(page);
html = FormatHtmlTemplate(html, data);
return html.ToStream();
}
}