2011-04-24 5 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など)。

私が考えていた1つの本当に悪い考えは、HttpContext.Current.IsDebuggingEnabledをチェックし、毎回異なる画像パスを入れたことでした。

もう1つ - 絶対パスを使用するすべての画像を参照し、/imagesフォルダに画像をコピーしないでください。このアプローチでは、内容を変更することなくどこでもcssの名前を変更/移動することはできません。

第3の問題は、常にデバッグバージョンのパスを参照することです。各リリースのビルドでは、それらのデバッグバージョンのパスを正しいパスに置き換えます(ただし、簡単なアプローチが必要です)。

cssファイルを結合した後、この参照画像の問題をどのように解決しますか?

+0

あなたは、CSS、画像を参照する方法の例を示していることはできますか? – Louis

+0

@ルイス: '.bg-add like { \t背景画像:url( 'images/add.png'); } ' –

+0

私の場合、デバッグとリリースビルドでは、パスは常にCSSファイルの場所からの相対パスです。 – Louis

答えて

0

OKと単純なHTTPハンドラを経由してすべての画像を提供することです、私が見つかりました。解決策。画像をコピーし、リリースビルドのページのパスを置き換える代わりに、フォルダに画像を残し、cssファイルの相対パスを絶対パスに置き換えることにしました。置き換えは、replacer-scriptがcssファイルのどこに絶対パスを生成するかについての情報を持つことができるように、ファイルを結合する前に行われます。私は、これを達成するために、msbuildコミュニティタスクからScriptおよびFileUpdateタスクを使用してWeb配置プロジェクトを使用します。スクリプトタスクは、各相対パスの前に挿入する必要がある絶対URL部分を作成するために使用されます。 FileUpdateタスクは、すべての相対パスをregexを使用して絶対アナログと置き換えるために使用されます。ここで

は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") %>' 

EDITとしてそれを使用します。さらに別の代替は、このような

<%@ 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

ありがとう、もう一つの方法です。しかし、私が気に入らないのは、サーバーコントロールのためにコードビハインドでイメージパスを設定する必要があるということです。 –

+0

@ Loki、正しいのですが、1つの回避策は、<%#GetImagePath(...)#%> 'のようなデータバインディング式を使用することです - ここではページまたは適切なコンテナコントロールで' DataBind'呼び出しを呼び出します。さらに別の方法は、ハンドラ(ashx)を介してすべての画像を提供することです - 私は同じもののための初歩的なコードを置くために答えを編集しました。 – VinayC

関連する問題