globetrotter
globetrotter

Reputation: 1047

Not caching [ChildActionOnly] action not working in ASP.NET MVC

In my ASP.NET MVC app, I have a MenuController with an Index method decorated with [ChildActionOnly]:

public class MenuController : Controller
{
    [OutputCache(Location=OutputCacheLocation.None, Duration=0, NoStore=true)]
    [ChildActionOnly]
    public PartialViewResult Index()
    {
        return PartialView();
    }
}

It's Index.cshtml partial view simply returns a login/logoff nav menu based on whether the user is logged in or not:

@using Microsoft.AspNet.Identity
@if (Request.IsAuthenticated)
{
    using (Html.BeginForm("logoff", "account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" }))
    {
        @Html.AntiForgeryToken()
        <ul class="nav navbar-nav navbar-right">
            <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-at"></i> @User.Identity.GetUserName() <span class="caret"></span></a>
                <ul class="dropdown-menu" role="menu">
                    <li><a href="~/manage" class="dropdown" title="Manage your account"><i class="fa fa-user fa-lg"></i> Account</a></li>
                    <li class="divider"></li>
                    <li><a href="javascript:document.getElementById('logoutForm').submit()" title="Log out"><i class="fa fa-sign-out fa-lg"></i> Log out</a></li>
                </ul>
            </li>
        </ul>
    }
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li>@Html.ActionLink("Sign up", "register", "account", routeValues: null, htmlAttributes: new { @class = "btn btn-signup", id = "registerLink" })</li>
        <li>@Html.ActionLink("Log in", "login", "account", routeValues: new { returnUrl = @Request.Path }, htmlAttributes: new { id = "loginLink" })</li>
    </ul>
}

I am calling this from my shared _Layout.cshtml file as such:

@{ Html.RenderAction("Index", "Menu"); }

What I'm trying to accomplish is for that particular menu item to never be cached so that no user information are cached. However for pages where caching takes place such as my HomeController:

public class HomeController : Controller
{
    [OutputCache(CacheProfile = "OneHour", Location=OutputCacheLocation.Server, VaryByParam = "None")]
    public async Task<ActionResult> Index()
    {
        //..some code
        return View(model);
    }

    [ChildActionOnly]
    [OutputCache(Duration = 86400, VaryByParam = "None")]
    public PartialViewResult Other()
    {
        //some code..
        return PartialView(otherModel);
    }
}

...the solution doesn't work: if I go to an uncached page, navigate to logout, then head back to /Home/Index the menu still shows me as logged in.

What am I missing here? Should the MenuController and it's view be in the Shared folder instead?

Upvotes: 2

Views: 752

Answers (1)

YEH
YEH

Reputation: 394

[ChildActionOnly] and [OutputCache(/*with anything other than Duration*/)] is very limited in its implementation from the framework source, you have to either implement your own cache attribute class by using : OutputCacheAttribute base class, or create an automatic sign out when the user closes page or whatever, that's what I can think of for now.

Upvotes: 1

Related Questions