Combine web server controls web and script resources (axd files) - asp.net

I know there are lots of similar questions like this in the web, but I haven't got to one working solution after searching for these last 2 days. Some threads are outdated, others solutions don't work, others are too complicated to manage, so... Yes, another question about resources.axd files in asp.net projects.
I'm starting to build a set of server controls and embedding some resources. After building my controls and dragging them into pages, each individual resource is requested by the browser in the form of an .axd script. I understand the part where the ScriptManager manages these scripts and they're not ready to use, for instance, in Bundles in some sort of .Include("*.axd").
I tried some of the combine/minify/compress/gzip/icecreamOnTop packages out there but couldn't manage none of them to work.
I tried the StriptManager CompositeScript approach and the ScriptResources.axd are indeed combined, the response is successful (code 200), but in the end the scripts don't work. Example: I included the jQuery lib in that composite script and then tried to use it in the page - didn't work. I must say I didn't reference () the composite script anywhere because I didn't understand how to do it. If I set the path, then a 404 was returned (found the 1024 byte limit threads, etc...) and all the requests to the WebResources.axd would still remain.
I would prefer not to write an HttpHandler myself.
Also tried to download the AjaxToolkit and tried the ToolkitScriptManager which combines scripts, but that added ~4seconds to my page load. No, thanks.
My question is: what is the current approach regarding this matter in .net 4.5?
I will have lots of resources and would like to combine them. All js and css files in the final website project are bundled, but how to 'bundle' the axd files?
Here's a little example which will make the following requests:
Click here to view image
I know I can set the AjaxFrameworkMode to Disabled and will only have the 2 first WebResources.axd requests in this example, but what about when I have 10 css files embedded in my controls?
Any working solution would be much appreciated.
Many thanks

I managed to implement something that suits my case. More of a work around than a proper combining solution, but works and that's good enough for now.
All my controls extend a base class which has a property called ProcessResources. By default this property is set to true. That means that JS and CSS resources will be registered and each control has everything to work as standalone (axd resources will be generated). When set to false, no resource is registered and no axd files are generated.
The base class also has a static method that receives a destination path as a parameter and copies all the JS and CSS resources to that folder (if they don't exist or have been modified). This method returns a collection of all the needed resources for the control to work.
This way, on Application_Start, I can do something like:
myJsBundle.Inlude(ServerControlA.GetResources("~/ExternalResources", RESOURCES.JAVASCRIPT));
Then just need to set the ProcessResources flag to false (each control or web.config). All resources are now bundled and no axd files are generated.

Related

How to deal with Web Controls in a class library which have file dependancies

I could do with a little guidance if possible..
I'm building a class library to contain custom web controls. I've transformed many of the jQuery UI elements into .NET classes for dynamic use in pages. e.g.
Dim Msg As New Dialog("Dialog Title", New LiteralControl("Dialog Content"))
Msg.Width.Value = 500
Msg.Height.Value = 300
Me.Controls.Add(Msg )
The necessary scripts get inserted into the head during CreateChildControls, and any jQuery file references are added to the head e.g.
RegisterScriptFile("~/Scripts/jquery-1.5.1.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.core.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.widget.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.mouse.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.draggable.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.position.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.resizable.js")
RegisterScriptFile("~/Scripts/UI/jquery.ui.dialog.js")
The WebControl base class handles inserting the references into the Page Head.
This is brilliant, however there's a problem...the file paths may differ between applications which consume the control library.
My choices that I can see are:
A) Embed the files as resources within the library itself....however the CSS styling would be non-customisable between the individual aplications, and any changes to CSS/JS would need a re-compile.
B) Define and use a standardised file heirarchy. Each application needing a folder call 'Scripts' with a fixed file heirarchy within, so the control knows where to reference the required files. The problem I can see here is that it might not always be possible to use this standardised heirarchy and could make using the library cumbersome.
C) Create a property for each control, for each file it requires. Again this would become cumbersome and a pain to use, because each instantiated control would have to have those properties set.
D) Make some kind of ResourceUrlLibrary Dictionary like class which the consuming app can populate, then give to each control as it's instantiated. However, this seems convoluted and could cause confusion for other developers.
If anyone has come across this problem and could spare me some guidance that would be brilliant :)
If its a custom control, it has a reference to the Page class, which then has a method call ResolveClientUrl to generate a relative URL for you. So that can take care of that scenario. You may want to expose a ScriptsFolder property that allows you to store the path to the scripts rather than hard-coding it too.
If this is for your own custom project, standardizing on a folder is fine, but if you are creating a common library to be reused, requiring a specific folder isn't a good idea, and you can then use the ScriptsFolder property to remedy this, or store the folder path in the config. It's OK to standardize on the use of an application setting.
To confirm, I use Telerik controls, and they go the route of having a property that defines a custom path to the script (since they rely on one for a specific control), and they also have certain settings that can be overridden by adding an application setting.
HTH.

Shorter names for /ScriptResource.axd and/or /WebResource.axd in ASP.NET?

My page loads scripts and css from some custom assembly. For now, I use the ScriptManager to add scripts to the page (its CompositeScript) and the page's ClientScript.GetWebResourceUrl() for css files. So, on the page(s) my scripts are referenced by /ScriptResource.axd and css are referenced by /WebResource.axd. Works fine except the fact that those URLs look really ugly. Is there any manageable way to replace those urls with my own fake paths without moving/hosting script/css physical files somewhere? Any help or ideas would be greatly appreciated.
Use a Filter to find all the WebResource.axd and ScriptResource.axd src'es and replace them with something you like better. You then need a IHttpHandler, as Brian comments, that understands your new url-format and returns the same content as the original axd-files would have.
You should also look into combining all those script and css resources to save requests from the browser. How do I combine WebResource.axd and ScriptResource.axd files so as to result in less requests to my ASP.NET server?

Drupal - customizing $scripts output

Basically the issue im having is I have a custom theme, and I need to use $scripts to call the analytics code at the top (the link tracking settings) however this also loads loads of other cr*p js files I dont need or want.
All I want is the analytics stuff the module places in $scripts.
So can I somehow either:
A) Load only the analytics code via $scripts (.info file?)
B) Create a new region in .info file (e.g. $analytics) and call that via the template. But then how do I get the analytics code to output to this new region instead of $scripts?
Any help would be most appreciated.
A.
I would be wary of not outputting $scripts. The files that are output are needed for your other modules to work properly. If you want to reduce the scripts which are output then turn off modules that you don't need.
I agree that disabling the $scripts variable (or cleaning it out) will have some "undesired results". I can think of about half a dozen modules that I use on every build that have required js files.
Maybe you should look into the Google Analytic Module which uses the $footer variable instead of the $scripts.
http://drupal.org/project/google_analytics
I also use this module on all my builds as it provides some very easy integration of Drupal into GA including downloads, user roles, etc. (out of the box)
p.s.
Remember Drupal has a pretty good Performance settings that allow for the cache as well as consolidation css/js.
My final builds have 1 line of markup that calls ALL of my css for that page and one line that does the same for my js. It's been shown that consolidating your asset files into one large file rather then many small ones is a huge performance saver, more so then the size of the end file itself.

How to create custom CSS "on the fly" based on account settings in a Django site?

So I'm writing a Django based website that allows users select a color scheme through an administration interface.
I already have middleware/context processors that links the current request (based on domain) to the account.
My question is how to dynamically serve the CSS with the account's custom color scheme.
I see two options:
Add a CSS block to the base template that overrides the styles w/variables passed in through a context processors.
Use a custom URL (e.g. "/static/dynamic/css/< website_id >/styles.css") that gets routed to a view that grabs all the necessary values and creates the css file.
I'm content with either option, but was wondering if anyone else out there has dealt with similar problems and could give some insight as to "Best Practices".
Update : I'm leaning towards option number 2, as I think this will allow for better caching down the road. So it's dynamic the first time, gets stored in memcache (or whatever), and invalidated when a user updates their settings in the admin site.
Update: Firstly, I'd like to thank everyone for their suggestions thus far. All the answers thus far have focused around generating static files. Though this would work great in production, it feels like a tremendous burden during development. If I wanted to add a new element to be styled, or tweak existing styles I'd have to go through and recreate each and every css file. Sure, this could be done with a management command, but I just don't feel it's worth it. Doing it dynamically would add 1 maybe 2 queries to each page load, which is something I'm not worried about at this stage. All I need to know is that at some point I will be able to cache it without rewriting the whole thing.
I've used option #2 with success. There are 2 decent ways of updating the generated static files that I know of:
Use a version querystring like /special_path.css?v=11452354234 where the v parameter is generated from a database field, key in memcached, or some other persistent file. Version gets updated by admin, or for development you would just make the generation not save if the parameter was something special like v=-1. You'll need a process to clean up the old generations after some time.
Don't use a version querystring, but have it look first for the generated file, if it can't find it, it generates it. You can create a cron job or WSGI app that looks for filesystem changes for development, and have a hook from your admin panel that deletes generations after an update. Here's an example of the monitoring, which you would have to convert to be specific to your generations and not to Django. http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode#Monitoring%5FFor%5FCode%5FChanges
Could generate the css and store it in a textfield in the same model as the user profile/settings. Could then have a view to recreate them if you change a style. Then do your option 1 above.
Nice question.
I would suggest to pre-generate css file after colors scheme is saved. This would have positive impact on caching and overall page loading time. You can store your css files in directory /media/css/custom/<id or stometing>/styles.css or /media/css/custom/<id or sth>.css and in template add <link rel="stylesheet" href="/media/css/custom/{{some_var_pointing _to_file_name}}" />
You can also do the trick with some random number or date in css file name that could be changed each time file is saved. Thanks to this browser will load the file immediately in case of changes.
UPDATE: example of using model to improve this example
To make managing of those file easy you can create simple model (one per user):
class UserCSS(models.Model):
bg_color = models.CharField(..)
...
...
Fields (like bg_color) can represent parts of your css file. You can ovveride save method to add logic that creates css file for user (by rendering some template).
In case your file format change you can make changes in your's model definition (with some default values for new fields), make little changes in template and run save method for each exisintg instance of class. This would renew your css files.
That should work nicely.
I would create an md5 key with the theme elements, store this key in the user profile and create a ccs file named after this md5 key : you gain static file access and automatic theme change detection.

Minify Html output of ASP.NET Application

What are the ways by which we can reduce the size of the HTML Response sent by an asp.net application?
I am using Controls which are not owned by me and it produces output with white spaces. I am interested in Minifying the entire HTML output of the page just like how google does (View source www.google.com) to improve the timing.
Is there any Utility classes available for ASP.NET which can do this stuff for me?
There is no need to do it at run time. Because it can be done at compile time.
Details: http://omari-o.blogspot.com/2009/09/aspnet-white-space-cleaning-with-no.html
Try HTTP module as described here: http://madskristensen.net/post/a-whitespace-removal-http-module-for-aspnet-20
For Microsoft .NET platform there is a library called the WebMarkupMin, which produces the minification of HTML code. For each ASP.NET framework has its own module:
ASP.NET Core - WebMarkupMin.Web. Implemented as an HTTP module, so it can work with any framework. Suitable for use in the ASP.NET Web Pages framework (Razor).
ASP.NET MVC - WebMarkupMin.Mvc
ASP.NET Web Forms - WebMarkupMin.WebForms
Documentation is available at - http://webmarkupmin.codeplex.com/documentation
I want to comment on Thorn's suggestion (but I'm new to stack overflow).
The linked code (omari-o.blogspot.com) doesn't support MVC4, and although the code is open source it cannot easily be upgraded because of braking changes between MVC3 and MVC4.
There might be whitespaces written to the http result at runtime, only the developer of the actual site can know that. Thus static minification of template files (aspx) is not foolproof at all. Dynamic minification, which is suggested by gius, should be used to guarantee that whitespaces are removed correctly, and unfortunately this will incur a runtime computation cost. If code dynamically writes spaces to the output, it will have to be removed dynamically.
The accepted answer does not work with MVC 4, so here is a similar lib that minifies at build-time https://github.com/jitbit/HtmlOptimizerMvc4
Just adding another option I do not see listed here, which is the one I was recommended using:
Html minifier command line tool
Usage:
here and here
There is an issue, however, with this tool: it leaves single line (//) comments, and it causes problems for Razor parsing, since a single line comment placed within a C# block like the following:
#{
...
...
// anything
...
}
will cause the minification output rest of the line, from this point on, to be ignored by the Razor parser, which will thus raise an error stating there it could not find the closing "}" for the block.
My workaround for this issue was to completely removing these comments from the output.
This way it works.
To do that, simply remove the RegexOptions.SingleLine from line 145:
htmlContents = Regex.Replace(htmlContents, #"//(.*?)\r?\n", ""/*, RegexOptions.Singleline*/);

Resources