Using outputcache in MVC - asp.net-mvc

I have an action declared as following
[Route("{language}/Navigation/Test")]
[OutputCache(Duration = 3600, VaryByParam = "none")]
public ActionResult Test()
{
return View();
}
In order to check outputcache setting I added #DateTime.Now.Ticks.ToString() in view Test.cstml
What troubles me is that when i run http://localhost/EN/Navigation/Test first time, view gets cached and page refresh returns a same number of ticks. Now if i change language and set http://localhost/DE/Navigation/Test number of tick changes, ie. view is not served from cache.
I tried to remove VaryByParam = "none" but is always produces the same results.
What is wrong here, how to serve a cached view not matter what language is used.

VaryByParam varies by the parameters passed in a URL. I.e. The URL www.stackoverflow.com/page?param1=5. Because DE is a different URL to EN, the page won't be found in the cache so it requests a new one.
From MSDN
A semicolon-separated list of strings used to vary the output cache. By default, these strings correspond to a query string value sent with GET method attributes, or a parameter sent using the POST method. When this attribute is set to multiple parameters, the output cache contains a different version of the requested document for each specified parameter. Possible values include none, *, and any valid query string or POST parameter name.
Bottom line: It's based on URL, not routing. You are able to configure based on the query string but no more.

Related

VaryByParam not working properly in MVC

In my MVC project I am using OutCache for caching a page. And I also use .htaccess so that for 2-3 different url it gets same page.
I am using VaryByParam to store page in cache. When I hit the any one url with some query string it store the output in cache perfectly but when I hit the different url (which redirect to the same controller as for the first one) with same query string which I used first time it will store different copy for this time.
I don't understand why it is happening as VaryByParam stores data based on Query String and not based on the URL.
Here is my code.
Controller: Main.cs
[OutputCache(Duration=200,VaryByParam="*")]
public ActionResult Details(Filter filter)
{
//some code
}
here Filter is Class to store query string based on its parameter.
.htaccess
RewriteRule ^cars/get-details/ /main/details/ [QSA,NC,L]
So when I hit http://localhost/main/details/?car=1 it store page in cache and works fine if I hit same url I will get data from cache but when I hit http://localhost/cars/get-details/?car=1 rather then fecthing from cache it store another copy for this.
I don't understand why it is happening.Any help would work.

Page output cache in MVC

I need to cache the page specific to logged in user. So I used as mentioned below:
[OutputCache(Duration = 10, VaryByParam = "Id", Location = OutputCacheLocation.Client)]
public ActionResult PartialPageOutputCaching(string Id)
{
return PartialView("PartialPageOutputCaching");
}
OutputCacheLocation.Client did not work for me as it is serving new request every time. I tried to search storing page output cache specific to user, but could not find the right working sample. Please let me know, how OutputCacheLocation.Client suppose to work.
I tried VaryByParam = "Id" assuming that, based on the action methods parameter page content will be cached, but looks like it works on query string parameter. Please confirm how VaryByParam suppose to work.
Thanks in advance.
OutputCacheLocation.Client means that it will cache on the client, meaning in the browser your user is using. Also there is really not much advantage of caching for a specific user, as user already has the page rendered and chances that he will open the same page are small to take advantage of that cache.

Appending ?param= to mvc routes

Some MVC sites have querystring params appended to the route Url (of which I noticed StackOverflow does), such as:
https://stackoverflow.com/questions/tagged/java?page=9802&sort=newest&pagesize=15
What are the advantages of having the parameters as more conventional ?querystring params, rather than /param/values/ ?
Also, how are these params appended to routes that have been set up? I'm familiar with setting up mvc routes with params like "users/details/{id}" etc. but don't know how to configure routes for use with 1 or more ?params as per the example url above?
Query string parameters are useful when you have multiple optional parameters and don't want to include default values for non-specified parameters just to satisfy a path.
And you don't have to do anything special to include these parameters in a rendered URL.
Take the following route for example:
routes.MapRoute
(
"QuestionsTagged",
"questions/tagged/{tag}",
new { controller = "Questions", action = "Tagged" }
);
If you render a link to that route using:
Url.RouteUrl
(
"QuestionsTagged",
new
{
tag = "java",
page = 9802,
sort = "newest",
pagesize = 15
}
)
...then the routing engine is smart enough to see that the route contains a parameter named tag and that the passed route values object also has something named tag so it uses that value in the route.
Any provided route values that don't have corresponding parameters in the route (page, sort and pagesize in this case) get tacked on as query string parameters. So the Url.RouteUrl call above would return /questions/tagged/java?page=9802&sort=newest&pagesize=15.
And your action method can explicitly list these parameters in its signature (promotes readability and maintainability) or you can access them via Request.QueryString.
public class QuestionsController : Controller
{
// I can explicitly list the parameters in my signature and let routing do
// its magic, like this...
public ViewResult Tagged(string tag, int? page, int? pagesize)
{
// ...or I can grab parameters like this:
string sort = Request.QueryString["sort"];
return View();
}
}
Note that the parameters to the action method do not have to match the parameters specified in the route. (In the route, I only specified tag, but the action method's signature lists tag, page, and pagesize.) However, any parameter of the action method that is not also a parameter of the route must be a reference or nullable type.
I've normally seen paging and filtering data be passed as querystring parameters since it gives information to the user in the URI. It is also normally harmless if a user alters this data since it will just filter the data you see on the page. Any sensitive data is normally posted so as it is not as easily seen or modified, but I would argue to keep your URI's clean and use quesrystrings as little as possible.
You don't need to do anything special when specifying routes to be able to handle quesrystrings. They will just be extra data that is passed to your action. On your action you will need to do some work to handle the data though. Using your querystring above you will have to specify the querystring names as the parameter names and then whatever datatype you are expecting.
public ActionResult Index (int page, string sort, int pagesize)
In this example, page will be the value of 9802, sort will be "newest" and pagesize will be 15.

Asp.net MVC Output cache

Im thinking in use the Output cache attribute for caching views in MVC.
My question is simple:
When i use output cache attribute on top of an action method, if in the next request the view was cached the action is not executed right?
Yes, you are correct. This is easliy tested:
[OutputCache(Duration=10, VaryByParam="id")]
public function TestCache()
{
return Content(" I was generated at " + DateTime.Now);
}
However, you can invalidate the cache using the VaryByParam property, which allows you to control the cache depending on request parameters or similar.
In my example, the cache will vary depending on which id is specified in the request parameters. This is useful when you have a dynamic page which loads data from the database.
Yes you are right , the cached action is not executed unless you use varyByParam or some other property of that attribute.

ASP.NET MVC Action Method Parameters from Querystring don't change after first request

I have an action method in a controller that needs to do paging. I am passing a page number and pagesize parameter in the querystring. The problem I am having is that the first request I make sets the parameters for all subsequent calls.
public ActionResult GetStuff(string key, int? page, int? pageSize)
{
// do something magical
}
My route looks like this:
routes.MapRoute("GetStuff", "Stuff/{key}", new {controller = "Stuff", action = "GetStuff"});
When I start debugging my app, I go to the url /Stuff/My_Stuff and the key parameter is correct, and both page and pagesize are null as I would expect. If I make a second call with the url /Stuff/My_Stuff?page=2&pageSize=3 then the values of page and pageSize are still null. If I restart the app, and make my first call include page and pagesize parameters, everything works as I would expect, but then changing those values on subsequent calls retains the values from the first call. In fact, even the key parameter, which is part of my route will keep the same value, even if I change my Url. What am I missing?
I am using IIS 6.1 on Windows Server 2003. I am using extensionless routes. Also, the actual code is in VB.Net, but I don't think that should matter. But for full disclosure, the above code is only representative of my actual code, and not the actual code.
I had the same problem because I used a DI Container (Castle Windsor) to create my Controllers. The problem arose because of the lifetime settings of Controller classes, because the default lifetime policy in Castle is Singleton (a weird default if you ask me).
It seems that because the Controller instance is only created once in the application's lifetime, the parameters get stuck on their first values.
Setting the lifetime to Transient solved the problem in my case.

Resources