How to let users have the latest non cached code? - javascript

This is kind of a core web development topic, and one that is tough to search for.
I'm running a medium sized websites ~2500 users a day. We are in heavy development of new features every month. We have GIT setup with a master, dev/master and some other development branches. We have a staging server and a dev server plus we all work locally till we push to dev.
However, when I push changes to dev, or even live, it's often the case that users have to refresh cache or else they see errors.
We do use HTML5 Application cache, which when we change the manifest will let all the files reset. But we're not using App Cache for the whole application, just some resources that make the application MUCH faster.
App Cache aside, this was still a problem in our old site, even without app cache. I know you can do ?timestamp after JS and CSS files. BUT I WANT users to cache these. It speeds up their experience.
So, how does one go about letting users cache content for speed, but get the NEWEST content when I push an update? How do the big boys handle this?
Thanks!

I wanted to put a clear answer here, because the solution to this is AWESOME. This is basically what Kay was saying to do.
In PHP we do this define("GIT_HASH",exec(GIT." rev-parse --short HEAD 2>&1"));
where GIT is a path to your git bin. On linux its just git, on mac its like /usr/local/bin/git
Then we put our GIT hash in JS to be used with require.js
<script>
window.app_hash = '<?=GIT_HASH;?>' || '';
</script>
Now we have our hash, So we just changed the config for require.js
require.config({
baseUrl: '__' + app_hash,
We also have this for hardcoded PHP urls
/css/main.css">
Lastly we used an NGINX rewrite rule to allow this
rewrite ^/__[^/]*/(.+) /$1 last;
And for apache in htaccess
RewriteRule ^__[^/]*/(.+) /$1
the __ is a prefix we used to our hash, just to make it clear. The last in NGINX is that the rest of our rules get hit, and for htaccess you don't need that.
The reason we didn't use a query string like ?whatever is because some browser will NEVER cache URLs with a query string like that. And we don't want that, we want caching, just not when we deploy.
If you aren't using require.js - you will have to change all of your URLs to the syntax, BUT ITS WORTH IT.
And if your using html5 app cache, be sure to take out any css and js you have in there.
Thanks Kay!

From what I've read though, browser cache files differently when you add a querystring. So the solution I use is to have URLs look like this:
<script type="text/javascript" src="/resources/cacheholder1/js/site.js" />
Every time I build my project and are about to deploy the new version, I increment this number. Of course, that's very annoying when you have dozens/hundreds of these lines. So I wrote a bash script to go through my project and look for anything that matches the following pattern:
/resources/cacheholder(#)/
then take the matched number, increment it, and update/save the file.
Of course, it would probably be wiser to use the project number instead of an arbitrary number, as long as you are actually tracking the project number and it is automatically changed. This works for us right now, so I'm sticking with it, but have been planning to use the project number.
This is supposed to cache the files properly since it's a "new" URL, not just a querystring change. At the same time, it took me a little extra configuration to allow for this URL scheme because that "cacheholder" part changes (the number), so you can't hardcode the URL mapping in your project.
The problem with querystrings is that browsers are not supposed to cache requests with a querystring, so there is a mix between which do and don't. And I'm betting the only one that does (because I'm remembering it happen) is IE. Other browsers seem to follow the spec to not cache requests with a querystring.

The query string in asset?timestamp causes Firefox to ask the server for every request. This is a waste of resources and user's time, even though you could respond with 304.
I use www.example.com/assets/<git hash>/name.js in my projects and it works fine. The revision only changes if the content was edited, so there won't be needless queries.
The static content is set to expire in 1 month:
Last-Modified: Thu, 28 Mar 2013 12:16:21 GMT
Cache-Control: public, max-age=2678400
Expires: Sun, 28 Apr 2013 14:00:58 GMT
ETag: "flask-1364472981.38-9149-1640239173"
In your deployment process you have to replace the <git hash> in your layout files.
You get the revision when an asset was last modified with:
git log --format=%h -1 -- path/to/asset.js

Related

How do I display my project correctly in a server?

I sent my project to my server but no one cant see changes what i did in local mode(i have index.html and other js and php). I had the same problem with another project with index.php but soved adding this <?php time();?> at the end of scrip. Is there any similar solution for javascript?
This is what i did
<script src="assets/js/funciones.js?<?php time();?>"></script>
The problem is that you're changing static files, but not their filenames.
By default apache/nginx/etc serve static content with headers that say "cache this for a very long time" because it's static content, why would you not?
Tacking on random trash to the URL like you're doing with you JS is a kludge that permanently breaks all caching and ensures that users will repeatedly download the exact same static file every time they request a page. You can make the trash less random to break the cache less frequently, but it's still an inefficient kludge. [Albeit a popular one, to my immense annoyance.]
Ideally for resource bundles like JS and CSS, you make a new resource bundle file every time you change it, eg: somefile-v1234.js or somefile-20211007.js and update the reference in your HTML source. This has the side-benefit of ensuring that the versions of your resource bundles always match.
The same goes for any other static file: images, CSV, etc.
The trouble you're having now is that you've updated some HTML pages and the only way to break the cache is to have the user perform an action, like hitting CTRL+F5 to force a refresh.
There are a couple ways around this:
Change the Apache/Nginx/etc settings to set shorter expiries for static file cache headers. You may be able to target specific files like index.html, but YMMV.
Serve the content with PHP. Anything served via a PHP script will not have any cache headers set by default, as the assumption is that the output of a script is dynamic. You can also issue the caching headers yourself in PHP to control what gets cached for how long.
Lastly, you cannot solve this problem retroactively. If a user has a cached version of the HTML page that has not yet reached its expiration, the user MUST take action to break that cache. There's nothing that can be done server side because the valid cache tells the client that it doesn't have to ask the server.
Once you get to the point of your application being popular enough to warrant putting a CDN in front of it this problem gets much worse as now there's a cache in the middle that the user doesn't have control of, and it's potentially an expensive problem because some CDN providers charge a fee for forcing CDN cache invalidations.

JavaScript version control: Managing versions from FE

SCENARIO:
I am trying to come up with a way to Version Control in JS that fulfills two premises:
Cache-wise
Few (or none ideally) calls to Backend
Therefore I came up with this scheme:
I need FE to reload contents everytime a new version is available, so a simple way to achieve this would be to add a version tag to src link:
<script type="text/javascript" src="myfile.js?15.6.0"></script>
I can add some templating, so the version number can be defined elsewhere, like:
<script type="text/javascript" src="myfile.js?$$RELEASE_ID$$"></script>
PROBLEM:
I would need to call the Backend, to know the latest version (and the Backend will read it from pom.xml file, returning it afterwards)
QUESTION:
Is there any way I can use so the Front End knows what is the latest version?
Thanks.
I'd use buildnumber-maven-plugin to generate a version tag, e.g. git hash. And, embed it somewhere in a war file. Either
It's a server side file, e.g. web.xml where you can define a context variable for access in your Java code, or
An HTML/JS file for browser side.
See https://github.com/renfeng/event-manager/blob/master/pom.xml#L130-L155
There is no way to eliminate communication with back end in order to get information about a state of a file on the server. But if you desire to have as few requests as possible, you could set an intervals for your FE to poll the server.
If you usually release BE version every day, it makes since to poll server any change every 12, 6 ,4 or any number of hours you want. It all depends on how crucial it is to update the file.
That been said, in most cases when updating a file version on back end, once page is refreshed (which is likely to happen after few hours) the server will send the new file version, unless server caching strategy is configured otherwise.

Glassfish not updating JavaScript files

I have been using Glassfish 3.1 for a web project, even after updating a JavaScript file, and re-publishing the whole project onto the glassfish server, server seems to execute the older version of file.
I have tried, restarting the server, but everything went in vain.
Thanks in advance.
In my answer I assume you are entirely sure that even if you packed an updated script still the old script version is rendered on the page. However I would advice to double check it.
You have some options here:
First option
If it is a developer machine and just one time problem with cache you can quickly fix it by deleting applications, generated and osgi-cache folders from your GLASSFISH_HOME. Before you should stop your AS though.
Second option
If you do not want your page to be cashed you can create a javax.servlet.Filter and add Expires header to a response in the doFilter method. If you use some date in the past the page will never be cached.
((HttpServletResponse) resp).addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
Alternatively you can calculate a value and that would be your strategy for caching.
Third Option
You can add a parameter to your page URL. For example http(s)://{YOUR_URL}/${PATH_TO_PAGE}?version={APP_VERSION}
You do not have to read or process this parameter, so you do not care about either its name or value, but if in your application you will increase {APP_VERSION} each time you upgrade your app and navigate to the page adding this parameter, it will make the page URL unique for each application version and you can be sure cached version from previous version is not used. This way of course a bit awkward, nevertheless it is still an option. BTW this is a good way to check if you really ran into a cache related problem. Just add a random parameter to your page URL with a random value and you should see the latest script version.
Forth Option
You can somehow combine these option
Hope that helps
This is not a Glassfish problem. This is because your browser caches the js files.
You just have to clear your browser cache.

Remove cached pages for entire site [duplicate]

Is there a way I can put some code on my page so when someone visits a site, it clears the browser cache, so they can view the changes?
Languages used: ASP.NET, VB.NET, and of course HTML, CSS, and jQuery.
If this is about .css and .js changes, then one way is "cache busting" by appending something like "_versionNo" to the file name for each release. For example:
script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.
or after the file name:
script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.
You can check this link to see how it could work.
Look into the cache-control and the expires META Tag.
<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">
Another common practices is to append constantly-changing strings to the end of the requested files. For instance:
<script type="text/javascript" src="main.js?v=12392823"></script>
Update 2012
This is an old question but I think it needs a more up to date answer because now there is a way to have more control of website caching.
In Offline Web Applications (which is really any HTML5 website) applicationCache.swapCache() can be used to update the cached version of your website without the need for manually reloading the page.
This is a code example from the Beginner's Guide to Using the Application Cache on HTML5 Rocks explaining how to update users to the newest version of your site:
// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {
window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
// Browser downloaded a new app cache.
// Swap it in and reload the page to get the new hotness.
window.applicationCache.swapCache();
if (confirm('A new version of this site is available. Load it?')) {
window.location.reload();
}
} else {
// Manifest didn't changed. Nothing new to server.
}
}, false);
}, false);
See also Using the application cache on Mozilla Developer Network for more info.
Update 2016
Things change quickly on the Web.
This question was asked in 2009 and in 2012 I posted an update about a new way to handle the problem described in the question. Another 4 years passed and now it seems that it is already deprecated. Thanks to cgaldiolo for pointing it out in the comments.
Currently, as of July 2016, the HTML Standard, Section 7.9, Offline Web applications includes a deprecation warning:
This feature is in the process of being removed from the Web platform.
(This is a long process that takes many years.) Using any of the
offline Web application features at this time is highly discouraged.
Use service workers instead.
So does Using the application cache on Mozilla Developer Network that I referenced in 2012:
Deprecated This feature has been removed from the Web standards.
Though some browsers may still support it, it is in the process of
being dropped. Do not use it in old or new projects. Pages or Web apps
using it may break at any time.
See also Bug 1204581 - Add a deprecation notice for AppCache if service worker fetch interception is enabled.
Not as such. One method is to send the appropriate headers when delivering content to force the browser to reload:
Making sure a web page is not cached, across all browsers.
If your search for "cache header" or something similar here on SO, you'll find ASP.NET specific examples.
Another, less clean but sometimes only way if you can't control the headers on server side, is adding a random GET parameter to the resource that is being called:
myimage.gif?random=1923849839
I had similiar problem and this is how I solved it:
In index.html file I've added manifest:
<html manifest="cache.manifest">
In <head> section included script updating the cache:
<script type="text/javascript" src="update_cache.js"></script>
In <body> section I've inserted onload function:
<body onload="checkForUpdate()">
In cache.manifest I've put all files I want to cache. It is important now that it works in my case (Apache) just by updating each time the "version" comment. It is also an option to name files with "?ver=001" or something at the end of name but it's not needed. Changing just # version 1.01 triggers cache update event.
CACHE MANIFEST
# version 1.01
style.css
imgs/logo.png
#all other files
It's important to include 1., 2. and 3. points only in index.html. Otherwise
GET http://foo.bar/resource.ext net::ERR_FAILED
occurs because every "child" file tries to cache the page while the page is already cached.
In update_cache.js file I've put this code:
function checkForUpdate()
{
if (window.applicationCache != undefined && window.applicationCache != null)
{
window.applicationCache.addEventListener('updateready', updateApplication);
}
}
function updateApplication(event)
{
if (window.applicationCache.status != 4) return;
window.applicationCache.removeEventListener('updateready', updateApplication);
window.applicationCache.swapCache();
window.location.reload();
}
Now you just change files and in manifest you have to update version comment. Now visiting index.html page will update the cache.
The parts of solution aren't mine but I've found them through internet and put together so that it works.
For static resources right caching would be to use query parameters with value of each deployment or file version. This will have effect of clearing cache after each deployment.
/Content/css/Site.css?version={FileVersionNumber}
Here is ASP.NET MVC example.
<link href="#Url.Content("~/Content/Css/Reset.css")?version=#this.GetType().Assembly.GetName().Version" rel="stylesheet" type="text/css" />
Don't forget to update assembly version.
I had a case where I would take photos of clients online and would need to update the div if a photo is changed. Browser was still showing the old photo. So I used the hack of calling a random GET variable, which would be unique every time. Here it is if it could help anybody
<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...
EDIT
As pointed out by others, following is much more efficient solution since it will reload images only when they are changed, identifying this change by the file size:
<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"
A lot of answers are missing the point - most developers are well aware that turning off the cache is inefficient. However, there are many common circumstances where efficiency is unimportant and default cache behavior is badly broken.
These include nested, iterative script testing (the big one!) and broken third party software workarounds. None of the solutions given here are adequate to address such common scenarios. Most web browsers are far too aggressive caching and provide no sensible means to avoid these problems.
Updating the URL to the following works for me:
/custom.js?id=1
By adding a unique number after ?id= and incrementing it for new changes, users do not have to press CTRL + F5 to refresh the cache. Alternatively, you can append hash or string version of the current time or Epoch after ?id=
Something like ?id=1520606295
<meta http-equiv="pragma" content="no-cache" />
Also see https://stackoverflow.com/questions/126772/how-to-force-a-web-browser-not-to-cache-images
Here is the MDSN page on setting caching in ASP.NET.
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True
If Response.Cache.VaryByParams("Category") Then
'...
End If
Not sure if that might really help you but that's how caching should work on any browser. When the browser request a file, it should always send a request to the server unless there is a "offline" mode. The server will read some parameters like date modified or etags.
The server will return a 304 error response for NOT MODIFIED and the browser will have to use its cache. If the etag doesn't validate on server side or the modified date is below the current modified date, the server should return the new content with the new modified date or etags or both.
If there is no caching data sent to the browser, I guess the behavior is undetermined, the browser may or may not cache file that don't tell how they are cached. If you set caching parameters in the response it will cache your files correctly and the server then may choose to return a 304 error, or the new content.
This is how it should be done. Using random params or version number in urls is more like a hack than anything.
http://www.checkupdown.com/status/E304.html
http://en.wikipedia.org/wiki/HTTP_ETag
http://www.xpertdeveloper.com/2011/03/last-modified-header-vs-expire-header-vs-etag/
After reading I saw that there is also a expire date. If you have problem, it might be that you have a expire date set up. In other words, when the browser will cache your file, since it has a expiry date, it shouldn't have to request it again before that date. In other words, it will never ask the file to the server and will never receive a 304 not modified. It will simply use the cache until the expiry date is reached or cache is cleared.
So that is my guess, you have some sort of expiry date and you should use last-modified etags or a mix of it all and make sure that there is no expire date.
If people tends to refresh a lot and the file doesn't get changed a lot, then it might be wise to set a big expiry date.
My 2 cents!
I implemented this simple solution that works for me (not yet on production environment):
function verificarNovaVersio() {
var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
$.ajax({
url: "./versio.txt"
, dataType: 'text'
, cache: false
, contentType: false
, processData: false
, type: 'post'
}).done(function(sVersioFitxer) {
console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
location.reload(true);
}
});
}
I've a little file located where the html are:
"versio.txt":
v00.5.0014
This function is called in all of my pages, so when loading it checks if the localStorage's version value is lower than the current version and does a
location.reload(true);
...to force reload from server instead from cache.
(obviously, instead of localStorage you can use cookies or other persistent client storage)
I opted for this solution for its simplicity, because only mantaining a single file "versio.txt" will force the full site to reload.
The queryString method is hard to implement and is also cached (if you change from v1.1 to a previous version will load from cache, then it means that the cache is not flushed, keeping all previous versions at cache).
I'm a little newbie and I'd apreciate your professional check & review to ensure my method is a good approach.
Hope it helps.
In addition to setting Cache-control: no-cache, you should also set the Expires header to -1 if you would like the local copy to be refreshed each time (some versions of IE seem to require this).
See HTTP Cache - check with the server, always sending If-Modified-Since
There is one trick that can be used.The trick is to append a parameter/string to the file name in the script tag and change it when you file changes.
<script src="myfile.js?version=1.0.0"></script>
The browser interprets the whole string as the file path even though what comes after the "?" are parameters. So wat happens now is that next time when you update your file just change the number in the script tag on your website (Example <script src="myfile.js?version=1.0.1"></script>) and each users browser will see the file has changed and grab a new copy.
Force browsers to clear cache or reload correct data? I have tried most of the solutions described in stackoverflow, some work, but after a little while, it does cache eventually and display the previous loaded script or file. Is there another way that would clear the cache (css, js, etc) and actually work on all browsers?
I found so far that specific resources can be reloaded individually if you change the date and time on your files on the server. "Clearing cache" is not as easy as it should be. Instead of clearing cache on my browsers, I realized that "touching" the server files cached will actually change the date and time of the source file cached on the server (Tested on Edge, Chrome and Firefox) and most browsers will automatically download the most current fresh copy of whats on your server (code, graphics any multimedia too). I suggest you just copy the most current scripts on the server and "do the touch thing" solution before your program runs, so it will change the date of all your problem files to a most current date and time, then it downloads a fresh copy to your browser:
<?php
touch('/www/sample/file1.css');
touch('/www/sample/file2.js');
?>
then ... the rest of your program...
It took me some time to resolve this issue (as many browsers act differently to different commands, but they all check time of files and compare to your downloaded copy in your browser, if different date and time, will do the refresh), If you can't go the supposed right way, there is always another usable and better solution to it. Best Regards and happy camping. By the way touch(); or alternatives work in many programming languages inclusive in javascript bash sh php and you can include or call them in html.
For webpack users:-
I added time with chunkhash in my webpack config. This solved my problem of invalidating cache on each deployment. Also we need to take care that index.html/ asset.manifest is not cached both in your CDN or browser. Config of chunk name in webpack config will look like this:-
fileName: [chunkhash]-${Date.now()}.js
or If you are using contenthash then
fileName: [contenthash]-${Date.now()}.js
This is the simple solution I used to solve in one of my applications using PHP.
All JS and CSS files are placed in a folder with version name. Example : "1.0.01"
root\1.0.01\JS
root\1.0.01\CSS
Created a Helper and Defined the version Number there
<?php
function system_version()
{
return '1.0.07';
}
And Linked JS and SCC Files like below
<script src="<?= base_url(); ?>/<?= system_version();?>/js/generators.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="<?= base_url(); ?>/<?= system_version(); ?>/css/view-checklist.css" />
Whenever I make changes to any JS or CSS file, I change the System Verson in Helper and rename the folder and deploy it.
I had the same problem, all i did was change the file names which are linked to my index.html file and then went into the index.html file and updated their names, not the best practice but if it works it works. The browser sees them as new files so they get redownloaded on to the users device.
example:
I want to update a css file, its named styles.css, change it to styless.css
Go into index.html and update , and change it to
in case interested I've found my solution to get browsers refreshing .css and .js in the context of .NET MVC (.net fw 4.8) and the use of bundles.
I wanted to make browsers refresh cached files only after a new assembly is deployed.
Buinding on Paulius Zaliaduonis response, my solution is as follows:
store your application base url in the web config app settings (the HttpContext is not yet available at runtime during the RegisterBundle...), then make this parameter changing according to the configuration (debug, staging, release...) by the xml transform
In BundleConfig RegisterBundles get the assembly version by the means of reflection, and...
...change the default tag format of both styles and scripts so that the bundling system generates link and script tags appending a query string parameter on them.
Here is the code
public static void RegisterBundles(BundleCollection bundles)
{
string baseUrl = system.Configuration.ConfigurationManager.AppSettings["by.app.base.url"].ToString();
string assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Styles.DefaultTagFormat = $"<link href='{baseUrl}{{0}}?v={assemblyVersion}' rel='stylesheet'/>";
Scripts.DefaultTagFormat = $"<script src='{baseUrl}{{0}}?v={assemblyVersion}'></script>";
}
You'll get tags like
<script src="https://example.org/myscriptfilepath/script.js?v={myassemblyversion}"></script>
you just need to remember to to build a new version before deploying.
Ciao
2023 onward
At the time of writing, many web browsers support the Clear-Site-Data HTTP header [MDN reference]. To instruct the client web browser to clear the cache for the website domain and subdomains, set the following header in the HTTP response from the server:
Clear-Site-Data: "cache"
Alternatively, the following header may be better supported across browsers, but it clears other website data, such as localStorage and cookies, in addition to the cache.
Clear-Site-Data: "*"
However note that intermediate caches (e.g. a CDN) may not understand or respect this header, so intermediate caches may still respond with previously cached data.
Do you want to clear the cache, or just make sure your current (changed?) page is not cached?
If the latter, it should be as simple as
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

Get URL and redirect before page load

So, i have an interesting situation. I've been working on re-organizing a directory on a website. I updated old files there's about 100 of them, they are in a new location. The old files have been taken down.
The problem I have is there are probably hundreds of people that have bookmarks directly to the URL of the old files. (e.i. "wahwah.com/subSite/pdfs/something.pdf") these files are 5 years old so they need to find the new ones anyways.
So instead of having a page for each individual file, Can I have something in the directory that used to house the files to watch for that URL and redirect to the new page?
It would watch for "wahwah.com/subSite/pdfs.." and redirect. Or maybe something in the main directory of this subSite to watch for the URL to have the /pdf path in it.
I know I can grab URLs in java script but that doesn't help me unless I can do what I stated above. I'm not sure how if at all I could do it in .NET. our servers support .NET because most of our site apps were made with it but I don't deal with those. I cannot use PHP, the servers don't use it.
I'm hoping JavaScript will be able to do it somehow, but it's something i've never tried before so just thinking about it i'm not sure I can. I'm not much for using JS libraries so Im not sure what is out there i've been searching a bit though.
I found Grunt but i'm not entirely sure how it works just yet. Just looking around maybe the file filter or matchBase. or some of the Global patterns.
If you have access to server, your best option is to set up redirect in there on wahwah.com/subSite/pdfs/ directory.
How to do this depends on if you're on IIS or unix.
In asp.net, 301 redirect is fairly efficient.
if (HttpContext.Contains("http://old.aspx"))
{
HttpContext.Current.Response.Status = "301 Moved Permanently";
HttpContext.Current.Response.AddHeader("http://www.new.aspx");
}
Or in page load you can write:
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location","http://new.aspx");

Categories

Resources