5

I have a controller action that returns a large amount of dynamic JavaScript (gets served once to the client) and I already have GZip compression enabled. One thing I'd like to do is read the executed result stream and apply JS minification on it.

Is it possible to do this using an Action Filter Attribute. I think my question boils down to - Assuming my minifier takes a string of JavaScript is there a way to pull the executed result as a string out of View(view).ExecuteResult(ControllerContext) ?

2
  • Have you considered minify on publish? You can do this using ms build, this is the one we use code.google.com/p/antix-software/wiki/MSBuild Commented Jul 15, 2010 at 8:09
  • It's a no go these results are actually SPARK views that are simply JavaScript with embedded C# (localisation, default values etc). So they need dynamically executed and can;t be pre-minified. It needs to be post execute. Commented Jul 15, 2010 at 9:29

1 Answer 1

4

I think the YUI Compressor for .NET will do exactly what you need.

http://yuicompressor.codeplex.com/

EDIT: Above is wrong as I misread the question. The code below will install a response filter allowing you to manipulate the output, in this case it just removes newline characters.

Hope this helps.

[HandleError]
public class HomeController : Controller
{
    [Minify]
    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }
}

public class Minify : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //You can check if the content type is CSS/JS here and prevent the filter running on HTML pages 

        filterContext.HttpContext.Response.Filter = new MinifyFilter(filterContext.HttpContext.Response.Filter);

        base.OnActionExecuting(filterContext);
    }
}

public class MinifyFilter : MemoryStream
{
    private StringBuilder outputString = new StringBuilder();
    private Stream outputStream = null;

    public MinifyFilter(Stream outputStream)
    {
        this.outputStream = outputStream;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        outputString.Append(Encoding.UTF8.GetString(buffer));
    }

    public override void Close()
    {
        //Call the minifier here, your data is in outputString
        string result = outputString.ToString().Replace(Environment.NewLine, string.Empty);

        byte[] rawResult = Encoding.UTF8.GetBytes(result);
        outputStream.Write(rawResult, 0, rawResult.Length);

        base.Close();
        outputStream.Close();
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

Yes it will perform the minification but that wasn't my question. Assuming I have a result like View() I want to be able to take that stream and convert it to string, minify and write it back to another result (or directly to the response if necessary)
Aah, sorry I misread the question. You need a response filter which you can hook up within an ActionFilter Attribute, similar to this: stackoverflow.com/questions/1640909/…
By replacing all new line characters with an empty string, you run the risk of commenting out everything that follows a js comment line. Unless you remove all comments first.
@DanielDyson From the answer "The code below will install a response filter allowing you to manipulate the output, in this case it just removes newline characters". In the context of the question, this was just an example to show how to manipulate the output. The author already knows how to wire up YUI or any other minifier, this was just some boiler plate showing them where to make the call.
True, however, someone searching for a JS Minifier might come accross this code. You can't assume that only people looking for info on ActionFilters will come accross this answer. So my comment was not aimed at you. Your answer was correct. It was just a warning to others that this is not a working JS minifier.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.