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

1

6

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?

Councilman answered 12/5, 2015 at 12:39 Comment(5)
can you show us your ProductCategoryType model?Debate
@Debate It's not a model - it's an enum. I'll add it to the question anyway though.Councilman
so where do you bind your quoteId in your action, you must bind it if you wan't to use it as param in VaryByParamDebate
@Debate If I change the quoteId, even without binding it - it caches correctly. The problem still remains if I change part of the name parameter though.Councilman
Relevant: https://mcmap.net/q/1916754/-asp-net-mvc-caching-vary-by-controller-action-parameter and I think since the IIS core is determining whether to serve a request from the cache, controller and action resolution occurs too late for pretty URLs to vary by param. But I can't provide a citation on that.Bays
S
2

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.

Sat answered 13/7, 2015 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.