forzar a los navegadores a obtener los archivos js y css más recientes en la aplicación asp.net

104

Algunos navegadores almacenan en caché archivos js y css, y no los actualizan a menos que los fuerce. Cuál es la forma más fácil.

Acabo de implementar esta solución que parece funcionar.

Declare una variable de versión en su página

  public string version { get; set; }

Obtenga el número de versión de la clave web.config

 version = ConfigurationManager.AppSettings["versionNumber"];

En su página aspx, realice las llamadas a javascript y hojas de estilo como tal

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

Por lo tanto, si configura la versión = 1.1 desde 1.0 en su web.config, su navegador descargará los archivos más recientes que, con suerte, le ahorrarán a usted y a sus usuarios algo de frustración.

¿Existe otra solución que funcione mejor o esto causará problemas imprevistos en un sitio web?

kiev
fuente
Pregunta interesante, tuve el mismo problema recientemente, pero solo fue un problema durante las pruebas de desarrollo. No me importó mucho, ya que no tenemos la intención de cambiar esos archivos después del lanzamiento. ¡Me encantaría saber una solución para futuras referencias!
Brett Allen
El único problema que veo es que los cambios en el web.config serán, en el fondo, llame a un reinicio de la aplicación: msdn.microsoft.com/en-us/library/aa478432.aspx
Monty
Gracias por la pregunta. Esto me ayudó a resolver un gran problema.
Reddy

Respuestas:

76

Resolví esto agregando una última marca de tiempo modificada como parámetro de consulta para los scripts.

Hice esto con un método de extensión y lo usé en mis archivos CSHTML. Nota: esta implementación almacena en caché la marca de tiempo durante 1 minuto, por lo que no destruimos tanto el disco.

Aquí está el método de extensión:

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;
        }
    }
}

Y luego en la página CSHTML:

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

En el HTML renderizado, esto aparece como:

 <script type='text/javascript' src='/MyJavascriptFile.js?20111129120000'></script>
Adam Tegen
fuente
1
esto es genial para mvc, me pregunto si el último marco mvc 5 maneja este problema. El enfoque que utiliza la agrupación con el comodín - {versión} también es una forma de resolver este problema, sin embargo, requiere que se cambie el nombre de los archivos después de cada nueva compilación ...
kiev
Estoy usando los conceptos básicos de su ejemplo MVC en un sitio web de formularios web y está funcionando muy bien, ¡así que gracias por compartir!
Bryan
¿Debería haber alguna razón para preocuparse por mostrar la última marca de fecha / hora modificada para archivos de recursos? Si un archivo que se está utilizando tiene una marca de fecha / hora hace algunos años, ¿podría ser información que una empresa no quiera que sea pública para sus usuarios?
Bryan
Es la forma estándar, la mayoría de las aplicaciones sigue. Pero esa marca de tiempo debe cambiar solo cuando implemente o compile su aplicación. De lo contrario, cada vez que el usuario actualice la página o cambie a otras páginas de su aplicación. El navegador descargará todas sus hojas de estilo y javascript nuevamente, lo cual no es bueno
Tarun
2
¿Cuál es el impacto en el rendimiento de la página? ¿Cuánto retraso puede causar la carga de la página?
Durgesh Sonawane
28

Tu solución funciona. De hecho, es bastante popular.

Incluso Stack Overflow usa un método similar:

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

¿Dónde v=6184está probablemente el número de revisión SVN?

Daniel Vassallo
fuente
Este sería un enfoque mucho más exigente que el descrito en la respuesta aceptada. Verificar la versión SVN del archivo cada vez que se publica una página es una sobrecarga de rendimiento, especialmente a medida que el número de usuarios aumenta con el tiempo.
Neolisk
4
Puede obtener el número de revisión durante la compilación, escribirlo en un archivo (por ejemplo, archivo .cs parcial), incluir ese archivo en su proyecto, por lo que no es necesario leerlo desde svn en tiempo de ejecución. He usado este enfoque con msbuild para poner números de revisión en mis archivos AssemblyInfo.cs de svn.
Ramazan Binarbasi
2
El uso de una versión / número de revisión global tiene al menos un inconveniente: la publicación de una actualización del sitio web invalida las cachés del navegador para todos los archivos .js y .css, no solo para los que cambiaron. Esto probablemente no importe en la mayoría de las aplicaciones, pero lo menciono para completarlo.
Adam Tegen
Si actualiza la versión de sus archivos assemblyinfo.cs automáticamente durante una implementación o compilación, la versión secundaria podría usarse para ese número.
kristianp
28

En ASP.NET Core (MVC 6), esto funciona de inmediato a través del asp-append-versionasistente de etiquetas:

<script src="scripts/myjavascript.js" asp-append-version="true"></script>
<link href="styles/mystyle.css rel="stylesheet" asp-append-version="true" />
metalheart
fuente
1
¡Gracias por dejarnos saber! ¡No lo sabía antes!
Federico Navarrete
18

ASP.NET MVC se encargará de esto por usted si usa paquetes para su JS / CSS. Agregará automáticamente un número de versión en forma de GUID a sus paquetes y solo actualizará este GUID cuando el paquete se actualice (también conocido como cualquiera de los archivos de origen tiene cambios).

Esto también ayuda si tiene una tonelada de archivos JS / CSS, ya que puede mejorar en gran medida los tiempos de carga de contenido.

Mira aquí

jonesy827
fuente
¿Quiere decir que si usamos paquetes en una aplicación MVC, no es necesario ninguno de los métodos en la respuesta publicada aquí? Si es así, la agrupación es mucho más importante de lo que jamás había pensado. ¿Podría aclararnos este problema? Gracias.
Jack
1
Sí exactamente. Siempre que sus scripts estén incluidos en un paquete, generará un número de versión automáticamente para cada paquete cuando se detecten cambios en cualquiera de los archivos fuente del paquete.
jonesy827
Y no olvide que todavía tiene dolores de cabeza como desarrollador. El paquete ASP.NET no ayuda de ninguna manera durante la depuración y el desarrollo.
it3xl
12

Hay una forma incorporada en asp.net para esto: agrupación . Solo utilícelo. Cada nueva versión tendrá un sufijo único "? V = XXXXXXX". En el modo de depuración, la agrupación está desactivada, para activar la configuración de make en web.config:

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

O agregue al método RegisterBundles (BundleCollection bundles):

BundleTable.EnableOptimizations = true;

Por ejemplo:

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
fuente
Pero esto solo funcionará en entornos de lanzamiento o producción. ¿Qué pasa con el desarrollo cuando está activado el modo de depuración? ¿El paquete aún soluciona este problema?
VAAA
Sí, bundlind no facilita la vida de los desarrolladores. Debe presionar Ctrl-F5 después de cada cambio de secuencia de comandos. Y si tienes marcos será aún más divertido.
it3xl
6

Hay una respuesta más simple a esto que la respuesta dada por el operador en la pregunta (el enfoque es el mismo):

Defina la clave en web.config:

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

Realice la llamada a la configuración de la aplicación directamente desde la página aspx:

<link href="styles/navigation.css?v=<%=ConfigurationManager.AppSettings["VersionNumber"]%>" rel="stylesheet" type="text/css" />
JackArbiter
fuente
Me gusta esto, pero me preocupa por qué esta solución tiene tan pocos votos
positivos
@SimplyInk No lo sé, pero hay 20 respuestas diferentes, así que eso podría tener algo que ver con eso. Si funciona y le gusta, no dude en votarlo.
JackArbiter
4

Basado en la respuesta de Adam Tegan , modificado para su uso en una aplicación de formularios web.

En el código de clase .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);
    }
}

En el marcado aspx:

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

Y en el HTML renderizado, aparece como

<script type="text/javascript" src='/js/exampleJavaScriptFile.js?v=20150402021544'></script>
Bryan
fuente
2
¡Oye! Su ejemplo está funcionando, pero debe eliminar las referencias de almacenamiento en caché o corregir el código para usar el caché porque puede resultar confuso por qué lo está usando. Para usar el caché, debe agregar la versión del archivo al caché usando el método context.Cache.Add en el caso context.Cache [nombre de archivo] == null. Si context.Cache [nombre de archivo]! = Nulo, entonces debe devolver el valor en caché (context.Cache [nombre de archivo])
Flavia Obreja
1
Flavia, creo que tu explicación tiene sentido y creo que es una implementación más simple y eficiente. Gracias por publicar comentarios y comentarios útiles.
Bryan
4

Curiosamente, este mismo sitio tiene problemas con el enfoque que describe en relación con algunas configuraciones de proxy, aunque debería ser a prueba de fallas.

Consulte esta discusión sobre desbordamiento de metastack.

Entonces, a la luz de eso, podría tener sentido no usar un parámetro GET para actualizar, sino el nombre real del archivo:

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

aunque esto es más trabajo por hacer, ya que tendrá que crear el archivo o crear una reescritura de URL para él.

Pekka 웃
fuente
4

Quería un trazador de líneas simple para hacer que la ruta sea única para romper el caché. Esto funcionó para mí:

<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 el archivo se ha modificado desde la última vez que se cargó en la página, el navegador extraerá el archivo actualizado.

Genera el last modifiedsello a partir del .jsarchivo y lo coloca allí en lugar de la versión a la que puede que no sea fácil acceder.

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

Otra opción podría ser obtener la suma de comprobación del archivo.

francotirador
fuente
1
Con mucho, la forma más fácil de hacer esto, y probablemente la sobrecarga más baja.
Tony Hinkle
1
Solución perfecta. También probé Chrome 70, Firefox 63 e IE 11 para asegurarme de que el almacenamiento en caché realmente funcionaba. Es. Esto solo elimina el almacenamiento en caché en nuevas versiones del archivo, al menos en las últimas versiones de los navegadores. Escuché mencionar en otra parte que algunos navegadores recargan cada archivo con una cadena de consulta (?). Tal vez ese fuera el caso o tal vez todavía sea cierto con Safari y Opera. DK.
Brad Mathews
3

Este es un enfoque que funciona con ASP.NET 5 / MVC 6 / vNext .

Paso 1: Cree una clase para devolver la última hora de escritura del archivo, similar a otras respuestas en este hilo. Tenga en cuenta que esto requiere la inyección de dependencia ASP.NET 5 (u otra).

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;
     }
}

Paso 2: Registre el servicio que se inyectará dentro de startup.cs :

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

Paso 3: Luego, en ASP.NET 5, es posible inyectar el servicio directamente en una vista de diseño como _Layout.cshtml así:

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

Hay algunos toques finales que podrían hacerse para combinar mejor las rutas físicas y manejar el nombre del archivo en un estilo más consistente con la sintaxis, pero este es un punto de partida. Espero que ayude a las personas a migrar a ASP.NET 5.

Ender2050
fuente
este comportamiento en realidad es compatible desde el primer momento, vea mi respuesta
metalheart
3

He empleado una técnica ligeramente diferente en mi sitio 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;
    }
}

Luego, en las vistas reales:

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

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

Esto me funciona en todos los navegadores. Aquí he usado PHP para generar números aleatorios. Puede utilizar su propio idioma del lado del servidor.

Mukesh Rai
fuente
Buena respuesta, pero ASP MVC puede ser un poco problemático si no considera lo que Adam explicó porque lo probé y la carpeta Bundle no lo reconoce si trabaja con MVC 5. ¡Pero gracias por la sugerencia!
Federico Navarrete
2

A partir de la respuesta anterior , modifiqué un poco el código para que el asistente también funcione con archivos CSS y agregue una versión cada vez que haga algún cambio en los archivos y no solo cuando realice la compilación.

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à
fuente
1

Obtenga la hora de modificación del archivo, como se muestra a continuación

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

Agregue esto con input como querystring

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

Llame a esto desde el marcado.

Enfoque del asistente de extensión de MVC

Agregar un método de extensión

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());
      }

    }
}

Agregue este espacio de nombres en 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>

Úselo en vista como

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

Sugerencias previas simplificadas y código para desarrolladores de .NET Web Forms.

Esto aceptará URL relativas ("~ /") y absolutas en la ruta del archivo al recurso.

Ponga en un archivo de clase de extensiones estáticas, lo siguiente:

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];
}

Y luego llámelo en su página maestra como tal:

<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
fuente
¡Buen enfoque también!
Federico Navarrete
0

Basado en la respuesta anterior , escribí una pequeña clase de extensión para trabajar con archivos CSS y 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;
        }
    }
}

En lugar de escribir algo como:

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

Ahora puedes escribir:

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

Es decir, simplemente reemplácelo Url.Contentcon Url.VersionedContent.

Las URL generadas tienen este aspecto:

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

Si usa la clase de extensión, es posible que desee agregar manejo de errores en caso de que la MapPathllamada no funcione, ya contentPathque no es un archivo físico.

Uwe Keim
fuente
0

Utilizo una forma similar de hacer lo mismo que estás haciendo sin modificar cada página. Se agregó un evento de PreRender en un archivo maestro. Mantiene mi lógica en un solo lugar y es aplicable a archivos js y 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"]));
                    }
                }

            }

        }
    }
Arrendajo
fuente
0

Puede invalidar la propiedad DefaultTagFormat de Scripts o Styles.

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

Para resolver este problema en mi aplicación ASP.Net Ajax, creé una extensión y luego llamé a la página maestra.

Para obtener más detalles, puede ir a través del enlace .

Kasim Husaini
fuente
0

Una forma fácil e inteligente de implementar el control de versiones css en la aplicación .net mediante el concepto siguiente ... no es necesario escribir código de back-end.

<link href="<%="../../App_Themes/Base/css/main.css?v="+ DateTime.Now.ToString("yyyyMMddhhmmss") +""%>" rel="stylesheet" />
SantoshK
fuente
esto forzará la descarga en cada representación de la página, incluso si los archivos no han cambiado en absoluto.
Thanasis Ioannidis
@ThanasisIoannidis Se puede usar donde los archivos se cambian regularmente. otra opción es agregar la clave appVersion en web.config y usarla con el nombre de los archivos ... pero debes actualizar cuando lances la aplicación para prod.
SantoshK
-1

El principal problema de hacerlo de esta manera es principalmente que deberá recordar actualizar su número de versión en su código cada vez que realice algún cambio en sus archivos css o js.

Una forma posiblemente mejor de hacerlo es establecer un parámetro único garantizado con cada uno de sus archivos css o js, ​​así:

<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" />

Esto obliga a que los archivos se soliciten al servidor cada vez, lo que también significa que su sitio no tendrá el mismo rendimiento cuando se cargue la página, ya que esos archivos nunca se almacenarán en caché y utilizarán ancho de banda innecesario cada vez.

Esencialmente, si puede recordar actualizar el número de versión cada vez que se realiza un cambio, puede salirse con la suya.

Tim S. Van Haren
fuente
9
y también utiliza grandes cantidades de ancho de banda.
Darren Kopp
2
Correcto, no desea una nueva versión de JS en cada carga de página ... solo desea que el navegador busque una nueva versión cada vez que tenga una versión actualizada.
kingdango
Esto es perfectamente aceptable para una solución temporal en un archivo css de 50 KB mientras está en desarrollo. +1
Colbs
-2

Para las páginas ASP.NET estoy usando lo siguiente

ANTES DE

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

DESPUÉS (forzar recarga)

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

Agregar DateTime.Now.Ticks funciona muy bien.

Ravi Ram
fuente
sí, el problema es con el ancho de banda, como en los comentarios anteriores stackoverflow.com/a/2185918/59508
kiev