解析' @import(less)'语句使用dotLess在ASP.net MVC 5项目中引发NullReferenceException

时间:2014-10-14 22:51:56

标签: c# .net asp.net-mvc less dotless

短篇小说

带有Web Essentials的Visual Studio 2013.3,带有dotLess 1.4.1的ASP .NET MVC 5项目。尝试在一个简单的less文件中使用@import (less)语句,只导入一个简单的css文件,导致NullReferenceException加注。没有@import指令的(less)没有按预期解析 - 它只是被解压缩到结果较少的文件。 有没有办法解决这个问题?或者它只是dotLess的一个错误?


长篇故事(包含重现的步骤)

  1. 在Visual Studio 2013.3中创建一个新的ASP .NET MVC 5项目
  2. 通过NuGet Package Manager安装最新版本的dotless
  3. ~/Content/内部文件夹中创建一个简单的Site.less文件,该文件仅导入默认的Site.css文件:
  4. _

    @import (less) "Site.css";
    
    1. 根据Bundling and Minification article of ASP .NET MVC 4 tutorial创建LessTransform课程如下:
    2. _

      using System.Web.Optimization;
      
      public class LessTransform : IBundleTransform
      {
          public void Process(BundleContext context, BundleResponse response)
          {
              response.Content = dotless.Core.Less.Parse(response.Content);
              response.ContentType = "text/css";
          }
      }
      
      1. RegisterBundles文件BundleConfig内的BundleConfig.cs方法中添加以下行:
      2. _

        var lessBundle = new Bundle("~/Content/less").Include("~/Content/Site.less");
        lessBundle.Transforms.Add(new LessTransform());
        bundles.Add(lessBundle);
        
        1. _Layout.cshtml文件中删除(或只是注释掉)行:
        2. _

          @Styles.Render("~/Content/css")
          

          并添加以下行:

          @Styles.Render("~/Content/less")
          
          1. 运行项目
          2. 结果NullReferenceException课程中会引发LessTransform

            response.Content = Less.Parse(response.Content);
            

            有没有办法解决这个问题?或者它只是dotLess的一个错误?


            知识库

            1. 更改
            2. _

              @import (less) "Site.css";
              

              @import (less) "./Site.css";
              

              无济于事。

              1. 将{始终复制到Site.css的输出目录无效。

              2. @import (less) "Site.css"更改为@import "Site.css"没有任何帮助,因为dotLess不会像我们预期的那样解析结果行。它只是复制该行而不进行任何处理。

              3. Web Essentials 2013 for Update 3正确表示较少文件的编译版本。尽管如此,问题仍然存在。

3 个答案:

答案 0 :(得分:0)

我不认为DotLess支持这种类型的导入@import (less) "Site.css";它在第1版第1节中介绍,但是Dotless并不总是最新的。

只需导入css就可以正常工作,然后捆绑可以解决剩下的问题。

@import site.css

答案 1 :(得分:0)

您可能想尝试使用Web Essentials 2013。看看它是否可以在保存(和构建)时编译较少。

答案 2 :(得分:0)

如果使用DotGess与WebGrease和System.Web.Optimization之类的东西进行捆绑,请在此处查看LessTransform代码:

https://github.com/philipproplesch/Web.Optimization/blob/master/src/Web.Optimization.Bundles.Less/LessTransform.cs

在编译和捆绑时,你需要做一些时髦的东西来让import命令工作。项目中还有一个LessBundle定义,但是当我创建我的端口时,我只是声明了一个标准Bundle并将变换应用到它。

摘录于此,截至2014年10月15日:

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Optimization;
using Web.Optimization.Common;
using dotless.Core.configuration;

namespace Web.Optimization.Bundles.Less
{
    public class LessTransform : IBundleTransform
    {
        private readonly DotlessConfiguration _configuration;

        public LessTransform(DotlessConfiguration configuration)
        {
            _configuration = configuration;
        }

        public LessTransform()
            : this(DotlessConfiguration.GetDefaultWeb())
        { }

        public void Process(BundleContext context, BundleResponse response)
        {
            var builder = new StringBuilder();

            foreach (var file in response.Files)
            {
                var path =
                   context.HttpContext.Server.MapPath(
                       file.IncludedVirtualPath);

                var fileInfo = new FileInfo(path);

                if (!fileInfo.Exists)
                {
                    continue;
                }

                var content = ResolveImports(fileInfo);

                builder.AppendLine(
                    _configuration.Web
                        ? dotless.Core.LessWeb.Parse(content, _configuration)
                        : dotless.Core.Less.Parse(content, _configuration));
            }

            response.ContentType = ContentType.Css;
            response.Content = builder.ToString();
        }

        private static readonly Regex s_lessImportRegex =
            new Regex("@import [\"|'](.+)[\"|'];", RegexOptions.Compiled);

        private static string ResolveImports(FileInfo file)
        {
            var content = File.ReadAllText(file.FullName, Encoding.UTF8);

            return s_lessImportRegex.Replace(
                content,
                match =>
                {
                    var import = match.Groups[1].Value;

                    // Is absolute path?
                    Uri uri;
                    if (Uri.TryCreate(import, UriKind.Absolute, out uri))
                    {
                        return match.Value;
                    }

                    var path =
                        Path.Combine(
                            file.Directory.FullName,
                            import);

                    if (!File.Exists(path))
                    {
                        throw new ApplicationException(
                            string.Concat("Unable to resolve import ", import));
                    }

                    return match.Value.Replace(import, path);
                });
        }
    }
}