views:

528

answers:

3

Hi,

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

A: 

Try setting the VaryByContentEncoding as well as VaryByParam.

Patrick Steele
no, that wasn't it..
David
Oops. Yeah, that wouldn't work. ContentType != ContentEncoding!! Sorry, my bad.
Patrick Steele
A: 

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;
Max Toro
+2  A: 

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 than 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");
}
Jace Rhea
thanks!!!.. the actionfilter actually did it!
David