Is there a way to check if the user has a different version of the CSS cached by their browser and if so force their browser to pull the new version?
You should possibly just share a common ancestor class, then you can flick it with a single js command if need be.
<body class="style2">
<body class="style1">
etc.
Without using js, you can just keep the css filename in a session variable. When a request is made to the Main Page, you simply compose the css link tag with the session variable name.
Being the ccs file name different, you force the broswer to download it without needing to check what was previusly loaded in the browser.
I know the question was specifically about C# and I assume from that Windows Server of some flavour. Since I don't know either of those technologies well, I'll give an answer that'll work in PHP and Apache, and you may get something from it.
As suggested earlier, just set an ID or a class on the body of the page dependent on the specific query eg (in PHP)
<?php
if($_GET['admin_page']) {
$body_id = 'admin';
} else {
$body_id = 'normal';
}
?>
...
<body id="<?php echo $body_id; ?>">
...
</body>
And your CSS can target this:
body#admin h1 {
color: red;
}
body#normal h1 {
color: blue;
}
etc
As for the forcing of CSS download, you could do this in Apache with the mod_expires or mod_headers modules - for mod_headers, this in .htaccess would stop css files being cached:
<FilesMatch "\.(css)$">
Header set Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate"
</FilesMatch>
But since you're probably not using apache, that won't help you much :(
Answer for question 1
You could write a Server Control inheriting from System.Web.UI.Control overriding the Render method:
public class CSSLink : System.Web.UI.Control
{
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if ( ... querystring params == ... )
writer.WriteLine("<link href=\"/styles/css1.css\" type=\"text/css\" rel=\"stylesheet\" />")
else
writer.WriteLine("<link href=\"/styles/css2.css\" type=\"text/css\" rel=\"stylesheet\" />")
}
}
and insert an instance of this class in your MasterPage:
<%@ Register TagPrefix="mycontrols" Namespace="MyNamespace" Assembly="MyAssembly" %>
...
<head runat="server">
...
<mycontrols:CSSLink id="masterCSSLink" runat="server" />
</head>
...
I don´t know if it is correct usage, but I think you can force a reload of the css file using a query string:
<link href="mystyle.css?SOME_UNIQUE_TEXT" type="text/css" rel="stylesheet" />
I remember I used this method years ago to force a reload of a web-cam image, but time has probably moved on...
As jeroen suggested you can have somthing like:
<link href="StyleSelector.aspx?foo=bar&baz=foz" type="text/css" rel="stylesheet" />
Then your StyleSelector.aspx file should be something like this:
<%@ Page Language="cs" AutoEventWireup="false" Inherits="Demo.StyleSelector" Codebehind="StyleSelector.aspx.cs" %>
And your StyleSelector.aspx.cs like this:
using System.IO;
namespace Demo
{
public partial class StyleSelector : System.Web.UI.Page
{
public StyleSelector()
{
Me.Load += New EventHandler(doLoad);
}
protected void doLoad(object sender, System.EventArgs e)
{
// Make sure you add this line
Response.ContentType = "text/css";
string cssFileName = Request.QueryString("foo");
// I'm assuming you have your CSS in a css/ folder
Response.WriteFile("css/" + cssFileName + ".css");
}
}
}
This would send the user the contents of a CSS file (actually any file, see security note) based on query string arguments. Now the tricky part is doing the Conditional GET, which is the fancy name for checking if the user has the page in the cache or not.
First of all I highly recommend you reading HTTP Conditional GET for RSS hackers, a great article that explains the basics of HTTP Conditional GET mechanism. It is a must read, believe me.
I've posted a similar answer (but with PHP code, sorry) to the SO question can i use “http header” to check if a dynamic page has been changed. It should be easy to port the code from PHP to C# (I'll do it if later I have the time.)
Security note: it is highly insecure doing something like ("css/" + cssFileName + ".css"), as you may send a relative path string and thus you may send the user the content of a different file. You are to come up with a better way to find out what CSS file to send.
Design note: instead of an .aspx page you might want to use an IHttpModule
or IHttpHandler
, but this way works just fine.
I like jeroen's suggestion to add a querystring to the stylesheet URL. You could add the time stamp when the stylesheet file was last modified. It seems to me like a good candidate for a helper function or custom control that would generate the LINK tag for you.