Первоначально я собирался предложить использовать выражения ресурсов для включения тега версии из AppSettings
, но после тестирования обнаружил, что он работает, только если это полное значение свойства элемента управления сервером.
Значение AppSettings
может обновляться сценарием сборки для каждого выпуска; может быть любого формата, который вам нравится:
<appSettings>
<add key="versionTag" value="27" />
</appSettings>
Работает:
<asp:Label runat="server" Text="<%$ AppSettings: versionTag %>" />
Не работает:
<link runat="server" rel="Stylesheet" type="text/css"
href='/css/site.css?v=<%$ AppSettings: versionTag %>' />
Так что моя реальная рекомендация - создать свои собственные элементы управления, которые читают тег версии и включают его в свой вывод. Вот как выглядит мой CSS-элемент управления на странице (ПРИМЕЧАНИЕ: серверные элементы управления должны находиться внутри серверной формы, даже если они могут отображаться внутри элемента head
):
...
<form id="form1" runat="server">
<my:Stylesheet runat="server" Url="~/css/site.css" />
</form>
...
Код для моего элемента управления таблицей стилей:
namespace MyNamespace
{
using System;
using System.ComponentModel;
using System.Configuration;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
/// <summary>
/// Outputs a CSS stylesheet link that supports versionable caching via a
/// build-specific query parameter.
/// </summary>
[
AspNetHostingPermission(SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.LinkDemand,
Level = AspNetHostingPermissionLevel.Minimal),
DefaultProperty("Href"),
ToolboxData(@"<{0}:Stylesheet runat=""server"" />")
]
public class Stylesheet : WebControl
{
private static string versionTag = Stylesheet.GetVersionTag();
/// <summary>
/// Gets or sets the stylesheet URL.
/// </summary>
public string Href
{
get
{
return this.ViewState["Href"] as string;
}
set
{
this.ViewState["Href"] = value;
}
}
/// <summary>
/// Raises the PreRender event.
/// </summary>
/// <param name="e">Contains the event data.</param>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
HtmlLink link = new HtmlLink();
link.Href = String.Format(
"{0}?v={1}",
this.Page.ResolveUrl(this.Href),
HttpUtility.UrlEncode(Stylesheet.versionTag));
if (!Stylesheet.HeadContainsLinkHref(this.Page, link.Href))
{
link.Attributes["type"] = "text/css";
link.Attributes["rel"] = "Stylesheet";
this.Page.Header.Controls.Add(link);
}
}
/// <summary>
/// Generates content to be rendered on the client.
/// </summary>
/// <param name="writer">Receives the server control content.</param>
protected override void Render(HtmlTextWriter writer)
{
// Do nothing.
}
/// <summary>
/// Retrieves the script version tag for this build.
/// </summary>
/// <returns>Returns the script version tag.</returns>
private static string GetVersionTag()
{
string tag = ConfigurationManager.AppSettings["versionTag"];
if (String.IsNullOrEmpty(tag))
{
tag = "1";
}
return tag;
}
/// <summary>
/// Determines if the page's <c>head</c> contains a <c>link</c> tag
/// with a matching <c>href</c> attribute value.
/// </summary>
/// <param name="thePage">The Page to be tested.</param>
/// <param name="href">The <c>href</c> URL to be matched.</param>
/// <returns>Returns true if a matching link is already part of the
/// page <c>head</c> or false otherwise.</returns>
public static bool HeadContainsLinkHref(Page thePage, string href)
{
if (thePage == null)
{
throw new ArgumentNullException("thePage");
}
foreach (Control control in thePage.Header.Controls)
{
if ((control is HtmlLink) &&
(control as HtmlLink).Href == href)
{
return true;
}
}
return false;
}
}
}
НТН.