2014-05-22 12 views
12

Ho appena inseguito un bug che era dovuto a un file javascript mancante, stava fallendo silenziosamente.Asp.Net MVC Bundling, il modo migliore per rilevare il file mancante

La versione minificata del file era presente ma non la versione completa, un collegamento non è reso sul client (cosa che mi aspettavo) ma non ottengo neanche un'eccezione. Mi piacerebbe sapere se il file non è presente.

(tanto per essere chiari, il fascio non ha cercato di incluso nella versione minified, si è cercato di includere la versione completa, ma la versione minified era presente nella directory di script)

Devo scrivere qualcosa di personalizzato per rilevare questo o MVC ha qualcosa di costruito per segnalare questo?

grazie

+0

Quale collegamento non è stato reso sul client? Il punto di raggruppamento è ridurre il numero di file, in modo da ottenere un solo file per bundle sul client, a meno che non si attivi la modalità di diagnostica con 'BundleTable.EnableOptimizations = false;'. Con questa impostazione puoi visualizzare le richieste con Fiddler2 e vedere gli script mancanti. –

+0

Prova questo http://stackoverflow.com/questions/20869907/. Il punto è che non dovresti avere la versione minificata. Almeno quello, senza '.min.js'.Per quanto ne so, il bundling runtime ** mai ** usa il min, lo fa sempre minifingando il suo –

+0

Radim, grazie ma non è quello che dice il link, "... verrà cercato, e se non trovato, il corrente verrà ridotta ", suggerendo che se è presente verrà utilizzato – tony

risposta

23

mi è venuta a utilizzare i seguenti metodi di estensione per Bundle:

public static class BundleHelper 
{ 
    [Conditional("DEBUG")] // remove this attribute to validate bundles in production too 
    private static void CheckExistence(string virtualPath) 
    { 
     int i = virtualPath.LastIndexOf('/'); 
     string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i)); 
     string fileName = virtualPath.Substring(i + 1); 

     bool found = Directory.Exists(path); 

     if (found) 
     { 
      if (fileName.Contains("{version}")) 
      { 
       var re = new Regex(fileName.Replace(".", @"\.").Replace("{version}", @"(\d+(?:\.\d+){1,3})")); 
       fileName = fileName.Replace("{version}", "*"); 
       found = Directory.EnumerateFiles(path, fileName).FirstOrDefault(file => re.IsMatch(file)) != null; 
      } 
      else // fileName may contain '*' 
       found = Directory.EnumerateFiles(path, fileName).FirstOrDefault() != null; 
     } 

     if (!found) 
      throw new ApplicationException(String.Format("Bundle resource '{0}' not found", virtualPath)); 
    } 

    public static Bundle IncludeExisting(this Bundle bundle, params string[] virtualPaths) 
    { 
     foreach (string virtualPath in virtualPaths) 
      CheckExistence(virtualPath); 

     return bundle.Include(virtualPaths); 
    } 

    public static Bundle IncludeExisting(this Bundle bundle, string virtualPath, params IItemTransform[] transforms) 
    { 
     CheckExistence(virtualPath); 
     return bundle.Include(virtualPath, transforms); 
    } 
} 

In questo modo non c'è bisogno di chiamare il metodo di supporto PreCheck() esplicitamente. Supporta anche i caratteri jolly di ASP.NET {version} e *:

bundles.Add(new ScriptBundle("~/test") 
    .IncludeExisting("~/Scripts/jquery/jquery-{version}.js") 
    .IncludeExisting("~/Scripts/lib*") 
    .IncludeExisting("~/Scripts/model.js") 
    ); 
+0

Cose utili! Una nota: è possibile sostituire 'Dove (file => re.IsMatch (file)). FirstOrDefault()' con 'FirstOrDefault (file => re.IsMatch (file))' – user1068352

0

Non posso credere che questo "anti-modello" esiste! Se non vedi errori, non ci sono errori!

In ogni caso, mi piace la soluzione di cui sopra. Un altro sarebbe l'output del link/script anche se manca quando BundleTable.EnableOptimizations è falso - questa è una cosa molto ovvia da provare durante il debug, e quindi sarà ovvio nei vari ispettori/debugger sui browser che il file è mancante. Sembrava una cosa così ovvia per il debugging che ho passato ore senza rendermi conto che mancavano i file. L'altro modo, ignorando in silenzio le parti mancanti del pacchetto, è così sbagliato che ha rafforzato la mia orribile sessione di debug.

Bene, questo non mi morderà due volte - il trauma dura.

0

Ho cambiato il codice un po '. Invece di lanciare un errore, non aggiungerà alcun file bundle. questo è necessario se si utilizza lo stesso config comune bundle per più progetti

public static class BundleHelper 
{ 
    private static bool CheckExistence(string virtualPath) 
    { 
     int i = virtualPath.LastIndexOf('/'); 
     string path = HostingEnvironment.MapPath(virtualPath.Substring(0, i)); 
     string fileName = virtualPath.Substring(i + 1); 

     bool found = Directory.Exists(path); 

     if (found) 
     { 
      if (fileName.Contains("{version}")) 
      { 
       var re = new Regex(fileName.Replace(".", @"\.").Replace("{version}", @"(\d+(?:\.\d+){1,3})")); 
       fileName = fileName.Replace("{version}", "*"); 
       found = Directory.EnumerateFiles(path, fileName).Where(file => re.IsMatch(file)).FirstOrDefault() != null; 
      } 
      else // fileName may contain '*' 
       found = Directory.EnumerateFiles(path, fileName).FirstOrDefault() != null; 
     } 
     return found; 
     //if (!found) 
     //throw new ApplicationException(String.Format("Bundle resource '{0}' not found", virtualPath)); 
    } 

    public static Bundle IncludeExisting(this Bundle bundle, params string[] virtualPaths) 
    { 
     foreach (string virtualPath in virtualPaths) 
      if (CheckExistence(virtualPath)) 
      { 
       bundle.Include(virtualPath); 
      } 

     return bundle; 
    } 

    public static Bundle IncludeExisting(this Bundle bundle, string virtualPath, params IItemTransform[] transforms) 
    { 
     if (CheckExistence(virtualPath)) 
      bundle.Include(virtualPath, transforms); 
     return bundle; 
    } 
} 
1

Un altro modo con BundleTable.VirtualPathProvider avvolgitore:

public class VirtualPathProviderExt : VirtualPathProvider 
{ 
    private readonly VirtualPathProvider _provider; 

    public VirtualPathProviderExt(VirtualPathProvider provider) 
    { 
     _provider = provider; 
    } 

    public override string CombineVirtualPaths(string basePath, string relativePath) 
    { 
     return _provider.CombineVirtualPaths(basePath, relativePath); 
    } 

    public override ObjRef CreateObjRef(Type requestedType) 
    { 
     return _provider.CreateObjRef(requestedType); 
    } 

    public override bool DirectoryExists(string virtualDir) 
    { 
     return _provider.DirectoryExists(virtualDir); 
    } 

    public override bool Equals(object obj) 
    { 
     return _provider.Equals(obj); 
    } 

    private static readonly Regex _ignorePathsRegex = new Regex(@"\.debug\.\w+$|^~/bundle.config$", RegexOptions.IgnoreCase | RegexOptions.Compiled); 

    public override bool FileExists(string virtualPath) 
    { 
     var result = _provider.FileExists(virtualPath); 
     if (!result && !_ignorePathsRegex.IsMatch(virtualPath)) 
     { 
      Logger.Instance.Log(RecType.Error, "Bundle file not found: " + virtualPath); 
     } 

     return result; 
    } 

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) 
    { 
     return _provider.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart); 
    } 

    public override string GetCacheKey(string virtualPath) 
    { 
     return _provider.GetCacheKey(virtualPath); 
    } 

    public override VirtualDirectory GetDirectory(string virtualDir) 
    { 
     return _provider.GetDirectory(virtualDir); 
    } 

    public override VirtualFile GetFile(string virtualPath) 
    { 
     return _provider.GetFile(virtualPath); 
    } 

    public override string GetFileHash(string virtualPath, IEnumerable virtualPathDependencies) 
    { 
     return _provider.GetFileHash(virtualPath, virtualPathDependencies); 
    } 

    public override int GetHashCode() 
    { 
     return _provider.GetHashCode(); 
    } 

    public override object InitializeLifetimeService() 
    { 
     return _provider.InitializeLifetimeService(); 
    } 

    public override string ToString() 
    { 
     return _provider.ToString(); 
    } 
} 

Bundle aiutante:

public static class BundleHelpers 
{ 
    public static void InitBundles() 
    { 
     if (!(BundleTable.VirtualPathProvider is VirtualPathProviderExt)) 
     { 
      BundleTable.VirtualPathProvider = new VirtualPathProviderExt(BundleTable.VirtualPathProvider); 
     } 
    } 
} 

Ed eseguire BundleHelpers.InitBundles() in BundleConfig.cs:

public class BundleConfig 
{ 
    public static void RegisterBundles(BundleCollection bundles) 
    { 
     BundleHelpers.InitBundles(); 
     ... 
Problemi correlati