David
David

Reputation: 2569

ASP.NET MVC: Problem with OutputCache

for my current project it's necessary to generate dynamic CSS...

So, i have a partial view which serves as a CSS deliverer... The controller code looks like this:

    [OutputCache(CacheProfile = "DetailsCSS")]
    public ActionResult DetailsCSS(string version, string id)
    {
        // Do something with the version and id here.... bla bla
        Response.ContentType = "text/css";
        return PartialView("_css");
    }

The output cache profile looks like:

<add name="DetailsCSS" duration="360" varyByParam="*" location="Server" varyByContentEncoding="none" varyByHeader="none" />

The problem is: When i use the OutputCache line ([OutputCache(CacheProfile = "DetailsCSS")]), the response is of content type "text/html", instead of "text/css"... when i remove it, it works as expected...

So, for me it seems that the OutputCache doesn't save my "ContentType" setting here... is there any way around this?

Thanks

Upvotes: 16

Views: 3825

Answers (3)

Jace Rhea
Jace Rhea

Reputation: 5018

You could overwrite the ContentType with your own ActionFilter that executes after the cache has occurred.

public class CustomContentTypeAttribute : ActionFilterAttribute
{
    public string ContentType { get; set; }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.ContentType = ContentType;
    }
}

And then call that attribute after the OutputCache.

[CustomContentType(ContentType = "text/css", Order = 2)]
[OutputCache(CacheProfile = "DetailsCSS")]
public ActionResult DetailsCSS(string version, string id)
{
    // Do something with the version and id here.... bla bla
    return PartialView("_css");
}

Or (and I haven't tried this) but override the "OutputCacheAttribute" class with a CSS specific implementation. Something like this...

public class CSSOutputCache : OutputCacheAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        base.OnResultExecuting(filterContext);
        filterContext.HttpContext.Response.ContentType = "text/css";
    }
}

and this...

[CSSOutputCache(CacheProfile = "DetailsCSS")]
public ActionResult DetailsCSS(string version, string id)
{
    // Do something with the version and id here.... bla bla
    return PartialView("_css");
}

Upvotes: 20

Max Toro
Max Toro

Reputation: 28618

This could be a bug in ASP.NET MVC. Internally they have a type called OutputCachedPage that derives from Page. When OnResultExecuting is called on OutputCacheAttribute they create an instance of this type and call ProcessRequest(HttpContext.Current), which eventually calls SetIntrinsics(HttpContext context, bool allowAsync) that sets the ContentType like this:

HttpCapabilitiesBase browser = this._request.Browser;
this._response.ContentType = browser.PreferredRenderingMime;

Here's a fix:

public sealed class CacheAttribute : OutputCacheAttribute {

   public override void OnResultExecuting(ResultExecutingContext filterContext) {

      string contentType = null;
      bool notChildAction = !filterContext.IsChildAction;

      if (notChildAction) 
         contentType = filterContext.HttpContext.Response.ContentType;

      base.OnResultExecuting(filterContext);

      if (notChildAction)
         filterContext.HttpContext.Response.ContentType = contentType;
   }
}

Upvotes: 12

PatrickSteele
PatrickSteele

Reputation: 14697

Try setting the VaryByContentEncoding as well as VaryByParam.

Upvotes: -1

Related Questions