Scriptmanager remove javascript - asp.net

The ASP.NET ScriptManager control automatically inserts all kinds of inline javascript like PageRequest initialize. Is it possible to remove or move this to an external js file?
Also, the scriptmanager always adds __DoPostback even when not used on the page, how can this be avoided or also moved to an external file?

First of all the "__DoPostBack" is inserted by controls that can cause a postback such as the DropDownList with the AutoPostBack property set to true. Since the ScriptManager basically intercepts the traditional postbacks, I believe that's the reason for it to insert the function.
-- The following is just me thinking... :)
Now, about moving everything to an external file. It's not easy, but it "could" be possible.
The problem is that ASP.NET is generating the scripts at runtime, so you cannot do anything about it statically. What you need to consider is why you would want to do this in the first place.
The fact is that much of the generated script is dynamic, which makes it rather hard to cache.
But, if you really need to, you should have a look at both HttpHandlers and HttpModules.
Basically you need to somehow extract every script tag (without the src-attribute set). This could be done in a HttpModule on the BeginRequest event of the HttpContext. Now you need to extract all the necessary pieces of information and replace it with a reference to a specific HttpHandler that can service as the replacement.
But to make any difference at all, it is necessary for you to do some sort of caching of the existing script. You could probably use the ASP.NET Cache for that.
The tricky part would be to compare an existing cache entry with the new and determine whether or not to get the cached version (pointing the HttpHandler to an existing entry) or to generate a new entry. If you have a lot of scripts, it's most likely to be a rather expensive operation.
Furthermore you need to determine whether the client can cache on it's own (e-tags etc. could come in handy). What's important is for the client to avoid downloading the same unnecessary scripts each time (I believe that's your ultimate goal?).
So to recap:
Build a HttpModule to take care of the page rewriting and putting the extracted script into some sort of cache (eg. ASP.NET Cache).
Build a HttpHandler to point to for the extracted script (it should stream the contents from the cache). The handler should be put in place of the extracted inline scripts.
Create some sort of algorithm for determining cache invalidity. I don't know from the top of my head what kind of script that could change between requests.
Btw. script externalization is tricky at most, so you need to be careful not to introduce bugs that are impossible to fix ;)
Not an extact solution, but I have tried doing this myself before without any luck... mostly because of too litle time. When you are payed to do a task, this kind of optimization can't be justified... :(

Related

New ASP.NET Bundling Features - How can i programmatically refresh a certain bundle?

I'm mucking around with the new ASP.NET bundling features (using the System.Web.Optmization 1.0.0-beta pre-release) in my ASP.NET MVC 3 web application.
Works great.
However, we have certain dynamic CSS/JS which is stored in the database.
I want to get this added to a seperate bundle for my core bundle, say "DynamicBundle". I know how to do that, not a problem.
Now my question is, when this CSS/JS is changed in the database, that bundle needs to be "refreshed" so that the content of those files are re-read in to the bundle.
Essentially, i need ASP.NET to re-generate that magic guid/string that is appended to the bundle URL.
Ideally, i'd only like to refresh a specific bundle, not the entire bundle table.
Is there a way to do this?
EDIT:
Okay second problem, can't figure out how to add the dynamic CSS/JS to the bundle. bundle.AddFile takes a virtual path to a file, but it's not a physical file, it's a string. How am i going to do this? Surely i don't have to write out string to files first?
EDIT 2:
So i've decided not to bundle my dynamic content. For 2 reasons:
It's only 1 file, so i'm not gaining any "bundling" benefits
Bundling is designed for static content, this is not
So what i've done is manually minified my dynamic css/js at runtime (once, then cached). That way i can easily refresh it, by simply clearing the cache.
That being said, this is still a relevant question (refreshing bundles) so i'll leave it open..
That "that magic guid/string" is a hash of the combined file contents.
You can test this with the following workflow which assumes that you have a mybundle.css. If you use Fiddler to watch the traffic, you will see it request something with a hash like
http://localhost:20206/mybundle.css?v=-6520265193368900210
Now, "touch" one of the files in the bundle as much as you want without actually changing the contents. The file is newer (LastModified / LastWrite is more recent), but the hash remains constant as it is being computed from the same combined contents. You could even add spaces to the file since those would be minified out.
http://localhost:20206/mybundle.css?v=-6520265193368900210
Next, actually make a change. Perhaps set a border to 2px instead of 1px. The hash will change now, since the contents feeding the hash have changed.
http://localhost:20206/mybundle.css?v=-4725541136976015445
Finally, set the border back to what it was (in the above example, back to 1px). The "magic string" is actually not random or magic at all. Instead, it returns to the matching one-way hash computed from the contents.
http://localhost:20206/mybundle.css?v=-6520265193368900210
Now you can rest easy that the hash will update only when it is needed, without manual intervention.
As for the other part of your question,
when this CSS/JS is changed in the database, that bundle needs to be
"refreshed" so that the content of those files are re-read in to the
bundle.
I think we just reverse the thinking. Instead of refreshing the bundle to trigger a re-read, we update the files to trigger the refresh. When ASP.NET sees the file(s) change, it will recombine the contents and update the hash.
I have good news for you. Many people have been asking for virtual path provider support for scenarios similar to yours, where they have content that's not necessarily from disk, so we currently are planning on supporting VPP in the next release.
To take advantage of this support, you will have to implement a VPP for your dynamic js/css.
VPP also has cache dependency mechanisms built in, so we should be able to use those to automatically flush the correct bundle cache entry for you.

ASP.net output caching

Just a quick question so I full understand this better, the way I understand it currently is if you set a page to be cached the HTML generated is essentially saved and then reserved.
This means no code behind on that page is run until the cache expries and regenerates. Also, if say for example I have a dynamically generated date stamp, this will always be the date the cache was generated.
Is this correct?
Read the artice about caching. If you want to fully understand Http Caching, you should also read Caching In Http. And the answer is yes, once the page is saved in cache, no code behind is run before it's regenerated. Also, dynamically generated content will stay in cached page as static
Yes, but you can flag some portions of code or some controls to be rewrited.
You can catch only some controls or all controls except one...
Catch the data from database or some collections...
Is a lot flexible.

Umbraco: Handling In Page Javascript in Uswe Controls

I have quite a number of user controls that I need to embed in Umbraco macros. Each user control has quite a bit of in page javascript that needs loaded into the page.
I have been building up the javascript with StringBuilder.Appendline then registering a startup script with code behind but this stinks and I feel there has to be a better way of going about this.
Has anyone any ideas please?
Thanks,
B
If the javascript isn't dynamic, that is that it changes based on the usercontrol you would probably be best to extract it and put it in either one .js file for the site or in a number of them. Doing so allows it to be cached by the browser.
If it is dynamic then I would personally keep it isolated inside the control rather than try to write it out all at once. I don't believe there is any major performance hit from having several script blocks, although I could be wrong.

Rendering javascript at the server side level. A good or bad idea?

Now a community wiki!
I want to make it clear first: This isn't a question in relation to server-side Javascript or running Javascript server side. This is a question regarding rendering of Javascript code (which will be executed on the client-side) from server-side code.
Having said that, take a look at below ASP.net code for example:
hlRemoveCategory.Attributes.Add("onclick", "return confirm('Are you sure you want to delete this?');")
This is prescribing the client-side onclick event on the server-side.
As oppose to writing Javascript on the client-side:
$('a[rel=remove]').bind('click', function(event) {
return confirm('Are you sure you want to delete this?');
}
Now the question I want to ask is: What is the benefit of rendering javascript from the server-side code? Or the vice-versa?
I personally prefer the second way of hooking up client-side UI/behaviour to HTML elements for the following reasons:
Server-side does what ever it needs to already, including data-validation, event delegation and etc; and
What server-side sees as an event is not necessarily the same process on the client-side. i.e., there are plenty more events on client-side (just look at custom events); and
What happens on client-side and on server-side, during an event, could be completely irrelevant and decoupled; and
What ever happens on client-side happens on client-side, there is no need for the server to know. Server should process and run what is given to them, how the process comes to life is not really up to them to decide in the event of the client-side events; and so on and so forth.
These are my thoughts obviously. I want to know what others think and if there has been any discussions on this topic.
Topics branching from this argument can reach:
Code management: is it easier to render everything from server-side?
Separation of concern: is it easier if client-side logic is separated to server-side logic?
Efficiency: which is more efficient both in terms of coding and running?
At the end of the day, I am trying to move my team to go towards the second approach. There are lot of old guys in this team who are afraid of this change. I just wish to convince them with the right facts and stats.
Let me know your thoughts.
UPDATE1: It looks like all of us who have participated in this post have common thought; Good to know that there are others who think alike. Now to go convince the guys ;) Thanks everyone.
Your second example is vastly superior to the first example. Javascript is your behaviour layer and should be separate from your semantic markup (content) and CSS (presentation). There are a number of reasons this is better architecture:
Encourages progressive enhancement. As you mentioned, the backend code should work correctly in the absence of JS. You cannot rely on your clients having JS available. This way you build it once without JS and then can enhance the experience for those with JS (e.g. by adding clientside validation as well as serverside validation so that the client can get instant feedback)
Cleaner markup. Normally reduced download size. One reusable selector in a separate JS file that can be cached and shared between pages vs. a handler on each element.
All of your JS in one re-used place. e.g. if your code was opening a popup window and you decided to change the dimensions of the window you would change it once in the code in the JS file vs. having to change it on every individual inline handler.
There are lots of other arguments and reasons but they should get you started...
Also, from your example it appears that you have a normal link in your document which can delete content. This would also be a bad practice. Anything that deletes or updates content should be done on a POST (not GET) request. So it should be the result of submitting a form. Otherwise e.g. googlebot could accidentally delete all of your content by just crawling your page (and search engine robots don't execute JS so your alert wouldn't help there)
The two biggest differences i can think of up front are:
you lose the client side caching you would get if the javascript was in a separate js file
if you need to change your javascript, you have to recompile (extrapolate this to what happens after you have released your product: if you have to recompile then you need to redistribute binaries instead of just a modified js file)
it is easier to use the VS debugger if the javascript is in a separate file; you can just set a break point in that file, if you are generating the code server side then you have to use the running documents feature, find your generated code and then add the breakpoint, and that breakpoint has to be manually added everytime you re-run your app. Following on from that, if the code is in a separate file, then you can just make your tweak to the javascript code, F5 your browser page, and keep on debugging without having to stop and restart the debugger.
It should be mentioned that sometimes you have to insert js code from the server - for example if the bulk of your code is in a separate js file and you need to insert control identities in to the page for that code to work with. Just try to avoid that situation if possible.
Looks like you already know what to do. Rendering it on the server side is a bad idea.
The simple reasoning being you're Javascript lives both on the server side pages as well as in separate Javascript files (assuming you are using Javascript at all). It can become a debugging nightmare to fix things when everything is everywhere.
Were you not using any other Javascript besides what the server side scripts generate, it would probably be fine and manageable (forget what the unobtrusive movement says).
Secondly, if you have 100 links on the page, you will be repeating that same code in 100 places. Repetition is another maintenance and debugging nightmare. You can handle all links on all pages with one event handler and one attribute. That doesn't even need a second thought.
<Rant>
It's not easy to separate HTML and Javascript, and even CSS especially if you want some AJAX or UI goodness. To have total separation we would have to move to a desktop application model where all the front-end code is generated on the client side programmatically using Javascript, and all interaction with the server gets limited to pure data exchange.
Most upstream communication (client to server) is already just data exchange, but not the downstream communications. Many server-side scripts generate HTML, merge it with data and spit it back. That is fine as long as the server stays in command of generating the HTML views. But when fancy Javascript comes onboard and starts appending rows to tables, and div's for comments by replicating the existing HTML structure exactly, then we have created two points at which the markup gets generated.
$(".comments").append($("<div>", {
"id": "123",
"class": "comment",
"html": "I would argue this is still bad practice..."
}));
Maybe this is not as big a nightmare (depending on the scale), but it can be a serious problem too. Now if we change the structure of the comments, the change needs to be done at two places - the server side script and templates where content is initially generated, and the Javascript side which dynamically adds comments after page load.
A second example is about applications that use drag and drag. If you can drag div's around the page, they would need to be taken off the regular page flow, and positioned absolutely or relatively with precise coordinates. Now since we cannot create classes beforehand for all possible coordinates (and that would be stupid to attempt), we basically inject styles directly in the element. Our HTML then looks like:
<div style="position: absolute; top: 100px; left: 250px;">..</div>
We have screwed up our beautiful semantic pages, but it had to be done.
</Rant>
Semantic, and behavioral separation aside, I would say is basically boils down to repetition. Are you repeating the code unnecessarily. Are multiple layers handling the same logic. Is it possible to shove all of it into a single layer, or cut down on all repetition.
You and the other people answering the question have already listed reasons why it is better not to having the server side code spit intrinsic event attributes into documents.
The flip side of the coin is that doing so is quick and simple (at least in the short term).
IMO, this doesn't come close to outweighing the cons of the approach, but it is a reason.
For the code in your example it doesn't really matter. The code isn't using any information that is only available at the server side, so it's just as easy to bind the event in client side code.
Sometimes you want to use some information that is available at the server side to decide whether the event should be added or not, or to create the code for the event, for example:
if (categoryCanBeDeleted) {
hlRemoveCategory.Attributes.Add(
"onclick",
"return confirm('Are you sure you want to delete the " + categoryType + "?');"
);
}
If you would do this at the client side, you have to put this information into the page somehow so that the client side code also has access to it.

Building ASP.NET application - Best Practices

We are building an ASP.NET application and would like to follow the best practices. Some of the best practices are:
Server side Code:
Use catch blocks to trap & log low level errors too.
Use Cache objects to populate dropdowns etc. where we won’t expect the changes in the underlying data/database.
In case of error logging framework, provide emailing alerts along with logging the errors.
HTML code:
- Don’t write inline CSS.
- Place the JavaScript code (If needed by the page) at the end of the page unless the page needs it for load time actions.
Now coming to the point, Would you please share these best practice points if you have a comprehensive list of them already?
Some of the best practices that I've learned over time and written up for use at my company...many are mainly applicable to WebForms and not MVC.
Don't write .NET code directly in
your ASPX markup (unless it is for
databinding, i.e. Evals). If you
have a code behind, this puts code
for a page in more than one place and
makes the code less manageable. Put
all .NET code in your code-behind.
SessionPageStatePersister can be used in conjunction with ViewState
to make ViewState useful without
increasing page sizes. Overriding
the Page's PageStatePersister with a
new SessionPageStatePersister will
store all ViewState data in memory,
and will only store an encrypted key
on the client side.
Create a BasePage that your pages can inherit from in order to
reuse common code between pages.
Create a MasterPage for your pages
for visual inheritance. Pages with
vastly different visual styles should
use a different MasterPage.
Create an enum of page parameter key names on each WebForm
that are passed in via the URL, to
setup strongly-typed page parameters.
This prevents the need for hard-coded
page parameter key strings and their
probable mis-typing, as well as
allowing strongly-typed parameter
access from other pages.
Make use of the ASP.NET Cache in order to cache frequently used
information from your database.
Build (or reuse from another project)
a generic caching layer that will
wrap the ASP.NET Cache.
Wrap ViewState objects with Properties on your Pages to avoid
development mistakes in spelling,
etc. when referencing items from the
ViewState collection.
Avoid putting large objects and object graphs in ViewState, use it mainly for storing IDs or very simple DTO objects.
Wrap the ASP.NET Session with a SessionManager to avoid development
mistakes in spelling, etc. when
referencing items from Session.
Make extensive use of the applicationSettings key/value
configuration values in the
web.config - wrap the
Configuration.ApplicationSettings
with a class that can be used to
easily retrieve configuration
settings without having to remember
the keys from the web.config.
Avoid the easiness of setting display properties on your UI
controls, instead use CSS styles and
classes - this will make your styles
more manageable.
Create UserControls in your application in order to reuse common
UI functionality throughout your
pages. For example, if a drop down
list containing a collection of
categories will be used in many
places in the site - create a
CategoryPicker control that will data
bind itself when the page is loaded.
Use Properties on your UserControls to setup things like
default values, different displays
between pages, etc. Value type
properties can be defined on your
UserControls and then be set in your
ASP.NET markup by using class level
properties on UserControls.
Make use of the ASP.NET validation controls to perform simple
validations, or use the
CustomValidator to perform complex
validations.
Create an Error handling page that can be redirected to when an
unhandled exception occurs within
your website. The redirection can
occur via the Page_Error event in
your Page, the Application_Error
event in your Global.asax, or within
the section within the
web.config.
When working with pages that use a highly dynamic data driven
display, use the 3rd party (free)
DynamicControlsPlaceholder control to
simplify the code needed to save the
state of dynamically added controls
between postbacks.
Create a base page for all your asp.net pages. This page will derive from System.Web.UI.Page and you may put this in YourApp.Web.UI. Let all your asp.net pages dervice from YourApp.Web.UI.Page class. This can reduce lot of pain.
Use Application_OnError handler to gracefully handle any error or exception. You should log the critical exception and send the details of the exception along with date-time and IP of client to the admin email id. Yes ELMAH is sure way to go.
Use ASP.NET Themes. Many developers don't use it. Do use them - they are a great deal.
Use MembershipProvider and RoleProvider. And Never use inbuilt ProfileProvider - They store everything in plain strings. It will drastically slow-down the performance while performing R/W
Use Firebug for client-side debugging. Try to follow YSlow standards for web-applications. Use YSlow extension for FireBug.
Use jQuery for client-scripting.
Never store User Authentication information in session or don't use sessions to judge if user is logged on. Store only minimum necessary information in sessions.
Have a look at PostSharp. Can improve maintainability of your code and make you more productive.
Never ever Deploy asp.net application under debug configuration on production. Find out here what scottgu has to say about this.
User Web Deployment projects. It can transform web.config sections and replace with production server setings. It will merge all compiled code-behind classes into one single assembly which is a great deal.
Use Cookie-less domains to serve static resources like images, scripts, styles etc. Each client request is sent along with whole bunch of cookies, you don't need cookies while serving pictures or scripts. So host those resources on a cookie-less domain.
Minify scripts, stylesheets and HTML response from the server. Removing unnecessary line-breaks and white-spaces can improve the time-to-load and bandwidth optimization.
Forms:
Set Page.Form.DefaultFocus and Page.Form.DefaultButton to improve user experience
Check Page.IsValid in your Save button handler before proceeding.
General:
Understand and implement the techniques found in the article "TRULY Understanding ViewState"
Use Page.IsPostBack in your page events to stop code from running unnecessarily.
Use hyperlinks instead of posting and using Response.Redirect whenever possible.
a. Understand and use the second parameter of Response.Redirect (it "Indicates whether execution of the current page should terminate")
Use the Page Lifecycle properly.
Use the Per-Request cache (HttpContext.Items) instead of Cache where it makes sense.
Web.Config:
Deploy with <compilation debug="false">
Register your controls at the web.config level instead of the page level (i.e. #Register).
Themes:
When using Themes, put your static images in the Theme as well.
a. Don't link to the images directly from your markup, link to them from a skin file or css file in your Theme instead.
ex: <asp:Image SkinID="MyImage" runat="server" ImageUrl="Images/myImage.gif" />
I don't think try/catch blocks are always appropriate for low-level methods. You want to catch (and log/alert, even better!) any errors before they get to the user, of course. But it is often better for a low-level method to just lets its errors get raised up to a higher level. The problem I have seen with low-level error trapping is that it often lets a larger operation continue, but then a result that is not quite correct gets presented to the user or saved to the database, and in the long run it's much more difficult to fix. It's also just a lot of extra clutter in your code to put a try/catch at every level if you're not going to "do anything" with the error until it's raised up to a higher level.
Here are some similar questions that may help you.
.NET best practices?
Best way to learn .NET/OOP best practices?
This should probably be community wiki as well.
I would recommend a couple of books if you are interested in pursuing a journey to become a better, more productive developer. These books are language agnostic and as you can see by the user reviews, very very helpful.
Code Complete 2
Pragmatic Programmer
If you are looking for a .NET specific book, you may appreciate the following book:
Microsoft Application Architecture Guide [available online for free outside of print format]
ASP.NET
If you don't use Session state, don't
forget to turn off it.
Use Server.Transfer instead of Response.Redirect if possible.
Set expiration parameter in IIS.
Use GZip to compress the text files.
Use Server-Side and Client-Side validation together.
Use Url Rewriter or Routing to make friendly url for SEO.
Design
Write each class and its properties
of your CSS file in the same line. (To decrease the file size)
Use CSS Sprites. (To decrease request)

Resources