BundleTransformer.Less根据上下文/请求注入变量

时间:2013-06-05 17:10:54

标签: c# system.web.optimization bundletransformer

我们希望将System.Web.Optimization的捆绑机制与Less transformer结合使用。

问题是相同的应用程序/服务器为不同品牌的网站提供页面。因此,根据'SiteContext',使用相同的.less文件,但.less变量应使用不同的值。因此,我们希望(重新)使用相同的较少文件,但具有不同的变量,具体取决于请求的上下文。

我尝试了几种不同的理论:

在所有3种情况下,我根据SiteContext设置了不同的包。

1使用主题变量注入@import指令,方法是使用拦截variables.less文件的自定义VirtualPathProvider

所以我有:

  • 样式文件例如:header.less(导入变量文件)
  • 变量文件:variables.less
  • 一个主题变量文件:variables-theme.less(通过VirtualPathProvider注入variables.less)

这不起作用,因为BundleTransformer缓存将此视为同一文件,并且不知道SiteContext。缓存密钥基于IAsset的Url,我们无法影响此行为。

2使用变量-themed.less替换variables.less import ,并在Less变换器之前运行自定义变换器

再次没有运气,同样的缓存问题。

作为副作用,额外的变换器未在调试中调用,因为资产未捆绑但由LessAssetHandler单独调用。这可以通过编写调用所有必需变换器的自己的AssetHandler来解决。

自定义VirtualPathProvider 解析的

3创建主题资产名称 例如。将header-themeX.less添加到包中,此文件不存在,但您将此文件解析为header.less并使用方法2设置正确的变量文件导入。 (将变量的导入替换为主题版本。)

再一次没有运气。我认为这可以解决缓存问题,如果不是内部Bundle.Include(string virtualPath)的{​​{1}}。它不会通过File.Exists(path)传递。


我是否希望能够解决这个问题? 欢迎所有的想法,我可以想象随着CustomVirtualPathProvider图书馆越来越受欢迎,这将成为越来越多人的问题......

请记住:

  • 我们有很多.less / css文件
  • 我们将有5个左右的主题
  • 我们喜欢在visual studio中保持工作(这就是为什么header.less有一个ref.to variables.less)。

感谢您的反馈。

1 个答案:

答案 0 :(得分:2)

迈克尔!

您在多租户环境中使用Microsoft ASP.NET Web Optimization FrameworkBundle Transformer,因此您需要替换System.Web.Optimization的某些组件并创建自己的调试HTTP处理程序版本(请参阅«Problem: LESS file imports are added to BundleResponse.Files collection»讨论)。据我所知,Murat Cakir在SmartStore.NET项目中解决了所有这些问题。

在Bundle Transformer中有两种注入LESS变量的方法:

  1. 查看LESS-translator的属性GlobalVariablesModifyVariables

    using System.Collections.Generic;
    using System.Web.Optimization;
    
    using BundleTransformer.Core.Builders;
    using BundleTransformer.Core.Orderers;
    using BundleTransformer.Core.Transformers;
    using BundleTransformer.Core.Translators;
    using BundleTransformer.Less.Translators;
    
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            var nullBuilder = new NullBuilder();
            var nullOrderer = new NullOrderer();
    
            var lessTranslator = new LessTranslator
            {
                GlobalVariables = "my-variable='Hurrah!'",
                ModifyVariables = "font-family-base='Comic Sans MS';body-bg=lime;font-size-h1=50px"
            };
            var cssTransformer = new CssTransformer(new List<ITranslator>{ lessTranslator });
    
            var commonStylesBundle = new Bundle("~/Bundles/BootstrapStyles");
            commonStylesBundle.Include(
               "~/Content/less/bootstrap-3.1.1/bootstrap.less");
            commonStylesBundle.Builder = nullBuilder;
            commonStylesBundle.Transforms.Add(cssTransformer);
            commonStylesBundle.Orderer = nullOrderer;
    
            bundles.Add(commonStylesBundle);
        }
    }
    
  2. 创建自定义项目转换:

    using System.Text;
    using System.Web.Optimization;
    
    public sealed class InjectContentItemTransform : IItemTransform
    {
        private readonly string _beforeContent;
        private readonly string _afterContent;
    
        public InjectContentItemTransform(string beforeContent, string afterContent)
        {
            _beforeContent = beforeContent ?? string.Empty;
            _afterContent = afterContent ?? string.Empty;
        }
    
        public string Process(string includedVirtualPath, string input)
        {
            if (_beforeContent.Length == 0 && _afterContent.Length == 0)
            {
                return input;
            }
    
            var contentBuilder = new StringBuilder();
            if (_beforeContent.Length > 0)
            {
                contentBuilder.AppendLine(_beforeContent);
            }
            contentBuilder.AppendLine(input);
            if (_afterContent.Length > 0)
            {
                contentBuilder.AppendLine(_afterContent);
            }
    
            return contentBuilder.ToString();
        }
    }
    
  3. 并按如下方式注册此转换:

        using System.Web.Optimization;
    
        using BundleTransformer.Core.Orderers;
        using BundleTransformer.Core.Bundles;
    
        public class BundleConfig
        {
            public static void RegisterBundles(BundleCollection bundles)
            {
                var nullOrderer = new NullOrderer();
    
                const string beforeLessCodeToInject = @"@my-variable: 'Hurrah!';";
                const string afterLessCodeToInject = @"@font-family-base: 'Comic Sans MS';
    @body-bg: lime;
    @font-size-h1: 50px;";
    
                var commonStylesBundle = new CustomStyleBundle("~/Bundles/BootstrapStyles");
                commonStylesBundle.Include(
                   "~/Content/less/bootstrap-3.1.1/bootstrap.less",
                   new InjectContentItemTransform(beforeLessCodeToInject, afterLessCodeToInject));
                commonStylesBundle.Orderer = nullOrderer;
    
                bundles.Add(commonStylesBundle);
            }
        }
    

    两种方式都有缺点:注入LESS变量在调试模式下不起作用。