Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 511
David Avatar asked Nov 18 '09 11:11

David


2 Answers

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");
}
like image 80
Jace Rhea Avatar answered Oct 23 '22 18:10

Jace Rhea


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;
   }
}
like image 21
Max Toro Avatar answered Oct 23 '22 17:10

Max Toro