Clear ASP.NET OutputCache across web applications - asp.net

Is it possible to clear the output cache of one asp.net web application from inside another asp.net web application?
Reason being... We have several wep applications structured like...
http://www.website.com/intranet/cms/
http://www.website.com/area1/
http://www.website.com/area2/
Pages in /area1/ and /area2/ are cached and are managed through /intranet/cms/. When a page is edited using /intranet/cms/ I want to clear it out of the cache in the appropriate /area#/ application.
I already tried using a VaryByCustom that looks up a guid stored in the HttpContext.Cache but that seems to be cached per web application, that doesn't work.
Really if there were any way of passing data between web applications on a single server, that would solve my problem, since I can use that + VaryByCustom.
Thanks!
-Mike Thomas

The way I've done this in the past is to have a "hidden" page (in each of the /areaX sites) that does the flushing, reloading, etc. The page validates a shared secret query parameter before doing anything (to avoid DoS attacks). If valid the page would output an "OK" message once the operation is complete; generates a 404 error if the secret is invalid.
If you want the flush to be on a per-item or per-group basis then add a second parameter that identifies that item/group.
This method is also server technology independent, and can be triggered by other management tools if required.

One way I know of doing this is by using a shared resource as a dependency, usually a file. When the file is changed, the cache is cleared. I think you can use HttpResponse.AddFileDependency for this.
However, in these cases it's usually better to use an out-of-process cache such as memcached. I haven't tested it myself, but this link deals on using memcached with OutputCache.

Related

How to invalidate browser cache using just configuration in the webserver?

For a long time I've been updating ASP.NET pages on the server and never find the correct way to make changes visible on files like CSS and images.
I know if a append something in the URL the browser will think the file is another one:
<img src="/images/myLogo.png?v=1"/>
or perhaps changing its name:
<img src="/images/myLogo.v1.png"/>
Unfortunately it does not look the correct way. In a case were I'm using App_Themes the files in this folder are automatically injected in the page in a way I can't easily change the URL.
So my question is:
When I'm publishing de ASP.NET Application on the server what is the correct way to signal to IIS (and it notify browser after that) that a file was changed? It is not automatic? Should I change some configuration in IIS or perhaps make some "decoration" in the code?
I've already tried many questions here in SO like "ASP.NET - Invalidate browser cache", "How to refresh the browser cache of an image?", "Handle cached images? How to get the browser to show the new version?", and even "What is an elegant way to force browsers to reload cached CSS/JS files?" but none of them actually take another aproach else in a way you must handle it manually in the code instead of IIS or ASP.NET configuration.
The closer I could find is "Asking browsers to cache our images (ASP.NET/IIS)" where they set expiration but not based on the fact the files were update. Instead they used days or hour to cache those file so they would updated even when no changes were made.
I'm want to know if IIS or ASP.NET offers something related to this, automatically send to the browser that the files was changed. Is it possible/built in?
The options you have to update the browser side, cached item are:
Change the file name
Add url parameter
Place it on cache for a limited time (eg for couple of hours)
Compare the date-time of creation.
Signaling with eTag.
With the three two you avoiding one server call for each item, but the third option load it again after some time.
With the others you have to make one call to the server to see if needs to be load it again.
So you can not have all here, there is not correct way, and you need to chose what is the best for you, and what you can do. The faster from client perspective is the (1) and (2) options.
The direct answer to your question is to use eTag, or date-time compare of the file creation, but you loose that way, a call to the server, you only win the size of what is travel back.
Some more links:
http eTag
How do I support ETags in ASP.NET MVC?
Configuring ETags with Http module in asp.net
How to control web page caching, across all browsers?
Jquery getScript caching
and you can find even more.

ASP.NET Friendly URLs

In my research, I found 2 ways to do them.
Both required modifications to the Application_BeginRequest procedure in the Global.Asax, where you would run your code to do the actual URL mapping (mine was with a database view that contained all the friendly URLs and their mapped 'real' URLs). Now the trick is to get your requests run through the .NET engine without an aspx extension. The 2 ways I found are:
Run everything through the .NET engine with a wildcard application extension mapping.
Create a custom aspx error page and tell IIS to send 404's to it.
Now here's my question:
Is there any reason one of these are better to do than the other?
When playing around on my dev server, the first thing I noticed about #1 was it botched frontpage extensions, not a huge deal but that's how I'm used to connecting to my sites. Another issue I have with #1 is that even though my hosting company is lenient with me (as I'm their biggest client) and will consider doing things such as this, they are wary of any security risks it might present.
`#2 works great, but I just have this feeling it's not as efficient as #1. Am I just being delusional?
Thanks
I've used #2 in the past too.
It's more efficient because unlike the wildcard mapping, the ASP.NET engine doesn't need to 'process' requests for all the additional resources like image files, static HTML, CSS, Javascript etc.
Alternatively if you don't mind .aspx extension in your URL's you could use: http://myweb/app/idx.aspx/products/1 - that works fine.
Having said that, the real solution is using IIS 7, where the ASP.NET runtime is a fully fledged part of the IIS HTTP module stack.
If you have the latest version of IIS there is rewrite module for it - see here. If not there are free third party binaries you can use with older IIS (i.e. version 6) - I have used one that reads the rewrite rules from an .ini file and supports regular expression but I cant remember its name sorry (its possibly this). I'd recommend this over cheaping it out with the 404 page.
You have to map all requests through the ASP.NET engine. The way IIS processes requests is by the file extension. By default it only processes the .aspx, .ashx, etc extensions that are meant to only be processed by ASP.NET. The reason is it adds overhead to the processing of the request.
I wrote how to do it with IIS 6 a while back, http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx.
You are right in doing your mapping from the database. RegEx rewriting, like is used out of the box in MVC. This is because it more or less forces you to put the primary key in the URL and does not have a good way to map characters that are not allowed in URLs, like '.
Did you checked the ASP .Net MVC Framework? Using that framework all your URLs are automatically mapped to Controllers which could perform any desired action (including redirecting to other URLs or controllers). You could also set custom routes with custom parameters. If you don't have seen it yet, maybe it will worth the look.

ASP3 And ASP.NET session sharing

Is there a way to share the session between ASP3 And ASP.NET?
Thanks
Despite all of Microsoft's best efforts to make ASP and ASP.NET coexist effortlessly, one area remains a stumbling block... session state. Fortunately the advantages of ASP.NET's upgraded session state management far outweigh the inconvenience of not being able to pass "Classic" session information to .NET. Unfortunately there is no simple solution; the most I can offer is an easy to implement workaround.
In trying to find a suitable resolution, I've come across two good options that are worth mentioning. The first involves parsing the session information out to hidden form fields on a "Classic" intermediate page and then submitting the page to a .NET intermediate page that loads the form fields into the session state. This is a good, simple solution, however it doesn't work both ways. In .NET you cannot specify the page that you submit to. Each page has to PostBack to itself.
The second option is probably closer to an actual solution than to a workaround. Billy Yuen at Microsoft has developed an effective solution. The code is elegant, the integration appears to be seamless, but I couldn't get it to work on my system (remember I said that there was no simple solution, not that there was no solution at all). If this solution works for you, great! You won't need my code and you'll be happily passing session information from "Classic" to .NET like it's going out of vogue, thanks for stopping by.
Ok, if you're still reading let me briefly describe the workaround I've created. It requires a database, but it is not important which type of database (though the code is written for SQL Server). When a page (source page) wants to redirect to another page (destination page) that uses a different version of ASP, it calls an intermediate page. The source intermediate page takes each session variable and adds it to the database along with a Globally Unique ID (GUID). Since "Classic" and .NET use different SessionID formats it is not possible to use SessionID, hence the use of a GUID. The source intermediate page then passes the GUID to the destination intermediate page through a Querystring variable. The destination intermediate page retrieves the session information from the database, cleans up after itself, and then redirects to the destination page. It's similar to the first workaround, but supports transferring state in both directions.
Code Usage
Installation
Run the SQL Query in "ASPSessionState.sql" on the database which will hold the temporary Session information.
Copy the .asp and .aspx.* (SessionTransfer.aspx and SessionTransfer.aspx.cs) files to a folder on your website.
Update connection object information in the "SessionTransfer.asp" and "SessionTransfer.aspx.cs" files. It is located in three places in each file (sorry about not consolidating the connection info).
Compile the aspx files.
The .asp and .aspx.* files must all reside in the same folder to work.
Usage
For use in a Hyperlink (Anchor Tag) or a Response.Redirect, set the destination URL to be one of the following:
From a ASP "Classic" page:
SessionTransfer.asp?dir=2aspx&url=<asp_dotnet_url>
From an ASP.NET page:
SessionTransfer.aspx?dir=2asp&url=<asp_classic_url>
The code will transfer the Session information and Redirect the user to the url specified by or .
Download
You can download the code from here: session_transfer.zip (4.6 KB).
Could take a look at NSession it allows sharing session state between Classic ASP and ASP.Net using State server. Pretty easy to setup just configure App to use State Server for session and register a couple of dll files.

ASP.Net Context.User.Identity weirdness

I have an ASP.Net 3.0 SP1 app that uses Form Authentication.
While testing, I noticed that if I viewed a page that another user was viewing, the other users name would be displayed in the control on my master page. The Context.User.Identity is also for the other user.
If I switch to different page that no one else is viewing the Context.User.Identity is correct.
I stumped and would appreciate suggestions.
Thanks in advance.
Chris
Maybe because output caching is enabled for the page: if the page is cached server-side with VaryByParam=none, all users will get the same copy from the cache.
I can only think of two things that can cause this:
You're storing user-specific data in a place shared between requests (e.g. in a static(C#)/shared(VB) variable, in the ASP.NET Cache, in the Application object, ...)
You have output caching enabled.
Check for:
OutputCache directives in your aspx and ascx files,
system.web/caching element in your web.config file(s),
Calls to the HttpCacheability.SetCacheability method.
If you can't find the problem:
Try creating a simplified version of your application until you get the simplest possible version that still reproduces the undesirable behaviour.
During this process of simplification you'll likely discover the problem for yourself. If not, post some code from the simplified version.
Make sure you are not using a link that comes with the authentication ticket when using a cookieless browser.
Also make sure to review any other that might be sharing the data among requests. Just like DOK said, but remember Application isn't the only way you could be doing that.
It looks like the issue was caused because I setting targetframe="_self" or Target="_self". I removed all these and everything seem to be working fine.
One other note: If I were to refresh the page it would also display the page with the correct user.

ASP.NET AJAX Load Balancing Issues

This would be a question for anyone who has code in the App_Code folder and uses a hardware load balancer. Its true the hardware load balancer could be set to sticky sessions to solve the issue, but in a perfect world, I would like the feature turned off.
When a file in the App_Code folder, and the site is not pre-compiled iis will generate random file names for these files.
server1 "/ajax/SomeControl, App_Code.tjazq3hb.ashx"
server2 "/ajax/SomeControl, App_Code.wzp3akyu.ashx"
So when a user posts the page and gets transfered to the other server nothing works.
Does anyone have a solution for this? I could change to a pre-compiled web-site, but we would lose the ability for our QA department to just promote the changed files.
Do you have the <machinekey> node on both servers set to the same value?
You can override the machine.config file in web.config to set this. This needs to match otherwise you can get strange situations like this.
Does your load balancer supports sticky sessions? With this on, the balancer will route the same IP to the same server over and over within a certain time window. This way, all requests (AJAX or otherwise) from one client would always hit the same server in the cluster/farm.
Ok, first things first... the MachineKey thing is true. That should absolutely be set to the same on all of the load balanced machines. I don't remember everything it affects, but do it anyway.
Second, go ahead and precompile the site. You can actually still push out new versions, whenever there is a .cs file for a page that page gets recompiled. What gets tricky is the app_code files which get compiled into a single dll. However, if a change is made in there, you can upload the new dll and again everything should be fine.
To make things even easier, enable the "Used fixed naming and single page assemblies" option. This will ensure things have the same name on each compilation, so you just test and then replace the changed .dll files.
All of that said, you shouldn't be having an issue as is. The request goes to IIS, which just serves up the page and compiles as needed. If the code behind is different on each machine it really shouldn't matter, the code is the same and that machine will reference it's own code. The actual request/postback doesn't know or care about any of that. Everything I said above should help simplify things, but it should be working anyway... so it's probably a machinekey issue.
You could move whatever is in your app_code to an external class library if your QA dept can promote that entire library. I think you are stuck with sticky sessions if you can't find a convenient or tolerable way to switch to a pre-compiled site.
If it's a hardware load balancer, you shouldn't have an issue, because all that is known there is the request URL, in which the server would compile the requested page and serve it.
the only issue i can think of that you might have is with session and view state.
Its true the hardware load balancer could be set to sticky sessions to solve the issue, but in a perfect world, I would like the feature turned off.
It appears that the is only for ViewState encryption. It doesn't affect the file names for auto compiled assemblies.
I think asp.net model has quite a bit dependency for encryption and machine specific storage, so I am not sure if it works to avoid sticky IP for session.
I don't know about ASP.NET AJAX (I use MonoRail NJS approach instead), but session state could be an issue for you.
You have to make sure session states are serializable, and don't use InMemory session. You probably need to run ASP.NET Session State Server to make sure the whole frontend farm are using the same session storage. In such case session has to be perfectly serializable (thats why no object in session is preferred, you have to always use ID, and I bet MS stick on this limitation when they do AJAX library development)

Resources