5

いくつかの画像を提供するIHttpHandlerASP.NET があります。ハンドラーは、次の方法で ETAG を設定します。

context.Response.AddFileDependency(filename);                
context.Response.Cache.SetLastModifiedFromFileDependencies();
context.Response.Cache.SetETagFromFileDependencies();
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(new TimeSpan(999,0,0,0));
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetValidUntilExpires(true);                
context.Response.Cache.VaryByParams["*"] = true;
byte[] buffer = File.ReadAllBytes(filename);
context.Response.ContentType = MimeMapping.GetMimeMapping(mi.Mi_filename);
context.Response.StatusCode = 200;
context.Response.BinaryWrite(buffer);

System.Web.HttpExceptionIIS7 で次のような例外が発生することがあります。

依存関係から etag を生成できません。依存関係の 1 つで一意の ID を生成できませんでした。

しかし、問題を再現することはできません (ASP.NET 内部テスト Web サーバーでこれをテストできないことはわかっています)。なぜこれが起こるのか、これを防ぐために何ができるのか、誰にも手がかりがありますか?

4

2 に答える 2

7

なぜこれが起こるのか説明することはできませんが、スレッドを非常に短い時間だけスリープ状態にすることで、ファイル依存関係マネージャーが「うまくまとまり」、新しく生成されたファイルが実際に存在することを確認してから、そこから eTag を作成します。

...<code to generate "filename" goes here>...

// BUG: For some reason, even though the cache file has definitely been created at this stage, the file dependency manager
// seems to require a bit of time to "register" that the file exists before we add it to the list of dependencies.
// If we don't tell the thread to sleep, we will get an error when it generates the eTag (no idea why this happens - can't find anything on the web).
// If the cache file already existed when this request began, then there is no error.
Thread.Sleep(5);
context.Response.AddFileDependency(filename);                
context.Response.Cache.SetLastModifiedFromFileDependencies();
context.Response.Cache.SetETagFromFileDependencies();
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(new TimeSpan(999,0,0,0));
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetValidUntilExpires(true);                
context.Response.Cache.VaryByParams["*"] = true;
byte[] buffer = File.ReadAllBytes(filename);
context.Response.ContentType = MimeMapping.GetMimeMapping(mi.Mi_filename);
context.Response.StatusCode = 200;
context.Response.BinaryWrite(buffer);
于 2014-01-13T13:12:09.650 に答える