2011-04-24 79 views
0

我正在開發一個asp.net webforms網站。網站結構:梳理css文件後引用圖像

/ 
    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文件後解決這個引用圖像問題?

+0

你可以顯示一個例子,如何引用一個圖像的CSS? – Louis 2011-04-25 01:19:23

+0

@Louis:喜歡'.bg-add { \t background-image:url('images/add.png'); }' – 2011-04-25 06:16:23

+0

對於我來說,在調試和發佈構建中,路徑總是相對於css文件的位置。 – Louis 2011-04-25 17:25:09

回答

0

好服務於所有圖像,我發現一個辦法。我沒有在發佈版本中複製圖像並替換頁面中的路徑,而是決定將圖像保留在其文件夾中,並用絕對路徑替換css文件中的相對路徑。在合併文件之前進行替換,以使替換腳本可以獲得有關css文件所在位置的信息以生成絕對路徑。我使用帶有來自msbuild社區任務的腳本和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> 
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); 
    } 
} 
+0

謝謝,這是另一種方法。但我不喜歡的是,對於服務器控件,我必須在代碼隱藏中設置圖像路徑。 – 2011-04-25 19:06:03

+0

@Loki,這是正確的 - 一種解決方法是使用數據綁定表達式,例如'<%#GetImagePath(...)#%>' - 這裏的技巧是調用頁面上的DataBind調用或合適的容器控件。還有一種方法是通過處理程序(ashx)提供所有圖像 - 我編輯了答案,爲相同的代碼添加了基本代碼。 – VinayC 2011-04-26 04:26:56