1

I've currently implemented a simple asset manager, which allows me to manage CSS and JavaScript resources, both in external files and in-line.

I'm looking to improve the way I work with it in my code, but I want to be able to use it in such a way that it can be accessed from both my helper functions and my views.

Currently calling it I am doing something like so:

In my helpers:

public void MyHelper(this HtmlHelper helper)
{
    JavascriptAssetManager.Current(helper.ViewData, typeof(JavascriptAssetManager)).Inline(@"alert('Some javascript!');");
}

In my views:

<% CssAssetManager.Current(this.ViewData, typeof(CssAssetManager))
       .Add(Url.Content("~/Content/styles.css")); %>

I have two instances of the AssetManager classes (one each), and I store these in the ViewDataDictionary, this is about the only way I've found that I can store a per page request object that is accessible to both my helpers and my views.

My Current method is implemented in the base abstract class (and that's why I have to pass the type of the child object to the method). This allows me to implement separate rendering functions (include and inline statements) for Javascript and CSS.

My end goal would be to modify the solution so that I can work with it something like this:

public void MyHelper(this HtmlHelper helper)
{
    helper.Scripts.Inline(@"alert('whatever');");
}

<% Css.Add(Url.Content("~/Content/layout.css")); %>

I have looked at other solutions, and tried one or two. Namely this: http://weblogs.asp.net/rashid/archive/2009/05/02/script-and-css-management-in-asp-net-mvc-part-2.aspx

Its really quite good, but I found it annoyingly round-about to include some simple JS in my HTML Helpers... In order to get the Lamba action to work I ended up having to do something like:

() => { "alert('whatever');".ToString() }

Trying to then pass C# variables into that is what broke me... I much prefer my parameterised String.Format() based Inline method (even though I don't like doubling up the curly braces).

My point here is: I'm perfectly open to scrapping my code and just using something third party, if someone can recommend something that works well. I really do want to have management of CSS as well as JavaScript, too.

This is the Current method as I have it now; I will gladly provide more (all) code:

    public static BaseAssetManager Current(ViewDataDictionary ViewData, Type InstanceType)
    {
        string viewDataKey = InstanceType.Name + "-ViewData";

        //If not instanciated yet, create it:
        if (!ViewData.ContainsKey(viewDataKey) || ViewData[viewDataKey] == null)
        {
            var instance = (AbstractAssetManager)Activator.CreateInstance(InstanceType);
            ViewData[viewDataKey] = instance;
            return instance;
        }

        return (AbstractAssetManager)ViewData[viewDataKey];
    }

As a bonus, it would be nice to be able to have CSS files included inside my helpers/views throughout, but then have it all put inside the tag.

I found with my solution that since I'm calling my rendering code at the header of the Master Page, any include calls made inside my views simply are left out.

Presumably because of the order in which stuff gets called and compiled. I ended up just rendering all of the CSS at the footer of the page to circumvent this, as its much more important for me (right now) to be able to have my helpers determine what files are needed on a page at run-time.

Flame me for that bad practice if you will, but I haven't reached any need to optimise it. :)

Thanks everyone!

EDIT:


Based on @smartcaveman's post, I've been trying out the Telerik Web Assets Styles and Scripts Registrars. It seems heavily based on the blog post I mentioned, maybe the author is associated with them?

There's lots of extra functionality in the Telerik version, but the one thing that's helped is the OnDocumentReady() overload which accepts a string to execute inline Javascript.

I would never use inline JS for anything major, but it definitely helps if you have all your JS functions in external files, which you can dynamically include. Then just make one line calls whenever an input (HTML helper etc...) needs that JS function called.

It's combined all the calls the the OnDocumentReady() method to a single javascript inline code block in my footer, where I've called Render().

This is exactly what I was after.

Unfortunately, calling Render() for Style sheets, still seems to suffer the same caveat where any included files after the render call is made, are simply not processed. Hopefully there's a work-around, but for now I'm happy.

Geekman
  • 599
  • 7
  • 18

3 Answers3

4

Telerik's ASP.NET MVC extensions have an excellent web asset manager. The description is here: http://www.telerik.com/products/aspnet-mvc/web-asset-managers.aspx. You can also download the open source code from the panel on the right. It's generally a good idea to avoid reinventing the wheel, and this component does all that you are looking for and more.

smartcaveman
  • 41,281
  • 29
  • 127
  • 212
  • I did check that out, but I _completely_ missed the open source download link. Will check it out, thanks! – Geekman Mar 10 '11 at 14:59
  • Looking good. Telerik's manager seems to use a similar syntax as that blog post, but at least it's got StyleSheet management! Still need to investigate best way to inject inline JS/CSS with it. But thanks! – Geekman Mar 10 '11 at 15:34
  • @Geekman, Let me know what you decide on. I'm actually working on something similar. Check my currently open question: http://stackoverflow.com/questions/5255223/asp-net-directive-convention-for-declaring-client-side-includes . That's the path I'm on right now. – smartcaveman Mar 10 '11 at 15:45
  • Just posted on your question about how I'm now doing things. :) – Geekman Mar 10 '11 at 18:06
  • @Geekman, If you check my post you will see the solution I came up with for registering the dependencies. – smartcaveman Mar 13 '11 at 16:00
2

There is a new .net open source asset manager that works well called Cassette that is hosted on Github. It has a clean syntax, supports style sheets, CoffeeScript, and html templates. It will minimize and combine scripts and cache them based on the file hash if your website is in production (debug=false).

bkaid
  • 51,465
  • 22
  • 112
  • 128
0

Telerik's ASP.NET MVC extensions are not free. I recently came across the following solution: http://weblogs.asp.net/rashid/archive/2009/04/28/script-and-css-management-in-asp-net-mvc.aspx

K.A.D.
  • 3,648
  • 3
  • 34
  • 35
  • While the Telerik extensions may not be completely free, there is an open source version - which can be used legally by other open source applications. I have used them in a couple of applications. http://www.telerik.com/products/aspnet-mvc/getting-started/licensing.aspx. Not sure if you saw, but I did actually link to one of the posts on Rashid's blog -- and I did try it, but found there to be some things I didn't like -- I believe that solution is actually an early version of that which was released by Telerik. As I understand it, he works for them. – Geekman Nov 22 '11 at 01:49
  • Can you use Telerik's ASP.NET MVC extensions in a commercial software for free? – K.A.D. Nov 24 '11 at 14:09
  • There's nothing stopping you, I suppose. But its not legal as per the GPL v2 agreement that the open source version is bound by. I guess if you do use it in a commercial application, you risk legal action if found out. – Geekman Nov 27 '11 at 10:09