【问题标题】:Returning generated CSS from an MVC5 or Web API 2 controller action从 MVC5 或 Web API 2 控制器操作返回生成的 CSS
【发布时间】:2014-09-23 01:39:36
【问题描述】:

在我们的多租户应用程序中,我们需要自定义每个租户使用的样式。

我们目前计划在客户端使用 LESS 和变量

  1. 从服务器下载依赖 LESS 文件
  2. 调用网络服务获取配置对象
  3. 定义了变量的有效 LESS 格式字符串
  4. 使用less.js 编译器根据这些变量和步骤 1 中固定的 LESS 文件编译 LESS

这种方法有很多缺点:

  • 客户可能表现不佳
  • 部分浏览器出现less.js问题
  • 编译需要时间

我们希望在服务器上处理这项工作,因此粗略地说,这发生在服务器上:

  1. 客户端请求下载一个大的编译样式表 - GET content/styles/{tenantName}.css
  2. 使用tenantName服务器获取配置
  3. 使用模板和适当的变量(可能是string.Format 或更复杂的东西)
  4. 服务器将 LESS 编译为 CSS 字符串
  5. 服务器返回带有适当Content-Type的CSS字符串

这是我的问题:

  1. 这是实现上述结果的不寻常或不受欢迎的方式吗?
  2. 服务器端 JavaScript 架构设置不足,如何将 LESS 编译成 CSS?
  3. 我必须在控制器操作或路由配置中做什么才能让客户端认为服务器正在返回一个常规的旧 CSS 文件,完成缓存控制,而不是修改?

【问题讨论】:

  • 难道您还没有将所有的 less 文件预先编译为 css,那么这只是提供正确 css 文件的情况。
  • 不,因为租户在编译时是未知的。

标签: css asp.net-mvc less asp.net-web-api2


【解决方案1】:

您可以使用BundleTransformer 来编译您的LESS 服务器端。

这取决于您希望如何提供文件。如果您知道所有租户,那么只需将每个租户应用程序的捆绑 url 添加到捆绑配置中。

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

如果您不这样做并且租户像我们的情况一样灵活,那么为您的主题添加以下控制器操作。

    [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);
    }

BundleTransformer 的 ThemeBuilder 实现

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);
    }

}

您将不需要取出主题颜色,我们将这些变量隐藏在 HttpContext 存储中,以便我们可以使用 GetThemeVariables 方法中的扩展方法将它们取出。

我希望这会有所帮助。

更新 我扩展了我的原始答案,并创建了一种包含主题的更可重用的方式。

这里是演示站点:http://bundletransformer-theme-builder.azurewebsites.net/

这里的 GitHub 存储库:https://github.com/benembery/bundle-transformer-theme-builder

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-22
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多