Returning generated CSS from an MVC5 or Web API 2 controller action

前端 未结 1 602
梦谈多话
梦谈多话 2020-12-20 04:00

In our multi-tenant application we have a need to customize the styles used per-tenant.

We currently plan to do so using LESS and variables in the following way

相关标签:
1条回答
  • 2020-12-20 04:11

    You could use BundleTransformer to compile your LESS server side.

    It can depend on how you want to serve the file. If you know all the tenants then just add add a bundle url for each tenant application to the bundle config.

     var themeStyles = new CustomStyleBundle("~bundles/theme/tenant").Include("~/Content/theme.less");
     themeStyles.Builder = new ThemeBuilder();
     BundleTable.Bundles.Add(themeStyles);
    

    If you don't and the tenants are flexible as was the case in our situation then add the following controller action for your themes.

        [Route("bundles/theme/{id}")]
        public ContentResult Theme(string id)
        {
            var tenantThemePath = string.Format("~/bundles/theme/{0}", id);
    
            // Check that bundle has not already been added.
            if (BundleTable.Bundles.All(x => x.Path != tenantThemePath))
            {
                var themeStyles = new CustomStyleBundle(tenantThemePath ).Include("~/Content/theme.less");
    
                themeStyles.Builder = new ThemeBuilder();
    
                BundleTable.Bundles.Add(themeStyles);
            }
    
            var context = new BundleContext(HttpContext, BundleTable.Bundles, institutionPath);
    
            var response = BundleTable.Bundles.GetBundleFor(tenantThemePath).GenerateBundleResponse(context);
    
            Response.Cache.SetCacheability(response.Cacheability);
    
            return Content(response.Content, response.ContentType);
        }
    

    The ThemeBuilder implementation for BundleTransformer

    public class ThemeBuilder : IBundleBuilder
    {
        public string BuildBundleContent(Bundle bundle, BundleContext context, IEnumerable<BundleFile> files)
        {
            var lessTranslator = bundle.Transforms.OfType<StyleTransformer>()
                .Where(x => x != null)
                .Select(x => x.Translators.OfType<LessTranslator>().FirstOrDefault())
                .FirstOrDefault();
    
            if (lessTranslator == null)
            {
                return string.Empty;
            }
    
            lessTranslator.GlobalVariables = GetThemeVariables();
    
            return string.Empty;
        }
    
        private string GetThemeVariables()
        {
            // Simplified for brevity
            // This will be translated to less variables by the BundleTransformer
            // themeColour should correspond to a variable name in your less file.  
            return string.Format("themeColour={0}", themeColour);
        }
    
    }
    

    You will need away of getting the theme colours out we stashed those variables in HttpContext stores so that we could pull them out using an extension method in the GetThemeVariables method.

    I hope this helps.

    UPDATE I've expanded on my original answer and created a more reusable way of including themes.

    Demo site here: http://bundletransformer-theme-builder.azurewebsites.net/

    GitHub repo here: https://github.com/benembery/bundle-transformer-theme-builder

    0 讨论(0)
提交回复
热议问题