ASP.NET MVC Caching - Logged-in user gets cached

Hiren Desai

I've a ASP.NET MVC application in which I've implemeneted custom caching filter as below code:

public class NonAuthenticatedOnlyCacheAttribute : OutputCacheAttribute
{
    public NonAuthenticatedOnlyCacheAttribute()
    {
        Duration = 600;  /*default cache time*/
    }

    private bool _partialView;
    public bool PartialView
    {
        get { return _partialView; }
        set
        {
            _partialView = value;
            if (_partialView)
            {
                VaryByCustom = "user";
            }
        }
    }

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (PartialView) OnCachePartialEnabled(filterContext);
        else OnCacheEnabled(filterContext);

        base.OnResultExecuting(filterContext);
    }

    private OutputCacheLocation? originalLocation;
    private int? _prevDuration;

    protected void OnCachePartialEnabled(ResultExecutingContext filterContext)
    {
        var httpContext = filterContext.HttpContext;

        if (!_prevDuration.HasValue) _prevDuration = Duration;
        Duration = httpContext.User.Identity.IsAuthenticated ? 1 : _prevDuration.Value;
    }

    protected void OnCacheEnabled(ResultExecutingContext filterContext)
    {
        var httpContext = filterContext.HttpContext;

        if (httpContext.User.Identity.IsAuthenticated)
        {
            // it's crucial not to cache Authenticated content
            originalLocation = originalLocation ?? Location;
            Location = OutputCacheLocation.None;
        }
        else
        {
            Location = originalLocation ?? Location;
        }

        // this smells a little but it works
        httpContext.Response.Cache.AddValidationCallback(IgnoreAuthenticated, null);
    }

    // This method is called each time when cached page is going to be
    // served and ensures that cache is ignored for authenticated users.
    private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
    {
        validationStatus = context.User.Identity.IsAuthenticated
          ? HttpValidationStatus.IgnoreThisRequest
          : HttpValidationStatus.Valid;
    }
}

The problem I'm facing is, even though I'm not caching the page for authenticated user, sometimes I'm seeing a cached page of some other authenticated user. This happens rarely and randomly.

If I debug through this, it works perfectly fine but not when it occurs on LIVE site. What I'm also seeing is, a cookie (".AspNet.ApplicationCookie") of the authenticated user gets created in browser as well. (Does it mean that output cache is also caching response cookies as well?) If I delete this cookie then user gets logged out which is obvious.

In Global.asax, I have following code:

public override string GetVaryByCustomString(HttpContext context, string value)
    {
        if (value.Equals("culture") || value.Equals("user"))
        {
            var customString = Thread.CurrentThread.CurrentUICulture.Name;
            if (context.User.Identity.IsAuthenticated)
            {
                customString = $"{context.User.Identity.Name}-{customString}";
            }
            return customString;
        }
        return base.GetVaryByCustomString(context, value);
    }

And on controller, below attribute is cached

[NonAuthenticatedOnlyCacheAttribute(Location = System.Web.UI.OutputCacheLocation.Server, Duration = 600, VaryByCustom = "user")]
johey

I think the problem may be that you did not tell ASP.NET what you mean with:

VaryByCustom = "user"

Maybe you did that, but the code is not included in your post. In your Global.asax.cs you will have something like:

public override string GetVaryByCustomString(HttpContext context, string arg) 
{ 
    if (arg.Equals("User", StringComparison.InvariantCultureIgnoreCase)) 
    {
        var user = context.User.Identity.Name; // TODO here you have to pick an unique identifier from the current user identity
        return string.Format("{0}@{1}", userIdentifier.Name, userIdentifier.Container); 
    }

    return base.GetVaryByCustomString(context, arg); 
}

You can find more information on this here and here.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Get role/s of current logged in user in ASP.NET Core MVC

Prevent Caching in ASP.NET MVC for specific actions using an attribute

ASP.NET Identity record user registration and last logged on time

Get UserID of logged-in user in Asp.Net MVC 5

ASP.NET MVC FormsAuthentication check if user logged in

Asp.net Identity: change user role while logged in

How to authorize user who logged in using external login in Asp.Net MVC

Caching of ASP.NET MVC Web API results

Check if user is logged in with Token Based Authentication in ASP.NET Core

ASP.NET MVC: Get user id of currently logged in user

How can keep the user logged in even after the browser has closed with Identity ASP.NET MVC framework?

How to check if currently logged-in user is Azure Active Directory B2C "Global Administrator"? ASP.NET MVC

How to get items for logged in user ASP.NET MVC

Asp.net Core Caching + IE 11 Results in Cached Responses

Check if user is logged on in ASP.NET Core

How to get the currently logged in user name through an interface to insert in updated by column in asp.net core mvc?

Error getting products from the logged in user. ASP.NET Core MVC

Asp.net MVC image caching in browser

Get Logged in User Role: Asp.net MVC5

CustomAuthorizeAttribute redirects to LoginView even when the user is logged in (ASP.Net MVC 5)

ASP.Net MVC ActionResult returns cached View?

How to obtain the name of the current user logged into my ASP.NET MVC website?

Displaying posts made by user that is logged in - c#, asp.net

Successfully logged in user keeps getting redirected to AccessDeniedPath using ASP.NET MVC CookieAuthentication

How to Upload File using Application Pool identity instead of Logged User Identity- ASP.NET MVC Impersonation

How to get logged user data in ASP.NET Core 5 MVC (.NET 5)?

ASP.NET MVC How to be logout when same user is logged in from different computer

asp.net mvc6 Authorization redirect do not work when user is not logged

ASP.NET MVC create "Add to favorite" button for logged in users