11

Javascriptファイルを返すコントローラアクションがあります。私は私の見解からこのファイルを参照することができ、うまく動作します。他のJSファイルと一緒にSystem.Web.Optimization.Bundleに入れたいと思います。ASP.NET MVCコントローラアクションの結果をバンドルに追加するにはどうすればよいですか?

私は基本的に、これをやろうとしている:

new Bundle().Include("~/DynamicScript/UrlDictionary"); 

を私のバンドル内の他のファイルがうまくレンダリングしますが、これは無視されます。この動作を見ると、アプリケーションがルーティングインフラストラクチャを通じてURLを解決できるようになる前にバンドリングが処理されるか、バンドルコンポーネントが解決を可能にする方法でファイルを要求しないことが想定されます。

誰かが私のためにそれを確認したり、ここで良い方向に向いていれば、それは非常に感謝しています。

答えて

0

バンドルシステムは、アプリケーションルートではなく物理ファイルのみをサポートします。

6

私は自分の解決策に入る前にバンドルが最初のヒット時に作成され、再利用されることを覚えておいてください。つまり、ダイナミックなスクリプトはまだグローバルでなければなりません。特定のユーザーに依存するなど)。これは一般的に静的なjsファイルのみを許可する理由です。そうだと思いますが、バージョン番号などの変数を自分のjsに入れたいと思うかもしれません(その場合は、私は個人的にAjax/JSONを使用します)。

私はそれについて行く方法は、Bundleから派生型を作成することだと思います。その中で、EnumerateFilesメソッドを上書きします。最初は、base.EnumerateFilesを列挙し、独自の仮想ファイルを組み込みます。以下のような

何か(注意:コードをテストしていません):

public class VirtualMethodBundle : Bundle 
{ 
    private List<VirtualFile> _virtualContent = new List<VirtualFile>(); 

    public override IEnumerable<VirtualFile> EnumerateFiles(BundleContext context) 
    { 
     foreach(var file in base.EnumerateFiles(context)) 
     { 
      yield return file; 
     } 

     foreach(var virtual in _virtualContent) 
     { 
      yield return virtual; 
     } 
    } 

    public void AddCustomFile(VirtualFile file) 
    { 
     _virtualContent.Add(method); 
    } 
} 

次に[開く/名前のメソッドをオーバーライドして...そこのようなものを、あなたの動的なコンテンツを返す特殊なVirtualFile定義された型を持っているでしょう。

public class MethodBasedVirtualFile : VirtualFile 
{ 
    private readonly Func<string> _contentFactory; 
    private readonly string _path; 

    public MethodBasedVirtualFile(string path, Func<string> contentFactory) 
    { 
     _path = path; 
     _contentFactory = contentFactory; 
    } 

    public override string Name { get { return _path; } } 

    public override Stream Open() 
    { 
     MemoryStream stream = new MemoryStream(); 
     StreamWriter writer = new StreamWriter(stream); 
     writer.Write(_contentFactory()); 
     writer.Flush(); 
     stream.Position = 0; 
     return stream; 
    } 
} 

それでは、それをあなたが持っているでしょう、すべてを使用するように...

var bundle = new VirtualMethodBundle(); 
bundle.Include(... real files ...); 
bundle.AddCustomFile(
    new MethodBasedVirtualFile("~/DynamicScript/UrlDictionary", 
    ... the method that creates the content of that script...) 
); 

あなたは賢いした場合、あなただけのURLパスを受け取り、自動的にコンテンツを取得するためにMVCを使用していますUrlVirtualFileを作ることができます必須。

+0

あなたはEnumerateFiles()戻り値の型をオーバーライドしている、それは IEnumerableを IEnumerableをではありません。コードはコンパイルされません。 –

3

これは私がこのシナリオのためにしたものです。私は "Bundle Result"を定義し、次にControllerメソッドでBundleを名前で返しました。私はクライアントキャッシュの最適化としてETags(If-None-Match Header)を使用しています。

例:ここでは

public ActionResult ReturnFooBundle() 
{ 
    return new BundleResult("foo", TimeSpan.FromDays(7)); 
} 

がBundleResult実装です:

public class BundleResult 
    : ActionResult 
{ 
    private class BundleInfo 
    { 
     public string BundleETag; 
     public DateTime LastModified; 
     public Bundle TheBundle; 
     public BundleResponse Response; 
    } 

    private static Dictionary<string, BundleInfo> _bundleCache = new Dictionary<string, BundleInfo>(); 

    public string BundleName { get; private set; } 
    public TimeSpan CacheExpiry { get; private set; } 

    public BundleResult(string bundleName, TimeSpan cacheExpiry) 
    { 
     BundleName = bundleName; 
     CacheExpiry = cacheExpiry; 
    } 
    public override void ExecuteResult(ControllerContext context) 
    { 
     context.HttpContext.Response.Clear(); 
     BundleInfo bundleInfo = GetBundle(context.HttpContext); 

     string requestETag = context.HttpContext.Request.Headers["If-None-Match"]; 
     if (!string.IsNullOrEmpty(requestETag) && (requestETag == bundleInfo.BundleETag)) 
     { 
      context.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotModified; 
      context.HttpContext.Response.StatusDescription = "Not Modified"; 
      return; 
     } 
     else 
     { 
      BundleResponse bundleResponse = bundleInfo.Response; 
      HttpResponseBase response = context.HttpContext.Response; 
      response.Write(bundleResponse.Content); 
      response.ContentType = bundleResponse.ContentType; 

      HttpCachePolicyBase cache = response.Cache; 
      cache.SetCacheability(HttpCacheability.ServerAndPrivate); 
      cache.SetLastModified(bundleInfo.LastModified); 
      cache.SetETag(bundleInfo.BundleETag); 
     } 
    } 

    private BundleInfo GetBundle(HttpContextBase context) 
    { 
     // lookup the BundleResponse 
     BundleInfo retVal; 
     lock (_bundleCache) 
     { 
      _bundleCache.TryGetValue(BundleName, out retVal); 
     } 
     if(retVal != null) 
     { 
#if DEBUG 
      // see if the contents have been modified. 
      BundleContext bundleContext = new BundleContext(context, BundleTable.Bundles, BundleName); 
      DateTime lastModified = retVal.TheBundle.EnumerateFiles(bundleContext).Select(fi => fi.LastWriteTimeUtc).Max(); 
      if (lastModified > retVal.LastModified) 
      { 
       // regenerate the bundleInfo 
       retVal = null; 
      } 
#endif 
     } 
     if (retVal == null) 
     { 
      string rawBundleName = BundleTable.Bundles.ResolveBundleUrl(BundleName); 
      string hash = rawBundleName.Substring(rawBundleName.IndexOf("?v=") + 3); 
      Bundle bundle = BundleTable.Bundles.GetBundleFor(BundleName); 
      BundleContext bundleContext = new BundleContext(context, BundleTable.Bundles, BundleName); 
      BundleResponse bundleResponse = bundle.GenerateBundleResponse(bundleContext); 
      DateTime lastModified = bundle.EnumerateFiles(bundleContext).Select(fi => fi.LastWriteTimeUtc).Max(); 
      retVal = new BundleInfo 
      { 
       BundleETag = hash, 
       Response = bundleResponse, 
       TheBundle = bundle, 
       LastModified = lastModified, 
      }; 
      lock (_bundleCache) 
      { 
       _bundleCache[BundleName] = retVal; 
      } 
     } 
     return retVal; 
    } 
} 
関連する問題