Use OutputCache and GetVaryByCustomString to cache same content for multiple paths
Asked Answered
I

1

9

I have the following code in my MVC controller:

[HttpGet]
[OutputCache(Duration = 3600, VaryByParam = "none", VaryByCustom = "app")]
public async Task<ViewResult> Index(string r)
{
   // Stuff...
}

And I have the following implementation of GetVaryByCustomString in my Global.asax.cs class:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
        switch (arg.ToLower())
        {
            case "app":
                return context.Request.Url.Host;

            default:
                return base.GetVaryByCustomString(context, arg);
        }
    }

In our application, customers will have their own subdomain (i.e. johndoe.app.com, janedoe.app.com).

So caching should vary on subdomain.

However, any "path" on that fully qualified URL should share the same cache. So the following should read the same output cache:

  • johndoe.app.com/
  • johndoe.app.com/123
  • johndoe.app.com/abc

There's an exhausting reason why this is the way it is, but in short, it's a SPA app, and the "path" is really just a tracker. This can't be changed to a query string.

When the path (tracker) changes, the index method is freshly accessed. I can tell this through the debugger. As a note, GetVaryByCustomString is still called, but it's called after the Index method has been processed.

How can I vary cache based on subdomain, but use that cache regardless of the path (tracker) on the URL?

If it offers anything benefical, here's my MVC routes:

routes.MapRoute(
            name: "Tracker",
            url: "{r}",
            defaults: new { controller = "Home", action = "Index", id = "" });

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

MVC version 5.2.3, .NET 4.6.1

Impersonate answered 11/7, 2017 at 5:35 Comment(6)
I am not sure if this work but cant you implement GetVaryByCustomString as a custom Filter if you want it be executed before index action??Teeter
@RAHULSR I don't think so. You have to override it at in the Global.asax.cs. I could implement a custom caching solution, involving action filters, or Global web handlers, or something of the like, but that wouldn't be ideal.Impersonate
Add how about putting it in the constructor of the controller??please share your answer too i am a bit curious nowTeeter
Just a suggestion but you could translate the subdomain into a parameter and cache on that. I've found a couple of blogs that make reference to this. See the following gist: gist.github.com/IDisposable/77f11c6f7693f9d181bbCyclometer
@JohnBabb Yes, this is what I was going to do. Glad to see the idea validated. Basically write an IIS re-write rule that translates the path to a query string. Then .NET can take it from there w/ the VaryByParam setting.Impersonate
@Impersonate this could be done in iis or you could do something similar in the MVC framework. Looks like it would be a little more straight forward and a cleaner implementation. benjii.me/2015/02/subdomain-routing-in-asp-net-mvcCyclometer
R
1

Have you tried to use: VaryByHeader = "Host" ?

[HttpGet]
[OutputCache(Duration = 3600, VaryByHeader = "Host")]
public async Task<ViewResult> Index(string r)
{
   // Stuff...
}

More information how to do this in different ways you can find here:

Output cache for multi-tenant application, varying by hostname and culture

Rennarennane answered 5/9, 2017 at 19:47 Comment(3)
Vary by host is good for varying by subdomains and the like. But this is the same domain, protocol, etc, just a variance in paths.Impersonate
You don't achieve this because everything afther subdomain is controlled by your SPA application controllers. If you had cached parts after subdomain it would mean that you couldn't control url from your SPA application.Swifter
@Impersonate I found such a solution: techblog.dorogin.com/… . Can you send Feedback?Swifter

© 2022 - 2024 — McMap. All rights reserved.