Use of HttpValidationStatus.IgnoreThisRequest - asp.net

I am studying the cache invalidation mechanisms and came across the HttpValidationStatus.IgnoreThisRequest.
I understand, that when this is specified, ASP.Net is going to treat response as Cache miss.
Another point is that the dynamic value received in this response is not going to replace the existing cache, as a result subsequent requests are going to use the already cached result.
What is the use of such a mechanism?
Why would someone want to use the already cached result even after having the latest ones?

The use of HttpValidationStatus.IgnoreThisRequest. is meant for cases when you don't want to show a cached page only for that request.
Example:
public void Page_Load()
{
Response.Cache.AddValidationCallback(new HttpCacheValidateHandler(ValidateCache), null);
}
public static void ValidateCache(HttpContext context, Object data, ref HttpValidationStatus status)
{
validationstatus = context.Request.IsAuthenticated ? HttpValidationStatus.IgnoreThisRequest : HttpValidationStatus.Valid;
}
In this case I want to serve cached pages to everybody except for logged users.
Think about a cms: i maybe want that an editor see the just edited page and not the cached one.

Related

Simulate previous request

In my application there are sometimes in that I want to get a user request, save it in some place and then, in a next request, simulate saved request instead of real request, is that possible?
Use any web debugger. I use Fiddler 2.6.2 myself.
Find it here, https://www.telerik.com/download/fiddler
Be warned - there is no robust way to do it (there are a lot of edge cases to consider) but hopefully this will get you started:
Take Request.Form.ToString() and save it against the user somewhere. For testing I suggest putting it in a hidden field, but at some point you would probably need to move that to a database and associate that with the user somehow.
You will need to have a field that will tell you whether the previous request should be replayed. Using a query string parameter like ?replay=true will work. Then pull it into your page:
protected bool IsReplayRequest
{
get
{
return bool.Parse(this.GetValue(p => p.Request["replay"], "false"));
}
}
To simulate the request you will need to override the page's DeterminePostBackMode. This is one of the first methods ASP.NET calls to start the postback process. Use the saved request form converted into a NameValueCollection. Something like this:
protected override NameValueCollection DeterminePostBackMode()
{
if (IsReplayRequest && SavedFormData != null)
{
if (!string.IsNullOrWhiteSpace(SavedFormData.Data))
{
return HttpUtility.ParseQueryString(SavedFormData.Data ?? string.Empty);
}
}
return base.DeterminePostBackMode();
}
Where SavedFormData is just a class which holds the request form and the user information.
With those 3 steps, you should be able to succesfully simulate a previous request for a simple page
Now for the potential problems:
First, the viewstate might get in the way. If you have any listboxes or data grids or authentication etc, you will then need to save the viewstate with the form data. for that you will need to override the page GetStatePersister() method (Is it possible to make a custom implementation of ViewState?).
Second, once you have simulated a request, you need to make sure a) no data is corrupted and b) you remove the "replay" query string. Otherwise the request will play over and over again.
Third, depending on how you store the request form, you will have to think about how to associate it with the user/browser/session/window. Dealing with each one of those has it's own problems.
Once you've got everything above solved, you will successfully simulate a saved request!

System.Web.Caching.Cache in ASP.NET

I just discovered System.Web.Caching.Cache used in a project that I am working on and I am having a hard time finding more information on it.
My question is how this cache is persisted? Is it client-side (similar to ViewState), server-side (Session)? Entirely different?
Example:
protected string FileContent
{
get
{
return Cache[FILE_UPLOAD_KEY + Id] as string ?? GetFileUpload();
}
}
It's a server-side, application-wide cache.
One instance of this class is created per application domain, and it
remains valid as long as the application domain remains active.
Information about an instance of this class is available through the
Cache property of the HttpContext object or the Cache property of the
Page object. (Cache Class, MSDN)
It grants the ability to set time limits and so forth on cached objects. And it doesn't promise the object will be there when you need it again. It keeps items in cache only so long as there is sufficient memory to do so.
So, it's not intended for passing objects between page views (use ViewState or Session for that) or controls (use Items for that). It's intended to cache global objects (accessible in any request from all clients) that are expensive to build.
It's persisted at the server, and it's global across sessions, like Application. So when you set a value in the Cache, it's available to all users until it expires.
EDIT
The example you've got probably isn't quite right (unless GetFileUpload() actually writes to the cache). Generally your calls to cache look something like:
string GetSomeStringFromCache()
{
string someString = Cache[SomeKey] as string;
if (someString == null)
{
someString = GetStringUsingSomeExpensiveFunction();
Cache.Add(SomeKey, someString, /*a bunch of other parameters*/);
}
return someString;
}
This will put it in the Cache if it's not already there, but if it is, it will just use it.

TempData implementation changes - Reasons for the change

In ASP.NET MVC 2, the lifespan of an entry in the TempDataDictionary was just one HTTP Request.
That translated to setting a value in one request, redirecting, and having access to the same item at the other end of the line. After this the entry would be no longer available, regardless of whether you read the value out of the dictionary at the latter end of the line or not.
Since ASP.NET MVC 3 (I believe), this implementation detail has changed quite significantly.
Entries in the TempDataDictionary are now only removed once they've been read.
MVC 4
public object this[string key]
{
get
{
object obj;
if (!this.TryGetValue(key, out obj))
return (object) null;
this._initialKeys.Remove(key);
return obj;
}
}
and
public bool TryGetValue(string key, out object value)
{
this._initialKeys.Remove(key);
return this._data.TryGetValue(key, out value);
}
MVC 2:
public object this[string key] {
get {
object value;
if (TryGetValue(key, out value)) {
return value;
}
return null;
}
and
public bool TryGetValue(string key, out object value) {
return _data.TryGetValue(key, out value);
}
Since most people seem to put items in the TempData collection in one request and immediately read them back out in the immediate next request, the functionality seems roughtly the same.
In scenarios where this is not the case such as wanting to read the TempData entry if redirected to one place, and expecting it to have been removed if requesting other resources and navigating back, this change has quite an impact.
No longer is the entry available for one http request but is available over many HTTP requests, be it only available to one single get on the dictionary.
I'd like to know more about this implimentation change, what were the reasons for the change, was this simply to cater for multiple redirects or are there deeper benefits?
Secondary to that, I'm intrigued to know if there's anything built in that now caters for single HTTP request sharing of data in the same way that TempData used to cater for?
You're correct that TempData keys are only cleared if they’ve been read (or after the user’s session expires) but this has been the case since MVC2, (http://forums.asp.net/post/3692286.aspx)
I'd like to know more about this implimentation change, what were the
reasons for the change, was this simply to cater for multiple
redirects or are there deeper benefits?
This change prevented problems that arose in MVC 1, such as TempData keys being deleted before they were read. So yes, the primary benefit is in avoiding these problems when you have multiple re-directs, or interleaved requests. In addition, the RedirectToRouteResult or RedirectResult methods now automatically call TempData.Keep() to prevent clearing of keys, even after they've been read so keep that in mind as well.
In scenarios where this is not the case such as wanting to read the
TempData entry if redirected to one place, and expecting it to have
been removed if requesting other resources and navigating back, this
change has quite an impact.
You’re correct, if you've been coding under the assumption that the TempData keys are cleared automatically you could run into unexpected problems. You can call TempData.Clear() to manually remove all keys from the TempDataDictionary, or TempData.Remove(key) to remove a specific key. You can also use TempData.Peek() to read the value of a TempData key without flagging it for removal from the TempDataDictionary.
Secondary to that, I'm intrigued to know if there's anything built in
that now caters for single HTTP request sharing of data in the same
way that TempData used to cater for?
I'm not aware of any new objects or functions that replicate the original implementation of TempData. Essentially we still use TempData but have to be mindful that the data persists until read and clear the dictionary manually if needed.

ASP.NET Caching - Programatically Invalidating Server Cache...confusion on example

I'm reading how to programmatically invalidate cached pages on the server in ASP.NET, and the book ("MCTS Self-Paced Traing Kit (Exam 70-515)") says:
To directly control whether a cached
version of a page is used or whether
the page is dynamically generated,
response to the ValidateCacheOutput
event and set a valid value for the
HttpValidationStatus attribute.
The code segments look like the following:
public static void ValidateCacheOutput(HttpContext context, Object data,
ref HttpValidationStatus status)
{
if (context.Request.QueryString["Status"] != null)
{
string pageStatus = context.Request.QueryString["Status"];
if (pageStatus == "invalid")
status = HttpValidationStatus.Invalid;
else if (pageStatus == "ignore")
status = HttpValidationStatus.IgnoreThisRequest;
else
status = HttpValidationStatus.Valid;
}
else
status = HttpValidationStatus.Valid;
}
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.AddValidationCallback(
new HttpCacheValidateHandler(ValidateCacheOutput),
null);
}
Could someone please explain to me what this code is doing? Also, the main question I have is that I thought Cached pages were simply returned from the server, but the code below indicates that the page life-cycle is being invoked (Page_Load event); I'm confused because the page life-cycle isn't invoked if a cached page is returned, so how would the code in the Page_Load event even fire?
Note: Here's the same example that the book has
I also came across this question. It is too bad that almost every blog post and article I find about this subject dutifully replicates the MSDN example without really explaining how it works.
I don't have a definite answer but I think this works because the page life cycle is invoked at least once. Namely when the page is requested for the first time and thus isn't cached yet.
During that first request the Page_Load is called and the HttpCacheValidateHandler is registered with the Cache object. During all subsequent request for that page, the Cache object is able to call your ValidateCacheOutput() method. And because this method is static the page life-cycle doesn't have to be invoked.
I hope that someone who knows more about this can comment on it but in my opinion this also implies the following:
In the given example the HttpCacheValidateHandler doesn't need to be a static method of the page because it doesn't use any properties of the Page object. It can be a static method on any other object you like.
The ValidateCacheOutput() method will probably be called for every page request, not just for the page which is (ab)used to call Response.Cache.AddValidationCallback(). Maybe i'm missing something obvious but I don't see how the Cache "knows" which HttpCacheValidateHandler belongs to which page.
You are right in that typically cached pages are just returned frm the server but this changes when you use AddValidationCallback. In this case, ASP.NET will call this method to determine whether to returned a cached copy or not. This method should therefore be very light or you will negate the effect of caching.
The code you have listed just checks the querystring for a Status variable and uses the value of this to determine whether to either (1) pull the page from the cache, (2) clear the cached page, re-render it and cache it or (3) just ignore the cache and re-render the page.
See http://msdn.microsoft.com/en-us/library/system.web.httpvalidationstatus.aspx for the status options.

Static data in an ASP.NET page - threadsafe?

The background to this question is that I need to use some user session data in a (static) WebMethod. I have created a static property that references the data I need like so:
private static UserWebSession UserWebSession
{
get
{
return (UserWebSession)HttpContext.Current.Session["UserWebSession"];
}
}
I can then call this in my page's static WebMethod.
My question is, is this technique thread safe? Or will this property's value be updated with every new page request - in other words, it will return the UserWebSession for the user who most recently requested the page?
That's fine - HttpContext.Current is designed precisely for this sort of thing. You won't get a previous user's session.
It's dependent on the thread though (I believe) - so if you start any extra background threads, they won't be able to see the current context.
Also be aware that although this call is safe in terms of not getting the wrong context, the normal concurrency caveats apply when it comes to what you actually do with the context.
I don't know that a Page Method is able to access Session state. If it can, then you may be ok. I recall that access to Session state is serialized, so that only one request at a time can arrive for a given session.

Resources