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)
{
开发者_JAVA百科 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.
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.
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).
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
精彩评论