1

On my website I have a header defined in my _Layout.cshtml. In that file, I'm doing this:

<li class="dropdown">
    @if (Request.IsAuthenticated)
    {
        <a href="#" class="dropdown-toggle menuItem" data-toggle="dropdown" style="color: red;">@User.Identity.Name <b class="caret"></b></a>
    }
    else
    {
        <a href="#" class="dropdown-toggle menuItem" data-toggle="dropdown">Profile <b class="caret"></b></a>
    }

    <ul class="dropdown-menu">
        @if (!Request.IsAuthenticated)
        { 
            <li><a href="/Account/Register">Register</a></li>
            <li><a href="/Account/Login">Login</a></li>
            <li><a href="/Account/ForgotPassword">Forgot Password</a></li>
        }
        else
        { 
            <li><a href="/Account/ChangePassword">Change Password</a></li>
            <li><a href="/Account/EditProfile">Edit Profile</a></li>
            <li><a href="/Account/Logout">Logout</a></li>
        }
    </ul>
</li>

So, I'm wanting to dynamically display my menu item name, as well as the contents based on whether the user is logged in or not.

99% of the methods in all of my controllers implement the [OutputCache] attribute. Because of this, after I login to the site, the menu item still says "Profile" with the corresponding menu items that go along with Profile (aka Register, Forgot Password, etc).

Do I have to turn off caching in my site in order for the username to show up immediately after logging in? This works perfect in my Development environment because I use #IF DEBUG statements around my caching attributes...

For example, here's my HomeController:

#if !DEBUG
    [OutputCache(Duration = 86400)]
#endif
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
ganders
  • 7,285
  • 17
  • 66
  • 114
  • It could be even worse... Supposing the page is cached when you're logged in... Sensitive info might be leaked. I wonder if donut caching is supported now in mvc... – spender May 01 '14 at 12:21
  • 1
    MvcDonutCaching https://github.com/moonpyk/mvcdonutcaching – spender May 01 '14 at 12:23
  • @spender very interesting, so would I need to specify both the DonutCache, as well as the regular OutputCache attribute everywhere? Or do I replace my OutputCache and use DonutCache instead? – ganders May 01 '14 at 12:31
  • Can't help, I'm afraid. This wasn't available last time i needed it! – spender May 01 '14 at 12:32
  • @spender sorry, just re-read it, it says to replace....I'll give that a shot tonight when I can work on my project more, thanks. – ganders May 01 '14 at 12:32

1 Answers1

1

I have used the donut caching library (mentioned by spender in the comments above) to solve a very similar problem.

Once your project has a reference to the MvcDonutCaching library, you can call an extended Html.Action method to exclude it from the cache e.g.

// Action(this HtmlHelper htmlHelper, string actionName, string controllerName, bool excludeFromParentCache)
@Html.Action("LoginStatus", "Home", true) 

To do this, you obviously would need to isolate the part you don't want to cache to its own action and partial view.

Electric Sheep
  • 3,867
  • 1
  • 29
  • 38
  • So it sounds to me that the current method of using the built-in Request.IsAutheticated right in my header will NOT work, even with the donut caching. I'll need to re-factor, and my header will have to be static on all pages... – ganders May 01 '14 at 15:39
  • I can't see any reason it wouldn't work. In your _Layout file you would replace the HTML you have posted with an `Html.Action` call to a controller method that renders the a partial view containing the HTML. – Electric Sheep May 01 '14 at 15:45
  • Oh, I guess I just assumed that I couldn't throw the partial view into the
  • element...
  • – ganders May 01 '14 at 15:45
  • 1
    You can throw it pretty much wherever you like :) – Electric Sheep May 01 '14 at 15:46