Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OutputCache VaryByParam is varying by parameter that isn't supposed to be included

I'm using OutputCache in MVC 5 to Cache a view on the server.

I only want to cache a view based on two parameters in the query string.

Action Method

[HttpGet]
[OutputCache(Location = OutputCacheLocation.Server, Duration = 60*10, VaryByParam = "id;quoteid")]
public ActionResult MyAction(int id, ProductCategoryType category)
{
    return Content(DateTime.Now.ToString());
}

Route

context.MapRoute(
"MyCustomRoute",
"myarea/{controller}/{action}/{id}/{category}/{name}/{quoteId}",
new { controller = "MyController", name = UrlParameter.Optional, quoteId = UrlParameter.Optional },
new[] { "MyNamespace.Areas.MyArea.Controllers" });

The URL

http://localhost:17191/myarea/mycontroller/myaction/2/1/a-holiday/aquoteid

This works and binds the data correctly, however, if I change any part of the {name} part of the URL, it still generates a new cache item, even though in my action method I've speficied VaryByParam="id;quoteid"

For example...

http://localhost:17191/myarea/mycontroller/myaction/2/1/a-holiday/somequoteid

and

http://localhost:17191/myarea/mycontroller/myaction/2/1/another-holiday/somequoteid

...are generating different DateTime outputs - but they shouldn't - they should be identical.

What have I done wrong and how can I achieve the desired behaviour?


Edit

Just to be clear, ProductCategoryType is an Enum that is being bound via it's int value. The binding for this is correct when I debug the ActionResult

Edit 2 Since I've been asked to show ProductCategoryType, I've added it below. This does bind correctly when I debug though - I don't think it has anything to do with the problem.

public enum ProductCategoryType
{
    TourActivity = 1,
    Accommodation = 2,
    BusPass = 3,
    SelfDrive = 4,
}

Edit 3

Changing the URL to: http://localhost:17191/a/products/view/2/1?name=test1&quoteid=123

And the cache now works as expected - but how can I achieve this with the prettier URL via routing?

like image 899
Alex Avatar asked May 12 '15 12:05

Alex


1 Answers

The mechanism using VaryByParam acts specifically on the querystring or post parameters of the actual raw HTTP request, and has no awareness of any URL routings mapping that raw request onto some other form. So, in your case, it won't see the id or quoteid parameters at all (since they're not actually in the raw requests's querystring or post).

It will, however, notice that the URL itself (before any '?', including the name) is different, and vary caching on that.

You may need to consider using VaryByCustom instead. See here for an example. And there's a very similar SO-question example here.

like image 188
Thogek Avatar answered Nov 15 '22 00:11

Thogek