Thursday, January 22, 2009

Speed up ASP.NET MVC + jQuery by Combining Files Build-time

The quick answer: Put the following in a file named 'postbuild.bat' in your project root

@echo Combining JS
if EXIST "%~f2Scripts\all.js" del "%~f2Scripts\all.js" /F
copy "%~f2Scripts\*.js" "%~f2Scripts\all.js" /B /Y
@echo Combining CSS
if EXIST "%~f2Content\all.css" del "%~f2Content\all.css" /F
copy "%~f2Content\*.css" "%~f2Content\all.css" /B /Y

and run from your project's Post Build Event: $(ProjectDir)postbuild.bat "$(SolutionDir)" "$(ProjectDir)"

Finally, in your site.master, remove all css and js references and simply use 'all.js' and 'all.css'

I recently started using jQuery and MVC on a project for a client, and while I love them, the app just seemed a little sluggish, especially in FireFox.  After some sleuthing, I traced the issue to the 6-7 css and a few .js files being loaded by the app.  This is a well documented problem - each file is a request to the server, and requires overhead on the client and server to serve up. 

Generally, it's better to combine them all into one file.  However doing this by hand makes development more difficult.  One solution is to use HttpHandlers to compress and combine files at run time.  This works, but can be difficult to configure, and executes for every request at runtime. My approach is to combine these all at build-time, so that everything is done as part of the build process. 

In practice, you may need to adjust the paths above.  This combines all js and all css files in the default MVC folders.  If your application is not an MVC app, the same concept will work, but you may need to adjust the folders. 

Friday, January 16, 2009

Obscure Error: IDataErrorInfo causes NullReferenceException in ASP.NET Dynamic Data

I'm using ASP.NET Dynamic Data against an existing Linq-to-SQL data context.  For some of the table classes, I implement IDataError info for validation in a different (non-dynamic data) part of the app.  For these tables, browsing to the List.aspx page was throwing a nullreferenceexception from 'MetaColumn'.   I debugged the issue down to the default indexer specified by IDataErrorInfo.  I'm not a fan of this indexer anyway - it's non-obvious that myClass["property"] should return an error, and in some cases conflicts with other, more sane default indexers.  I'd prefer myClass.Errors["property"].  Anyway, I degress-  I was about to give up, when I decided to try an explicit implementation of IDataErrorInfo.  Viola! No error. 

So, if you get 'Object not set to instance' using ASP.NET Dynamic Data, and your class implements IDataErrorInfo, or has some other default indexer, try changing from this:

public string this[string columnName]

To this:

string IDataErrorInfo.this[string columnName]

This is probably a better way to implement anyway.

Monday, January 5, 2009

Check Out

Jeff Atwood and Joel Spoelsky's baby StackOverflow has developed a pretty decent user base now and has quickly become one of my favorite community resources for programming related questions.  There are a ton of .NET users, but also Java and others.   This beats the forums and blogs because of the rating system, which weeds out poor answers and questions. 

There are several ways I use StackOverflow:

  • As a knowledge base for stubborn problems that I can't solve on Google or MSDN.  Half the time I find a solution in auto-search while entering the title. 
  • As a blog-like learning resource.  The 'Hot' tab lists interesting posts and discussions.  Add the RSS feed to your reader for interesting news daily.
  • As a discussion board.  Occasionally, if I know the answer to something I'll post an answer.

Anyway, great site - check it out.