When we use the [OutputCache] attribute, content could be cached in three locations: the web server, any proxy servers, and the
web browser. We can control exactly where content is cached by
modifying the Location property of the [OutputCache] attribute.
The Location property can be set to any one of the following values,
- Any
- Client
- Downstream
- Server
- None
- ServerAndClient
By default, the Location property has the value
Any. However, there are
situations in which one might want to cache only on the browser or only
on the server. For example, if you are caching information that is
personalized for each user then you should not cache the information on
the server. If you are displaying different information to different
users then you should cache the information only on the client.
Add code below into the OutputCacheController,
- [OutputCache(Duration = 3600, VaryByParam = "none")]
- public string GetName()
- {
- return "Hi " + User.Identity.Name();
- }
-
- [OutputCache(Duration = 3600, VaryByParam = "none", Location = OutputCacheLocation.Client, NoStore = true)]
- public string GetName1()
- {
- return "Hi " + User.Identity.Name();
- }
The output of the GetName() action is cached with no locaiton (location by default: Any), while GetName1() action is cached with location at Client. Notice that the [OutputCache] attribute in GetName1() action also includes a NoStore property. The NoStore property is
used to inform proxy servers and browser that they should not store a
permanent copy of the cached content.
Update the code in Views/home/index.chtml:
- @{
- ViewBag.Title = "Home Page";
- }
-
-
- <div class="row">
- <div class="col-md-4">
- <h2>Time Cached</h2>
- <li>@Html.ActionLink("No Cache", "NoCache", "OutputCache")</li>
- <li>@Html.ActionLink("Outpu Cache: duration = 10 senc", "Index", "OutputCache")</li>
- </div>
- <div class="col-md-4">
- <h2>Client Side Cache</h2>
- <li>@Html.ActionLink("Get Name | Server Cache", "GetName", "OutputCache")</li>
- <li>@Html.ActionLink("Get Name | Client (Browser)Cache", "GetName1", "OutputCache")</li>
- </div>
-
- </div>
Register at least one user such as:
If we logout, click these two links again, then we will see, the one, that the content is cached on the client browser and not on the
server, will get the correct name, i.e.
- when login, get "Hi, test@hotmail.com",
- when not login get "Hi" only.
While another one, that the content by default is cached on the server, will get the same name for both login or log out situations as "Hi, test@hotmail.com", which is the result of the first request, but not correct for the second request, the log out situation.
Varying the Output Cache: VaryByParam
In some situations, one might want different cached versions of the
very same content. Imagine, for example, that you are creating a
master/detail page. The master page displays a list of movie titles.
When you click a title, you get details for the selected movie.
If you cache the details page, then the details for the same movie
will be displayed no matter which movie you click. The first movie
selected by the first user will be displayed to all future users.
You can fix this problem by taking advantage of the VaryByParam
property of the [OutputCache] attribute. This property enables you to
create different cached versions of the very same content when a form
parameter or query string parameter varies.
Examine our MoviesController created from the PreSetup app, the action named Index() is the Master and the action Details(int? id) is the Detail. The Master action returns a list of movie
titles and the Details(int? id) action returns the details for the selected
movie.
We add a VaryByParam property with the value
"none" to both Master action, Index(), and Details action, Details(int? id).
-
- [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
- public ActionResult Index()
- {
- return View(db.Movies.ToList());
- }
-
-
- [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
- public ActionResult Details(int? id)
- {
- if (id == null)
- {
- return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
- }
- Movie movie = db.Movies.Find(id);
- if (movie == null)
- {
- return HttpNotFound();
- }
- return View(movie);
- }
When the Master action is invoked, the same cached version of
the Master view is returned. Any form parameters or query string
parameters are ignored. If you refresh the browser, it will not make a request from the server
to execute the code to get a new version of data, instead to use the
server chached version. If you add a debug point in the code, you will
see exactly what the process is doing.
The Details() action also includes a VaryByParam property with the value
"none" in our code now. We expected that the behavior is the same as the Master action that the same cached version of the detailed view is returned for any different parameters. However, it is not, for exampe, when id = 1 and id = 2, you got two different versions:
Exame the link, we found out that those are two different addresses, one is
- https://localhost:44374/Movies/Details/1, another is
- https://localhost:44374/Movies/Details/2,
instead of one address with two different parameters. Therefore, they must have an independent version cached by themselves.
Now, if we change the address like this
- https://localhost:44374/Movies/Details?id=1, and
- https://localhost:44374/Movies/Details?id=2,
then we will get the same cached version: the one that the first time be requested.
For example, we choose the parameter id = 3 the first time; if we change the id, and refresh the browser, we will get exactly the same version as the case: id = 3.
Now, we modify the VaryByParam property with the value
"Id" for the detias action. When different values of the Id parameter are passed to the
controller action, different cached versions of the Details view are
generated.
-
- [OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
- public ActionResult Index()
- {
- return View(db.Movies.ToList());
- }
-
-
- [OutputCache(Duration = int.MaxValue, VaryByParam = "id")]
- public ActionResult Details(int? id)
- {
- if (id == null)
- {
- return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
- }
- Movie movie = db.Movies.Find(id);
- if (movie == null)
- {
- return HttpNotFound();
- }
- return View(movie);
- }
It is important to understand that using the VaryByParam property
results in more caching and not less for one specific caching (with one address). A different cached version of the
Details view is created for each different version of the Id parameter.
Finally, one can set the VaryByParam property to the following values,
* = Create a different cached version whenever a form or query string parameter varies.
none = Never create different cached versions
Semicolon list of parameters = Create different cached versions
whenever any of the form or query string parameters in the list varies