Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Allow the BuildModel method in the DefaultViewService class to be overridden in the derived classes #3593

Open
OsmanMElsayed opened this issue Mar 25, 2017 · 0 comments

Comments

@OsmanMElsayed
Copy link
Contributor

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();
        }
    }
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants