forcer les navigateurs à obtenir les derniers fichiers js et css dans l'application asp.net

104

Certains navigateurs mettent en cache les fichiers js et css, ne les actualisant pas sauf si vous les forcez. Quel est le moyen le plus simple.

Je viens de mettre en œuvre cette solution qui semble fonctionner.

Déclarez une variable de version sur votre page

  public string version { get; set; }

Obtenez le numéro de version à partir de la clé web.config

 version = ConfigurationManager.AppSettings["versionNumber"];

Dans votre page aspx, faites les appels à javascript et aux feuilles de style comme ceci

<script src="scripts/myjavascript.js?v=<%=version %>" type="text/javascript"></script>
<link href="styles/mystyle.css?v=<%=version %>" rel="stylesheet" type="text/css" />

Donc, si vous définissez la version = 1.1 à partir de 1.0 dans votre web.config, votre navigateur téléchargera les derniers fichiers qui, espérons-le, vous éviteront, à vous et à vos utilisateurs, une certaine frustration.

Existe-t-il une autre solution qui fonctionne mieux, ou cela causera-t-il des problèmes imprévus pour un site Web?

kiev
la source
Question intéressante, j'ai eu le même problème récemment, mais ce n'était qu'un problème lors des tests de développement. Je ne m'en souciais pas trop car nous n'avons pas l'intention de modifier ces fichiers après le lancement. J'adorerais connaître une solution pour référence future!
Brett Allen
Le seul problème que je peux voir est que les modifications apportées au web.config appelleront, en arrière-plan, un redémarrage de l'application: msdn.microsoft.com/en-us/library/aa478432.aspx
monty
Merci pour la question. Cela m'a aidé à résoudre un gros problème.
Reddy

Réponses:

76

J'ai résolu ce problème en ajoutant un horodatage de la dernière modification en tant que paramètre de requête aux scripts.

Je l'ai fait avec une méthode d'extension et en l'utilisant dans mes fichiers CSHTML. Remarque: cette implémentation met en cache l'horodatage pendant 1 minute afin de ne pas trop écraser le disque.

Voici la méthode d'extension:

public static class JavascriptExtension {
    public static MvcHtmlString IncludeVersionedJs(this HtmlHelper helper, string filename) {
        string version = GetVersion(helper, filename);
        return MvcHtmlString.Create("<script type='text/javascript' src='" + filename + version + "'></script>");
    }

    private static string GetVersion(this HtmlHelper helper, string filename)
    {
        var context = helper.ViewContext.RequestContext.HttpContext;

        if (context.Cache[filename] == null)
        {
            var physicalPath = context.Server.MapPath(filename);
            var version = $"?v={new System.IO.FileInfo(physicalPath).LastWriteTime.ToString("MMddHHmmss")}";
            context.Cache.Add(filename, version, null,
              DateTime.Now.AddMinutes(5), TimeSpan.Zero,
              CacheItemPriority.Normal, null);
            return version;
        }
        else
        {
            return context.Cache[filename] as string;
        }
    }
}

Et puis dans la page CSHTML:

 @Html.IncludeVersionedJs("/MyJavascriptFile.js")

Dans le HTML rendu, cela apparaît comme:

 <script type='text/javascript' src='/MyJavascriptFile.js?20111129120000'></script>
Adam Tegen
la source
1
c'est génial pour mvc, je me demande si le dernier framework mvc 5 gère ce problème? L'approche que le regroupement utilise avec le caractère générique - {version} est également un moyen de résoudre ce problème, mais il nécessite que les fichiers soient renommés après chaque nouvelle construction ...
kiev
J'utilise les bases de votre exemple MVC dans un site Web de formulaires Web, et cela fonctionne très bien, alors merci pour le partage!
Bryan
Doit-il y avoir une raison de s'inquiéter de l'affichage de la dernière date / heure modifiée pour les fichiers de ressources? Si un fichier utilisé avait un horodatage il y a quelques années, pourrait-il y avoir des informations qu'une entreprise pourrait ne pas vouloir rendre publiques à ses utilisateurs?
Bryan
C'est la méthode standard, la plupart des applications suivent. Mais cet horodatage ne doit changer que lorsque vous déployez ou créez votre application. Sinon, chaque fois que l'utilisateur actualise la page ou passe à d'autres pages de votre application. Le navigateur téléchargera à nouveau toutes vos feuilles de style et javascript, ce qui n'est pas bon
Tarun
2
Quel est l'impact sur les performances de la page? Combien de retard peut-il entraîner pour charger la page?
Durgesh Sonawane
28

Votre solution fonctionne. C'est assez populaire en fait.

Even Stack Overflow utilise une méthode similaire:

<link rel="stylesheet" href="http://sstatic.net/so/all.css?v=6184"> 

v=6184est probablement le numéro de révision SVN.

Daniel Vassallo
la source
Ce serait une approche beaucoup plus imposante que celle décrite dans la réponse acceptée. Vérifier la version SVN du fichier chaque fois qu'une page est servie est une surcharge de performances, d'autant plus que le nombre d'utilisateurs augmente avec le temps.
Neolisk
4
Vous pouvez obtenir le numéro de révision pendant la construction, l'écrire dans un fichier (par exemple un fichier .cs partiel), inclure ce fichier dans votre projet, vous n'avez donc pas besoin de le lire depuis svn au moment de l'exécution. J'ai utilisé cette approche avec msbuild pour mettre les numéros de révision dans mes fichiers AssemblyInfo.cs de svn.
Ramazan Binarbasi
2
L'utilisation d'une version / numéro de révision globale présente au moins un inconvénient: la publication d'une mise à jour de site Web invalide les caches du navigateur pour tous les fichiers .js et .css, pas seulement ceux qui ont changé. Cela n'a probablement pas d'importance dans la majorité des applications, mais je le mentionne par souci d'exhaustivité.
Adam Tegen
Si vous mettez à jour automatiquement la version de vos fichiers assemblyinfo.cs lors d'un déploiement ou d'une génération, la version mineure peut être utilisée pour ce numéro.
kristianp
28

Dans ASP.NET Core (MVC 6), cela fonctionne directement via le asp-append-versiontag helper:

<script src="scripts/myjavascript.js" asp-append-version="true"></script>
<link href="styles/mystyle.css rel="stylesheet" asp-append-version="true" />
metalheart
la source
1
Merci de nous en informer! Je ne le savais pas avant!
Federico Navarrete
18

ASP.NET MVC gérera cela pour vous si vous utilisez des bundles pour votre JS / CSS. Il ajoutera automatiquement un numéro de version sous la forme d'un GUID à vos bundles et ne mettra à jour ce GUID que lorsque le bundle est mis à jour (c'est-à-dire que tous les fichiers source ont des changements).

Cela aide également si vous avez une tonne de fichiers JS / CSS car cela peut grandement améliorer les temps de chargement du contenu!

Vois ici

jonesy827
la source
Voulez-vous dire que si nous utilisons des bundles dans une application MVC, aucune des méthodes de la réponse publiée n'est nécessaire ici? Si tel est le cas, le regroupement est vraiment beaucoup plus important que j'aie jamais pensé. Pourriez-vous nous éclairer sur ces questions? Merci.
Jack
1
Oui, exactement. Tant que vos scripts sont inclus dans un bundle, il génère automatiquement un numéro de version pour chaque bundle lorsque des changements sont détectés dans l'un des fichiers source du bundle.
jonesy827
Et n'oubliez pas que vous avez encore des maux de tête en tant que développeur. Le regroupement ASP.NET ne facilite en rien le débogage et le développement.
it3xl
12

Il existe un moyen intégré dans asp.net pour cela: le regroupement . Utilisez-le simplement. Chaque nouvelle version aura le suffixe unique "? V = XXXXXXX". En mode débogage, le regroupement est désactivé, pour activer le paramètre make dans web.config:

<system.web>
    <compilation debug="false" />
</system.web>

Ou ajoutez à la méthode RegisterBundles (BundleCollection bundles):

BundleTable.EnableOptimizations = true;

Par exemple:

BundleConfig.cs:

bundles.Add(new ScriptBundle("~/Scripts/myjavascript.js")
                .Include("~/Scripts/myjavascript.js"));

bundles.Add(new StyleBundle("~/Content/mystyle.css")
                .Include("~/Content/mystyle.css"));

_Layout.cshtml:

@Scripts.Render("~/Scripts/myjavascript.js")
@Styles.Render("~/Content/mystyle.css")
Alex Tkachuk
la source
Mais cela ne fonctionnera que dans les environnements de sortie ou de production. Qu'en est-il du développement lorsque le mode débogage est activé? Le bundle résout-il toujours ce problème?
VAAA
Oui, bundlind ne facilite pas la vie des développeurs. Vous devez appuyer sur Ctrl-F5 après chaque changement de script. Et si vous avez des cadres, ce sera encore plus drôle.
it3xl
7

Il y a une réponse plus simple à cela que la réponse donnée par l'op dans la question (l'approche est la même):

Définissez la clé dans le web.config:

<add key="VersionNumber" value="06032014"/>

Faites l'appel à appsettings directement depuis la page aspx:

<link href="styles/navigation.css?v=<%=ConfigurationManager.AppSettings["VersionNumber"]%>" rel="stylesheet" type="text/css" />
JackArbiter
la source
J'aime cela, mais je m'inquiète de savoir pourquoi cette solution a si peu de votes ...
SimplyInk
@SimplyInk Je ne sais pas, mais il y a 20 réponses différentes, donc cela pourrait avoir quelque chose à voir avec ça. Si cela fonctionne et que vous l'aimez, n'hésitez pas à le voter.
JackArbiter
4

Basé sur la réponse d'Adam Tegan , modifiée pour une utilisation dans une application de formulaires Web.

Dans le code de classe .cs:

public static class FileUtility
{
    public static string SetJsVersion(HttpContext context, string filename) {
        string version = GetJsFileVersion(context, filename);
        return filename + version;
    }

    private static string GetJsFileVersion(HttpContext context, string filename)
    {
        if (context.Cache[filename] == null)
        {
            string filePhysicalPath = context.Server.MapPath(filename);

            string version = "?v=" + GetFileLastModifiedDateTime(context, filePhysicalPath, "yyyyMMddhhmmss");

            return version;
        }
        else
        {
            return string.Empty;
        }
    }

    public static string GetFileLastModifiedDateTime(HttpContext context, string filePath, string dateFormat)
    {
        return new System.IO.FileInfo(filePath).LastWriteTime.ToString(dateFormat);
    }
}

Dans le balisage aspx:

<script type="text/javascript" src='<%= FileUtility.SetJsVersion(Context,"/js/exampleJavaScriptFile.js") %>'></script>

Et dans le HTML rendu, il apparaît comme

<script type="text/javascript" src='/js/exampleJavaScriptFile.js?v=20150402021544'></script>
Bryan
la source
2
Hey! Votre exemple fonctionne, mais vous devez soit supprimer les références de mise en cache, soit corriger le code pour utiliser le cache, car il peut être difficile de savoir pourquoi vous l'utilisez. Pour utiliser le cache, vous devez ajouter la version du fichier au cache en utilisant la méthode context.Cache.Add dans le cas context.Cache [filename] == null. Si context.Cache [filename]! = Null, vous devez renvoyer la valeur mise en cache (context.Cache [filename])
Flavia Obreja
1
Flavia, je pense que votre explication a du sens, et je pense que c'est une implémentation plus simple et plus efficace. Merci d'avoir publié les commentaires et commentaires utiles.
Bryan
4

Fait intéressant, ce site même a des problèmes avec l'approche que vous décrivez en relation avec certaines configurations de proxy, même s'il devrait être à sécurité intégrée.

Consultez cette discussion Meta Stack Overflow .

Donc, à la lumière de cela, il peut être judicieux de ne pas utiliser un paramètre GET pour mettre à jour, mais le nom du fichier réel:

href="/css/scriptname/versionNumber.css" 

même si c'est plus de travail à faire, car vous devrez créer le fichier ou créer une réécriture d'URL pour celui-ci.

Pekka 웃
la source
4

Je voulais une simple doublure pour rendre le chemin unique pour casser la cache. Cela a fonctionné pour moi:

<script src="scripts/main.js?bust_js_cache=<%=System.IO.File.GetLastWriteTime(Server.MapPath("scripts/main.js")).ToString("HH:mm:ss")%>" type="text/javascript"></script>

Si le fichier a été modifié depuis la dernière fois qu'il a été chargé sur la page, le navigateur extraira le fichier mis à jour.

Il génère le last modifiedtampon à partir du .jsfichier et le place là-dedans au lieu de la version à laquelle il peut ne pas être facile d'accéder.

<script src="scripts/main.js?bust_js_cache=10:18:38" type="text/javascript"></script>

Une autre option pourrait être d'obtenir la somme de contrôle du fichier.

sniperd
la source
1
De loin la façon la plus simple de le faire, et probablement la plus faible surcharge.
Tony Hinkle
1
Solution parfaite. J'ai également testé Chrome 70, Firefox 63 et IE 11 pour m'assurer que la mise en cache fonctionnait réellement. C'est. Cela ne supprime la mise en cache que sur les nouvelles versions du fichier, du moins sur les dernières versions des navigateurs. J'ai entendu dire ailleurs que certains navigateurs rechargent chaque fichier avec une chaîne de requête (?). Peut-être que c'était le cas auparavant ou peut-être que c'est toujours vrai avec Safari et Opera. DK.
Brad Mathews
3

Voici une approche qui fonctionne avec ASP.NET 5 / MVC 6 / vNext .

Étape 1: Créez une classe pour renvoyer la dernière heure d'écriture du fichier, similaire aux autres réponses de ce fil. Notez que cela nécessite une injection de dépendances ASP.NET 5 (ou autre).

public class FileVersionService
{
    private IHostingEnvironment _hostingEnvironment;
    public FileVersionService(IHostingEnvironment hostingEnvironment)
    {
        _hostingEnvironment = hostingEnvironment;
    }

    public string GetFileVersion(string filename)
    {
       var path = string.Format("{0}{1}", _hostingEnvironment.WebRootPath, filename);
       var fileInfo = new FileInfo(path);
       var version = fileInfo.LastWriteTimeUtc.ToString("yyyyMMddhhmmssfff");
       return version;
     }
}

Étape 2: Enregistrez le service à injecter dans startup.cs :

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddScoped<FileVersionService>();
    ...
}

Étape 3: Ensuite, dans ASP.NET 5, il est possible d'injecter le service directement dans une vue de mise en page telle que _Layout.cshtml comme ceci:

@inject Namespace.Here.FileVersionService fileVersionService
<!DOCTYPE html>
<html lang="en" class="@ViewBag.HtmlClass">
<head>
    ...
    <link href="/css/[email protected]("\\css\\styles.css")" rel="stylesheet" />
    ...
</head>
<body>
    ...
</body>

Certaines touches finales pourraient être apportées pour mieux combiner les chemins physiques et gérer le nom du fichier dans un style plus cohérent avec la syntaxe, mais c'est un point de départ. J'espère que cela aidera les gens à passer à ASP.NET 5.

Ender2050
la source
ce comportement est en fait pris en charge hors de la boîte, voir ma réponse
metalheart
3

J'ai utilisé une technique légèrement différente dans mon site aspnet MVC 4:

_ViewStart.cshtml:

@using System.Web.Caching
@using System.Web.Hosting
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    PageData.Add("scriptFormat", string.Format("<script src=\"{{0}}?_={0}\"></script>", GetDeployTicks()));
}

@functions
{

    private static string GetDeployTicks()
    {
        const string cacheKey = "DeployTicks";
        var returnValue = HttpRuntime.Cache[cacheKey] as string;
        if (null == returnValue)
        {
            var absolute = HostingEnvironment.MapPath("~/Web.config");
            returnValue = File.GetLastWriteTime(absolute).Ticks.ToString();
            HttpRuntime.Cache.Insert(cacheKey, returnValue, new CacheDependency(absolute));
        }
        return returnValue;
    }
}

Puis dans les vues réelles:

 @Scripts.RenderFormat(PageData["scriptFormat"], "~/Scripts/Search/javascriptFile.min.js")
Anthony Wolfe
la source
3

<?php $rand_no = rand(10000000, 99999999)?> <script src="scripts/myjavascript.js?v=<?=$rand_no"></script>

Cela fonctionne pour moi dans tous les navigateurs. Ici, j'ai utilisé PHP pour générer des non aléatoires. Vous pouvez utiliser votre propre langue côté serveur. »

Mukesh Rai
la source
Bonne réponse, mais ASP MVC peut être un peu problématique si vous ne tenez pas compte de ce qu'Adam a expliqué car je l'ai essayé et le dossier Bundle ne le reconnaît pas si vous travaillez avec MVC 5. Mais merci pour la suggestion!
Federico Navarrete le
2

À partir de la réponse ci - dessus, j'ai modifié un peu le code pour que l'assistant fonctionne également avec les fichiers CSS et ajoute une version à chaque fois que vous modifiez les fichiers et pas seulement lorsque vous faites la construction

public static class HtmlHelperExtensions
{
    public static MvcHtmlString IncludeVersionedJs(this HtmlHelper helper, string filename)
    {
        string version = GetVersion(helper, filename);
        return MvcHtmlString.Create("<script type='text/javascript' src='" + filename + version + "'></script>");
    }

    public static MvcHtmlString IncludeVersionedCss(this HtmlHelper helper, string filename)
    {
        string version = GetVersion(helper, filename);
        return MvcHtmlString.Create("<link href='" + filename + version + "' type ='text/css' rel='stylesheet'/>");
    }

    private static string GetVersion(this HtmlHelper helper, string filename)
    {
        var context = helper.ViewContext.RequestContext.HttpContext;
        var physicalPath = context.Server.MapPath(filename);
        var version = "?v=" +
        new System.IO.FileInfo(physicalPath).LastWriteTime
        .ToString("yyyyMMddHHmmss");
        context.Cache.Add(physicalPath, version, null,
          DateTime.Now.AddMinutes(1), TimeSpan.Zero,
          CacheItemPriority.Normal, null);

        if (context.Cache[filename] == null)
        {
            context.Cache[filename] = version;
            return version;
        }
        else
        {
            if (version != context.Cache[filename].ToString())
            {
                context.Cache[filename] = version;
                return version;
            }
            return context.Cache[filename] as string;
        }
    }
}
Sergi Mulà
la source
1

Obtenir l'heure de modification du fichier, comme indiqué ci-dessous

private static string GetLastWriteTimeForFile(string pathVal)
    {
        return System.IO.File.GetLastWriteTime(HostingEnvironment.MapPath(pathVal)).ToFileTime().ToString();
    }

Ajoutez ceci avec l'entrée en tant que chaîne de requête

public static string AppendDateInFile(string pathVal)
    {
        var patheWithDate = new StringBuilder(pathVal);
        patheWithDate.AppendFormat("{0}x={1}",
                               pathVal.IndexOf('?') >= 0 ? '&' : '?',
                               GetLastWriteTimeForFile(pathVal));
        return patheWithDate.ToString();
    }

Appelez cela à partir du balisage.

Approche MVC Extension Helper

Ajouter une méthode d'extension

namespace TNS.Portal.Helpers
{
    public static class ScriptExtensions
    {
        public static HtmlString QueryStringScript<T>(this HtmlHelper<T> html, string path)
        {
            var file = html.ViewContext.HttpContext.Server.MapPath(path);
            DateTime lastModified = File.GetLastWriteTime(file);
            TagBuilder builder = new TagBuilder("script");
            builder.Attributes["src"] = path + "?modified=" + lastModified.ToString("yyyyMMddhhmmss");
            return new HtmlString(builder.ToString());
        }

       public static HtmlString QueryStringStylesheet<T>(this HtmlHelper<T> html, string path)
       {
        var file = html.ViewContext.HttpContext.Server.MapPath(path);
        DateTime lastModified = File.GetLastWriteTime(file);
        TagBuilder builder = new TagBuilder("link");
        builder.Attributes["href"] = path + "?modified=" + lastModified.ToString("yyyyMMddhhmmss");
        builder.Attributes["rel"] = "stylesheet";
        return new HtmlString(builder.ToString());
      }

    }
}

Ajouter cet espace de noms dans web.config

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="TNS.Portal" />
        <add namespace="TNS.Portal.Helpers" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

Utilisez-le dans la vue comme

@Html.QueryStringScript("/Scripts/NPIAjaxCalls.js")
@Html.QueryStringStylesheet("/Content/StyledRadio.css")
Lijo
la source
1

Suggestions préalables simplifiées et fourniture de code pour les développeurs .NET Web Forms.

Cela acceptera les URL relatives ("~ /") et absolues dans le chemin du fichier vers la ressource.

Mettez dans un fichier de classe d'extensions statiques, ce qui suit:

public static string VersionedContent(this HttpContext httpContext, string virtualFilePath)
{
    var physicalFilePath = httpContext.Server.MapPath(virtualFilePath);
    if (httpContext.Cache[physicalFilePath] == null)
    {
        httpContext.Cache[physicalFilePath] = ((Page)httpContext.CurrentHandler).ResolveUrl(virtualFilePath) + (virtualFilePath.Contains("?") ? "&" : "?") + "v=" + File.GetLastWriteTime(physicalFilePath).ToString("yyyyMMddHHmmss");
    }
    return (string)httpContext.Cache[physicalFilePath];
}

Et puis appelez-le dans votre page maître comme tel:

<link type="text/css" rel="stylesheet" href="<%= Context.VersionedContent("~/styles/mystyle.css") %>" />
<script type="text/javascript" src="<%= Context.VersionedContent("~/scripts/myjavascript.js") %>"></script>
Jason Ellingson
la source
Belle approche aussi!
Federico Navarrete
0

Sur la base de la réponse ci-dessus, j'ai écrit une petite classe d'extension pour travailler avec les fichiers CSS et JS:

public static class TimestampedContentExtensions
{
    public static string VersionedContent(this UrlHelper helper, string contentPath)
    {
        var context = helper.RequestContext.HttpContext;

        if (context.Cache[contentPath] == null)
        {
            var physicalPath = context.Server.MapPath(contentPath);
            var version = @"v=" + new FileInfo(physicalPath).LastWriteTime.ToString(@"yyyyMMddHHmmss");

            var translatedContentPath = helper.Content(contentPath);

            var versionedContentPath =
                contentPath.Contains(@"?")
                    ? translatedContentPath + @"&" + version
                    : translatedContentPath + @"?" + version;

            context.Cache.Add(physicalPath, version, null, DateTime.Now.AddMinutes(1), TimeSpan.Zero,
                CacheItemPriority.Normal, null);

            context.Cache[contentPath] = versionedContentPath;
            return versionedContentPath;
        }
        else
        {
            return context.Cache[contentPath] as string;
        }
    }
}

Au lieu d'écrire quelque chose comme:

<link href="@Url.Content(@"~/Content/bootstrap.min.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content(@"~/Scripts/bootstrap.min.js")"></script>

Vous pouvez maintenant écrire:

<link href="@Url.VersionedContent(@"~/Content/bootstrap.min.css")" rel="stylesheet" type="text/css" />
<script src="@Url.VersionedContent(@"~/Scripts/bootstrap.min.js")"></script>

Ie simplement remplacer Url.Contentpar Url.VersionedContent.

Les URL générées ressemblent à ceci:

<link href="/Content/bootstrap.min.css?v=20151104105858" rel="stylesheet" type="text/css" />
<script src="/Scripts/bootstrap.min.js?v=20151029213517"></script>

Si vous utilisez la classe d'extension, vous souhaiterez peut-être ajouter une gestion des erreurs au cas où l' MapPathappel ne fonctionnerait pas, car il contentPathne s'agit pas d'un fichier physique.

Uwe Keim
la source
0

J'utilise une manière similaire de faire la même chose que vous faites sans modifier chaque page. Ajout d'un événement PreRender dans le fichier maître. Il maintient ma logique au même endroit et s'applique aux fichiers js et css.

protected void Page_PreRender(object sender, EventArgs e)
    {
        HtmlLink link = null;
        LiteralControl script = null;


        foreach (Control c in Header.Controls)
        {
            //StyleSheet add version
            if (c is HtmlLink)
            {
                link = c as HtmlLink;


                if (link.Href.EndsWith(".css", StringComparison.InvariantCultureIgnoreCase))
                {
                    link.Href += string.Format("?v={0}", ConfigurationManager.AppSettings["agVersion"]);
                }

            }

            //Js add version
            if (c is LiteralControl)
            {
                script = c as LiteralControl;

                if (script.Text.Contains(".js"))
                {
                    var foundIndexes = new List<int>();


                    for (int i = script.Text.IndexOf(".js\""); i > -1; i = script.Text.IndexOf(".js\"", i + 1))
                    {

                        foundIndexes.Add(i);
                    }

                    for (int i = foundIndexes.Count - 1; i >= 0; i--)
                    {

                        script.Text = script.Text.Insert(foundIndexes[i] + 3, string.Format("?v={0}", ConfigurationManager.AppSettings["agVersion"]));
                    }
                }

            }

        }
    }
Geai
la source
0

Vous pouvez remplacer la propriété DefaultTagFormat des scripts ou des styles.

Scripts.DefaultTagFormat = @"<script src=""{0}?v=" + ConfigurationManager.AppSettings["pubversion"] + @"""></script>";
Styles.DefaultTagFormat = @"<link href=""{0}?v=" + ConfigurationManager.AppSettings["pubversion"] + @""" rel=""stylesheet""/>";
phénix
la source
0

Pour résoudre ce problème dans mon application ASP.Net Ajax, j'ai créé une extension, puis j'ai appelé dans la page maître.

Pour plus de détails, vous pouvez passer par le lien .

Kasim Husaini
la source
0

Un moyen simple et intelligent d'implémenter le contrôle de version css dans l'application .net par le concept ci-dessous .. pas besoin d'écrire du code back-end.

<link href="<%="../../App_Themes/Base/css/main.css?v="+ DateTime.Now.ToString("yyyyMMddhhmmss") +""%>" rel="stylesheet" />
SantoshK
la source
cela forcera le téléchargement dans chaque rendu de page, même si les fichiers n'ont pas du tout changé.
Thanasis Ioannidis le
@ThanasisIoannidis Il peut utiliser les fichiers où les fichiers sont modifiés régulièrement. une autre option est d'ajouter la clé appVersion dans web.config et de l'utiliser avec le nom des fichiers .. mais vous devez mettre à jour lorsque vous lancez l'application pour prod.
SantoshK
-1

Le principal problème avec cette méthode est principalement que vous devrez vous rappeler de mettre à jour votre numéro de version dans votre code chaque fois que vous apportez des modifications à vos fichiers css ou js.

Une meilleure façon de le faire est de définir un paramètre unique garanti avec chacun de vos fichiers css ou js, comme ceci:

<script src="scripts/myjavascript.js?_=<%=DateTime.Now.Ticks%>" type="text/javascript"></script>
<link href="styles/mystyle.css?_=<%=DateTime.Now.Ticks%>" rel="stylesheet" type="text/css" />

Cela oblige les fichiers à être demandés au serveur à chaque fois, ce qui signifie également que votre site ne sera pas aussi performant lors du chargement de la page, car ces fichiers ne seront jamais mis en cache et utiliseront à chaque fois une bande passante inutile.

Essentiellement, si vous vous souvenez de mettre à jour le numéro de version chaque fois qu'une modification est apportée, vous pouvez vous en sortir avec la façon dont vous le faites.

Tim S. Van Haren
la source
9
et utilise également de grandes quantités de bande passante.
Darren Kopp
2
Bon, vous ne voulez pas une nouvelle version du JS à chaque chargement de page ... vous voulez juste que le navigateur recherche une nouvelle version chaque fois que vous avez réellement une version mise à jour.
kingdango
Ceci est parfaitement acceptable pour une solution temporaire sur un fichier css de 50 Ko pendant le développement. +1
Colbs
-2

Pour les pages ASP.NET, j'utilise les éléments suivants

AVANT

<script src="/Scripts/pages/common.js" type="text/javascript"></script>

APRÈS (rechargement forcé)

 <script src="/Scripts/pages/common.js?ver<%=DateTime.Now.Ticks.ToString()%>" type="text/javascript"></script>

L'ajout de DateTime.Now.Ticks fonctionne très bien.

Ravi Ram
la source
oui, le problème concerne la bande passante - comme dans les commentaires ci-dessus stackoverflow.com/a/2185918/59508
kiev