Search code examples
asp.net-mvcasp.net-mvc-3cachingasp.net-mvc-2action-filter

No trailing slash in hostname, HttpResponse.RemoveOutputCacheItem doesn't work


I'm in a bit of a pickle here.

I have an action for which the output is fairly static, until another action is used to update the datasource for the first action. I use HttpResponse.RemoveOutputCacheItem to remove that action's cached output so that it is refreshed next time the user loads it.

Basically I have an action like this:

[OutputCache(Duration=86400, Location=OutputCacheLocation.Server)]
public ActionResult Index()
{
    return ...
}

on my HomeController, and another action on another controller that updates the information used in the former:

public ActionResult SaveMenu(int id, Menu menu)
{
    ...
    HttpResponse.RemoveOutputCacheItem(Url.Action("Index", "Home"));
    ...
}

The crazy thing is that this works, as long as you're either loading the URLs http://site/ or http://site/Home/Index. When you use the URL http://site it never refreshes.

Why is that?


Solution

  • It has to do with the way the OutputCacheAttribute works, specifically on its dependency on RouteData not being null. The relevant part is:

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }
        if (!filterContext.IsChildAction)
        {
            new OutputCachedPage(this._cacheSettings).ProcessRequest(HttpContext.Current);
        }
     }
    

    The ResultExecutingContext filterContext derives from ControllerContext. This is the source for ControllerContext.IsChildAction:

    public virtual bool IsChildAction
    {
        get
        {
            RouteData routeData = this.RouteData;
            if (routeData == null)
            {
                return false;
            }
            return routeData.DataTokens.ContainsKey("ParentActionViewContext");
        }
    }
    

    So, why is this relevant to your question?

    Because when you omit the "/" then your Route does not match anything. The default route is "/". An article that explains this more in depth is here: http://www.58bits.com/blog/2008/09/29/ASPNet-MVC-And-Routing-Defaultaspx.aspx . It was written to explain why the Default.aspx file was necessary in ASP.NET MVC 1 projects, but the reason is rooted in the same place.

    So, basically, the RouteData is null, so the OutputCacheAttribute can't work. You can solve your problem by doing what Michael Jasper suggested and leveraging URL Rewriting.