在梳理css文件后引用图像

时间:2011-04-24 21:48:21

标签: asp.net css

我正在开发一个asp.net webforms网站。网站结构:

/
    capabilities/
        capability-A/
            style.css
            images/
                imageA.png
                imageB.png
        capability-B/
            style.css
            images/
                imageC.png
                imageD.png
        ...

在发布版本中,所有style.css文件被合并并放入/style.css文件中。因为他们可能会引用相应capability/images文件夹中的图像(使用相对路径),所有图像都会复制到/images文件夹中。

在调试版本中,结构不会改变(css文件没有组合等)。

当我尝试在页面上引用这些图像时,问题就出现了问题 - 图像路径在调试和发布版本中有所不同(例如/capabilities/capability-A/images/foo.png用于调试,/images/foo.png用于发布)。

我想到的一个非常糟糕的想法是每次检查HttpContext.Current.IsDebuggingEnabled并放置不同的图像路径。

另一个 - 使用绝对路径引用所有图像,而不是将图像复制到/images文件夹。使用这种方法,我无法在不改变内容的情况下将css重命名/移动到任何地方。

第三个是始终引用调试版路径,并且在每个版本构建中用正确的路径替换那些调试版路径(但我希望有一个更简单的方法)。

如何在合并css文件后解决此引用图像问题?

2 个答案:

答案 0 :(得分:1)

为什么不使用一些辅助函数来输出图像路径 - 辅助函数可以获取图像的站点相对路径并按照调试版本(使用条件语句#if)输出它并折叠释放路径建立。例如,

public string GetImagePath(string url)
{
   #if DEBUG
      return "/images/" + url;
   #else
      return "/images/" + url.Substring(url.LastIndexOf(”/”) + 1);
   #endif
}

使用它,例如

<img src='<%= GetImagePath("/capabilities/capability-A/images/foo.png")  %>'

编辑:另一种选择是通过简单的http处理程序(如

)提供所有图像
<%@ WebHandler Language="C#" Class="ImageHandler" %>

using System;
using System.Web;

public class ImageHandler : IHttpHandler {

    public void ProcessRequest (HttpContext context) {
       // get relative image path (or have some key to image mapping logic)
       var path = request.QueryString["q"]; 

       // map image path
       #if DEBUG

       #else
          path = System.IO.Path.GetFileName(path);
       #endif

       // get the physical path
       path = Path.Combine(context.Server.MapPath("~/Images"), path);

       // Emit cache headers (recommended)
       ...

       // transmit the image file
       context.Response.TransmitFile(path);
    }
}

答案 1 :(得分:0)

好的,我找到了解决方案。我决定将图像保留在其文件夹中,并用绝对路径替换css文件中的相对路径,而不是在发布版本中复制图像和替换页面中的路径。在组合文件之前进行替换,以便replacer-script可以获得有关css文件所在位置的信息以生成绝对路径。我使用来自msbuild社区任务的Script和FileUpdate任务的Web部署项目来实现这一点。脚本任务用于创建需要插入每个相对路径前面的绝对URL部分。 FileUpdate任务用于使用正则表达式替换所有相对路径及其绝对模拟。

这是msbuild脚本的一部分:

<Target Name="BeforeBuild">
    <CallTarget Targets="CombineAndMinifyCssAndJavaScript" />
</Target>

<Target Name="_InitCombineAndMinifyCssAndJavaScript">
    <ItemGroup>
        <!-- These are the CSS files that will be combined. -->
        <InputCssFiles Include="$(CopyBeforeBuildTargetPath)\capabilities\**\*.css" />
    </ItemGroup>
</Target>

<Target Name="_CorrectResourceUrlsInCSSFiles"
        Outputs="%(InputCssFiles.Identity)"
        DependsOnTargets="_InitCombineAndMinifyCssAndJavaScript"
        Condition=" '@(InputCssFiles)' != '' ">
    <PropertyGroup>
        <InputCssFileDir>%(InputCssFiles.RootDir)%(InputCssFiles.Directory)</InputCssFileDir>
        <CodeToExtractAbsoluteUrlPath>
            <![CDATA[
                public static String ScriptMain()
                {
                    String cssDir = @"$(InputCssFileDir)".ToLowerInvariant();
                    String websiteDir = @"$(CopyBeforeBuildTargetPath)".ToLowerInvariant();

                    cssDir = cssDir.TrimEnd(new char[] { '\\' });
                    websiteDir = websiteDir.TrimEnd(new char[] { '\\' });

                    if (!cssDir.StartsWith(websiteDir))
                    {
                        throw new ArgumentException(String.Format(
                            "CSS file directory ({0}) should be somewhere under website root ({1}).", cssDir, websiteDir));
                    }

                    String absoluteUrlPath = (cssDir.Remove(0, websiteDir.Length) + "\\").Replace('\\', '/');
                    return absoluteUrlPath;
                }
            ]]>
        </CodeToExtractAbsoluteUrlPath>
    </PropertyGroup>

    <Script Language="C#" Code="$(CodeToExtractAbsoluteUrlPath)">
        <Output PropertyName="AbsoluteUrlPath" TaskParameter="ReturnValue" />
    </Script>

    <!--
        Regex is:
            url \s*
            \( \s*
                ['"]
                    ([^/'":][^'":]*)
                ['"]
            \s* \)
    -->
    <FileUpdate
        Files="%(InputCssFiles.FullPath)"
        Regex="url\s*\(\s*[&apos;&quot;]([^/&apos;&quot;:][^&apos;&quot;:]*)[&apos;&quot;]\s*\)"
        ReplacementText="url('$(AbsoluteUrlPath)$1')" />
</Target>