Friday, February 29, 2008

ASP.NET MVC

Microsoft is finally admitting ASP.NET is now an outdated web framework. It makes testing very complex, working around the ViewState is a big waste of time, and the webform metaphor makes zero sense to most web developers. Most web front-end developers don't use the designer, and want complete control over rendered HTML and styles. You can do this in ASP.NET, but it requires workarounds like CSS adapters etc...

ASP.NET MVC keeps all the good ASP.NET stuff like databinding, user controls etc... and add a pure Model-View-Controller pattern to your app. Mixed with Linq, and considering Unit Tests now come out of the box with VS 2008 Professional, you now have a web framework that's very similar to Ruby on Rails, with a much better IDE and the whole .Net framework to support it.

I'm building an app using the MVC framework, and I have to say I like it a lot. I was very familiar with webforms, custom web controls, ViewState and all that nice stuff. Quite powerful, yes. But now web UIs are getting more client-centric thanks to the rebirth of Javascript, all that server-side stuff is not necessary anymore. You really just want to serve a page, offer data services (SOAP/REST/whatever) and let javascript take care of the rest.

I've been very happy with the framework so far. The URL routing engine is nice, and the HTML helpers are great. Strong-typing and generic ViewData make views a breeze to put together.

There are only a few things I hope MS can put together before the release:
  • Better AJAX support. I don't really care about UpdatePanels, but I'd like to be able to catch AJAX requests at the controller level and add ScriptManager instances to my controls without using a server form. Nikhil Kothari at Micrsofot worked on his own implementation. You check it out here.
  • Ability to out views in generic http handlers (.ashx). Right now you can use pages and user controls. But whenever outputing content other than HTML (xml, JSON strings, images, binary data...), HTTP handlers are pretty handy.
  • Ability to use sub-views. I'm not sure yet how that would work exactly, but right now if the page to render is pretty complex, your controller becomes responsible for too many parts of the page. A controller should be able to call sub-controllers, maybe linked to user controls... something like that.

If you're sick of the webform model but love .Net and Visual Studio, I'd strongly recommend you check this out. If you're familiar with other MVC frameworks, it'll look pretty familiar. If you're new to the idea, you'll finally learn what all the rage is about.

A new community preview should be released at Mix 08 next week. I'm looking forward to it.

VS 2008 - Javascript Intellisense

It's a big step in the right direction, but there are still some things that need to be figured out. My biggest problems are:
  • Lack of intellisense support within the prototype. Let's say I'm writing a JS "class". Intellisense seems to work well for all external libraries that are properly referenced, but I can't access the current class methods and properties within its prototype. "this" doesn't give me any choices.
  • Some methods referrencing the DOM rather than javascript objects seem to not work as expected. The first one that comes to mind is "$get()" in the MS Ajax library. Using getElementById() shows all the DOM element properties and methods, but the "$get" shortcut doesn't. It's a real pain actually, and it looks like a bug. It seems like DOM element are described via "isDomElement=true" in the comments rather than the "type" attribute, but it doesn't seem to work properly. I've found multiple posts about the topic, but no response from Microsoft.
  • Not support for code folding / outlining. That seems like a pretty basic feature - all other JS editors offer it, and I don't understand why it didn't get implemented. It makes long javascript files a big pain to edit.

Overall, JavasScript Intellisense works really well if you write small snippets of code referencing well-described external files. Referencing Web Services works really well, too. But if you're writing complex components, it's not going to do much for you.

Wednesday, February 13, 2008

XSD.exe

I've been using a neat little Visual Studio command-prompt tool lately: xsd.exe. It lets you create XSDs from XML (though it seems to generate some dataset-specific code that I had to clean up), classes from XSD (very useful), and other little things.

http://msdn2.microsoft.com/en-us/library/x6c1kb0s(VS.80).aspx

Wednesday, February 06, 2008

The beauty of IoC and DI

I had been reading about Inversion of Control and Dependency Injection for a while. It looked interesting, but I never took the time to implement it in any of my projects. I think I just never had the perfect scenario that would greatly benefit from that kind of configurable component-oriented architecture.

If you're an ASP.NET programmer and have never heard of those terms, they're basically the same as the Container or Provider pattern (provider pattern is issued by MS in ASP.NET 2.0 for Profiles, Membership, Roles, Session storage etc...).

Lately I've had 2 use cases that fit this need perfectly. I downloaded Castle.Windsor and started digging into it.

Sample Scenario: caching.

Every ASP.NET programmer has used ASP.NET's static Cache. It's fast, easy to implement, until... you try running it in a web farm. .Net doesn't support distributed caching out of the box, ,o now you're stuck with a bunch or redundant caches on each server that get out of sync easily. If you use SQL Server 2005, you can try using SQL Dependencies. I did. It started generating a whole bunch of events in the event log, and was overall not very reliable. Not only that, but now you've built a system that's highly reliant on a SQL Server 2005 backend. What if you decide using MySQL? Then ASP.NET will poll the database, and you're going to have more scalability issues.

Here comes distributed caching. Basically your cache is now located on a cluster of caching server shared among your web front-end servers, and now you only need to worry about that one cache being in sync with the database. There are different flavors, with different pricing and different features, but I chose Memcached because it's free, runs on Linux, is easy to setup, and if MySpace relies on it it must be good enough for my little app. (There's also a Windows implementation that's pretty useful for development and testing.)

But here's the thing. I don't want to write references to the C# Memcached client all over my code. What if I switch to something else? What if the app doesn't need to scale up and needs to rely on ASP.NET cache? Caching, like logging, is one of those aspects that's all over the place and creates dependencies that can be a real pain to refactor.

Here's where a container (like Castle.Windsor) comes in handy. All I had to do was create an ICache interface as follows:

public interface ICache
{

void Set(string key, object value);
void Set(string key, object value, TimeSpan duration);
object Get(string key);
void Remove(string key);
bool KeyExists(string key);
}

then I wrote 3 simple implementations:

CacheMocukupImpl uses a private dictionary to organize its contents. It's not thread-safe but is guaranteed to work in any context. Very useful for unit-testing.

ASPNetCacheImpl is a wrapper for the built-in ASP.NET Cache object.

MemCachedImpl uses a MemCached client (there are a couple C# clients out there: here and here).

Then it's just a matter of declaring the ICache component in the Castle configuration, and calling IWindsorContainer.Resolve() to get access to the instance.

Remember to set lifecycle attribute to "singleton", which prevents the class from being instanciated for every single call. Since the cache shares its resources across all incoming requests, it has to be a singleton. Of course, you have to make sure your implementation is thread-safe. Now depending on my needs all I need to do is change the Castle configuration to change my caching implementation. Why not using the ASP.NET provider pattern you might ask? Because I didn't want to limit myself to ASP.NET. I might have other non-web apps that could benefit from this feature. Also, it makes unit testing much easier. Using mockups allows me to focus the test on the method it's testing, and not associated components.

I'm now implementing this pattern all over the place. We're using Amazon Web Services extensively, so I created interfaces, mockups and implementations for queuing and file storage. Logging is next. By decoupling your components, your code becomes much easier to read, test and debug.

.Net source code debugging

Shockingly, Microsoft released the entire .Net framework source code a few weeks ago. More here. This is really amazing; a great, great move. A full downloable version will come out soon. It'll really help debugging, and gives me better visibility in the inner workings of various components. I don't have to use my favorite decompiler anymore, and even have access to developer comments. I'm also hoping it'll speed up Mono project development.

I did run into some difficulties installing the hotfix though, kept getting a fatal error. Turns out that it had to do with my having Orcas Beta2 installed a while ago. I read a post mentioning I just needed to insert the original install DVD and everything should work OK, but that didn't work for me. I finally figured it out, so hopefully this will save you a 1 hour headache.

Here were my original VS 2008 install steps:

- Installed Orcas Beta 2.
- Removed Orcas Beta 2.
- Downloaded VS 2008 ISO from MSDN.
- Burned DVD from ISO.
- Installed VS 2008 Team System from DVD.
- 2 weeks later, received MSDN DVD and threw away my burned copy.
- When trying to install the VS 2008 QFE, inserting the MSDN DVD doesn't solve the problem.

It turned out that the downable ISO and the mailed DVD don't have the same file structure. The hotfix tries to find the original vs_setup.msi. In the ISO, it's located under D:\vs_setup.exe (where D is my DVD drive), but on the shipped DVD it's D:\vs\vs_setup.exe. So the solution was to re-download VS 2008 ISO from MSDN web site, re-burn it to DVD and insert it. One I did that, everything worked fine.

VS 2008 Team System Rant/Rave

After using VS 2008 and TFS 2008 for a few weeks, here are a few initial impressions.

Pros:

- TFS 2008 merging is working great
- Unit test creation is much, much faster (UI used to freeze for 2 solid minutes)
- Thanks to Vishal Joshi for giving me access to the latest build of WDP 2008 before official release. You saved the day.
- ASP.NET ListView control is pretty cool
- LINQ is amazing. Just utterly amazing.
- Multi-targeting works great.

Cons:

- The XML Schema (XSD) designer is gone. I understand it's being re-written, and it'll be nice once it's released (release date seems to be TBD), but I find strange to take away useful product features entirely. For now I have to resort to manual XSD editing, VS 2005, or I might to purchase XML Spy.

- ASP.NET designer and xml intellisense are broken. Sorry. A 20 sec freeze EVERY time I edit a tag or change some control property is just not usable. I run a 2.4 GHz core duo, Vista 64 and 4 GB of RAM, with a 128 MB NVidia video card. It can't be my machine. A lot of people are having similar issues. Even in a simple page with no master page, no themes, and only 6 native ASP.NET components (3 gridviews and 3 repeaters), I'm ready to blow my head off every time I need to make an edit. It's faster to just use WordPad. How bad is that?

EDIT: Since this post, Microsoft has released a hotfix for this specific issue.

- There used to be an annoying UI bug whenever using the database schema compare tool - sometimes the text in the source / target dropdowns would be off by a few pixels, making it unreadable. The good news is the bug is fixed for database dropdowns, but not for database projects. Basically, it's half-fixed. FYI - this bug was acknowledged by MS as soon as VS for database developers came out - about 2 years ago?? No hotfix was ever released for VS 2005.

No comment yet:
- Javascript debugging (coming soon)
- WPF / WCF (coming soon)