This is a migrated thread and some comments may be shown as answers.

Extending WebAssetHttpHandler

2 Answers 74 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Binu Thayamkery
Top achievements
Rank 1
Binu Thayamkery asked on 21 Dec 2010, 06:29 PM
I am using SharedWebAssets to combine and compress all our JS script groups. I want to extend the WebAssetHttpHandler to  minify scripts before we compress the response. How do we do this? 
(I took an initial stab at this, but looks like there ProcessRequest() of the handler is using some internal methods, etc... so looking for pointers here)

Thanks!

[Edited: 12/21/2010]
I have figured out how to do this (think Reflection), I will post my complete finds for anyone who are interested soon.
 

2 Answers, 1 is accepted

Sort by
0
William Hurst
Top achievements
Rank 1
answered on 06 Feb 2011, 08:07 PM
Did you manage to complete this? I am looking to do the same thing.
0
Binu Thayamkery
Top achievements
Rank 1
answered on 07 Feb 2011, 07:47 PM
Yes William. I created an extension to the AssetHttpHandler. Please note that my code does work only for SharedWebAssets. Also we found that there is a bit of issue with Caching. If you set your Asset Groups to cache, Asset Handler will be called only when this cache expires. So that means even if you have a new release, user's browser will not be requesting asset.axd. Workaround for this (as given by telerik support) is to have a file name change within each asset group, example: stick version to at least one file. Our solution was to add a versio0000.js and rename it with the build version as a post build event. We are currently testing this solution.
using Yahoo.Yui.Compressor;
:
:
public
override void ProcessRequest(HttpContextBase context)
{
    var id = context.Request.QueryString[IdParameterName];
    var content = String.Empty;
    HttpResponseBase response = null;
    var minifyScripts = !bool.Parse(ConfigurationManager.AppSettings["DebugJavaScript"]);
 
    if (string.IsNullOrWhiteSpace(id)) return;
 
    var findScriptGroups = typeof(SharedWebAssets).GetMethod("FindScriptGroup",
                                                             BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
 
    var findStyleGroups = typeof(SharedWebAssets).GetMethod("FindStyleSheetGroup",
                                                            BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
 
 
    var group = findScriptGroups.Invoke(null, new object[]{id}) as WebAssetGroup
                ?? findStyleGroups.Invoke(null, new object[] { id }) as WebAssetGroup;
 
     
    if (group != null)
    {
        response = context.Response;
        // Set the content type
        response.ContentType = group.ContentType;
 
        var reader = typeof(WebAssetHttpHandler).GetField("reader", BindingFlags.NonPublic | BindingFlags.Instance);
        if (reader != null)
        {
            var assetGroupReader = reader.GetValue(this) as IWebAssetGroupReader;
            if (assetGroupReader != null)
                content = assetGroupReader.Read(group);
        }
 
        //Minify
        if (minifyScripts && response.ContentType.ToLower() == "text/javascript")
        {
            content = JavaScriptCompressor.Compress(content,
                                                    false, // Verbose Logging
                                                    true// Obfuscate JavaScript
                                                    true// Preserve all semi colons
                                                    false, // Disable Optimizations
                                                    -1,    // Line Break Position
                                                    Encoding.Default,
                                                    CultureInfo.CurrentCulture,
                                                    false // Ignore Eval
                                                    );
        }
    }
 
    if (string.IsNullOrWhiteSpace(content) || group == null) return;
 
    // Compress
    if (group.Compress && !context.IsMono())
    {
        var httpResponseCompressor = typeof (WebAssetHttpHandler).GetField("httpResponseCompressor",
                                                                           BindingFlags.NonPublic | BindingFlags.Instance);
 
        if (httpResponseCompressor != null)
        {
            var responseCompressor = httpResponseCompressor.GetValue(this) as IHttpResponseCompressor;
            if (responseCompressor != null)
                responseCompressor.Compress(context);
        }
    }
    // Write
    using (var sw = new StreamWriter((response.OutputStream)))
    {
        sw.Write(content);
    }
    // Cache
    if (!context.IsDebuggingEnabled)
    {
        var httpResponseCacher = typeof (WebAssetHttpHandler).GetField("httpResponseCacher",
                                                                       BindingFlags.NonPublic | BindingFlags.Instance);
 
        if (httpResponseCacher != null)
        {
            var responseCacher = httpResponseCacher.GetValue(this) as IHttpResponseCacher;
            if (responseCacher != null)
                responseCacher.Cache(context, TimeSpan.FromDays(group.CacheDurationInDays));
        }
    }
}
Good Luck!
[Edited 02/08] - In order to get caching to work, we ended up adding our build version to our asset group names. This way when we have a new release out, asset.axd url changes and it will invalidate browser cache.
Tags
General Discussions
Asked by
Binu Thayamkery
Top achievements
Rank 1
Answers by
William Hurst
Top achievements
Rank 1
Binu Thayamkery
Top achievements
Rank 1
Share this question
or