about
framework & approach
knowledge network
news & events
technology council
why join?

Tuesday, May 19, 2009

Best Of Mix ‘09 (MSDN event)

I went to this free MSDN event yesterday, a 3-hour recap of the most interesting technologies unveiled at Mix ‘09. The event focused on Silverlight 3, Windows Azure and ASP.NET MVC (we skipped that introductory lecture since we’ve been using the framework for quite a while). Here’s a quick recap.

Silverlight 3 / .Net RIA services

The MS demo guy really just focused on the RIA services extensions (a separate framework you can add on SliverLight 3 apps). The technology is built on top of SQL Server Data Services (Astoria), which provides quick REST scaffolding around your entities / db schema.

No WCF here, just an .axd resource handler with REST-like Uris that lets you access your CRUD services with no need to write code.

What’s cool about the Silverlight RIA dat aservice framework is it provides you with client-side proxy model and service classes that you don’t have to worite. Not only that, but it deals with entity states on the client, difgrams, and lets you save changes automatically or manually. It makes for a coll demo – build your entities, add a datagrid & form views to your sliverlight apps, a save button and you’re done. It uses optimistic concurrency by default, so you can even detect conflicts (mutliple users changing the same data concurrently).

You can also decorate your model classes with CLR attributes from System.ComponentModel.DataAnnotations to define validation rules (on the server), and bam – all validation is taken care of on the client as well.

I absolutely get the benefit of all this for quick and dirty intranet apps. You already have the data model, now you can build an entire RIA on top of it in a matter of hours. A few clicks in Visual Studio, some XAML, and you’re done. No need for an advanced C# programmer.

The demo I saw used ADO.NET Data services via an .ax resource handler. I’m not super familiar with that technology, but I read a blog post from Brad Abrams mentioning various data stores could be used, including REST service, nHibernate, WCF-server etc…

Personally I think MS can go a bit overboard with declarative markup with its declarative data sources etc… I think a little bit of C# never killed anybody, which is why I like the ASP.NET MVC model so much. But I digress.

Windows Azure

Azure is Microsoft’s cloud infrastructure response to Google App Engine, Mosso, Amazon Web Services etc… For those of you who’ve heard about cloudiness but don’t really know what it means, these vendors are trying to make it easy for you to deploy scalable clustered apps using a “pay for what you use” pricing model, without having to worry about load balancing, failover, redundancy etc... A typical cloud hosting offering usually consists of a combination of the following:

- Data store (SQL Server Data Services, Azure table storage, Amazon Simple DB, MYSQL cluster etc…)
- Cloud file storage (Amazon S3, virtual NAS devices, Azure simple data storage)
- Queuing service (Amazon SQS)
- Computing nodes for background processing
- Load-balanced web cluster to host your web app and/or web services

Their offerings range from pure infrastructure where you get a bunch of computing instances at the OS level (GoGrid, EC2) to a full framework (Google App Engine), with Azure and Mosso as in betweens – you don’t have access to the actual VMs, but your code is not completely dependant on your host.

What I like about Azure:

- Microsoft provides you with a full development stack / SDK you can install on your development machine. It’ll run your Azure app just like it would in the cloud, and deployment is a breeze. No other vendor out there offers anything like it. We use AWS, and we had to develop an abstraction layer for each service with implementations that allowed us to develop while not being connected to AWS. I still think it was the right thing to do since our app would now be easily portable to a different host, but it makes me nervous whenever we deploy. Unit-tests only take you so far, there are performance and scalability issues that can be impossible to detect when you’re simulating the app in a completely different environment (such as local disk access vs web service based storage).

- I registered for the beta a while a go and played with a bit. You get a staging and production environments out of the box, and deploying from staging to production is just one click.

- At first I was very excited about SQL Server in the cloud. I thought MS had found a way to scale a relational DB indefinitely. Yes, I also believe in magic. However, I was mistaken. It’s just like using any SQL server instance – sharding will be a pain, and the platform won’t work if you’re building a super-large app. For this you’ll need to use Azure table storage (closer to SimpleDB) - I’ll get to that in a minute. I’ll still put that feature as a pro since you don’t have to worry about DB maintenance and licensing – it’ll be price as you go. I have t say though, Mosso found a way to have a similar offering. Create as many DBs as you want, priced by amount of storage needed.

- Windows Server 2008 / IIS 7 support. I know this should be obvious, and Mosso & GoGrid do offer this as well, but not EC2. That’s the one thing preventing us from hosting our web app on the Amazon cloud.

What I don’t like:

- SQL Server Data Services don’t come with full-text indexing or CLR integration. So if your cloud app features a search box (I know, crazy concept, right?), you’ll need to use a 3rd party indexing app (Google?) or write your own indexer (who’s going to do that??).

- Table storage is so limited I don’t understand what I would do with it. You can basically store your entities in name/value property bags by specifying a partition key & row key. I’m fine with the inability to join, but you can’t even query data across partitions. Since each partition will always be stored on the same node, you’ll want to break your extra-large tables into multiple partitions by using multiple partition keys. So let’s say you build the next YouTuve and host – I don’t know – 500 million videos. You’ll segment your video data store into maybe 100 partitions. There’s no built-in way for you to query that huge data store at once. You’ll need to create your reports separately or use something like Hadoop (which Amazon offers) to query each partition and aggregate the results. In short: a lot of work.

- No distributed caching layer. This one baffles me. Any cloud app should be built with distributed caching in mind (like memcached). If you’re going to get 100 simultaneous requests to your load-balanced clustered, with each one potentially fetching 50 items from your data store, you could be in trouble. I’m sure SQL Server data services use replicated DBs, so that’ll help, but if MS charges for DB traffic, this could be very, very painful. Not only that, but it’ll be slower than fetching a binary serialized object from memory. IIS caching won’t do, you’ll get into big-time cache invalidation nightmares if your data changes often. The demo guy showed blob storage as a potential solution, but since operation writes the data 3 times, it’ll be slow – and potentially costly. It sounds like MS is aware of the problem, they’re working on a Velocity offering. No ETA though. BTW – Mosso has the same exact problem. Right now if you need distributed caching you’ll have to use an infrastructure offering like EC2 or GoGrid.

Conclusion

Azure looks promising. I really want pricing info though. And it sill looks about 12 to 18 months away from being exactly what I need.

Tuesday, April 28, 2009

WCF REST & ASP.NET MVC authorization

Last week I needed to implement an authorization scheme in our MVC and WCF apps. I found a bunch of resources on how to implement Role or Claims-based authorization in both frameworks, but they all required adding CLR attributes on controller actions and service operations - a bit of messy for my taste, and required hard-coding your authorization rules, which didn’t fit my requirements. We developed a system that allow us to define authorization rules at run-time, and I was looking for a way to write a single authorization front controller for all service / MVC calls. I could have gone the HTTP module way, but that would have mean writing code to parse the request & figure out what controller, contract, operation are being called with what parameters. Since all of this is already done for in the MVC and WCF frameworks, I wanted to have this authorization controller called after the request is parsed and before the operation is executed.

public class MyAuthorizedController {
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
string targetAction = filterContext.ActionDescriptor.ActionName;
string idParameter = filterContext.ActionParameters["id"];
string username = filterContext.HttpContext.User.Identity.Name;
bool isAllowed = IAuthorizationManager.Validate(username, idParameter , targetAction);
if(isAllowed)
base.OnActionExecuting(filterContext);
throw new UnauthorizedAccessException();
}
}


Now just make sure all your secured controllers extend this class, and you’re done.



WCF looked just as easy at first. In the ServiceBehavior configuration, you can define a custom authorization class in the serviceAuthorization’s ServiceAuthorizationManagerType property. The custom class needs to extend ServiceAuthorizationManager, which exposes a protected virtual method called “CheckAccessCore”. Just override that method.



public class MyAuthorizationManager : System.ServiceModel.ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
// If using ASP.NET authentication, we can retrieve the user name from HttpContext
// Of course this won't work for anonymous requests, you;d need to handle those as well
var userName = HttpContext.Current.User.Identity;

// the target service is the actual service class being called.
var targetService = operationContext.Host.Description.ServiceType;

// not used in the specfic authorization manager, but could be useful depending on your scenario
var contractDescription = getOperationContractType(operationContext);

// The following key will help check whether or not this was a valid REST request
// If the key is found, we'll retrieve the UriTemplateMatch results which will give us info about operation name and
string key = WebHttpDispatchOperationSelector.HttpOperationSelectorUriMatchedPropertyName;
var props = operationContext.IncomingMessageProperties;
UriTemplateMatch match = null;
if (props.ContainsKey(key) && (bool)props[key])
match = operationContext.IncomingMessageProperties["UriTemplateMatchResults"] as UriTemplateMatch;
else
// in this case, we'll ignore all non-REST requests
return true;

// now that we've found the UriTemplateMatch instance, we can find information about our method parameters
// we'll use 'id' as an example
if(match.BoundVariables.AllKeys.Contains("id", StringComparer.InvariantCultureIgnoreCase))
idValue = match.BoundVariables["id"];
}


// For information about the data contract (the interface mapped to the endpoint being used),
// you'll need to loop through all EndPoints in operationContext.Host.Description.Endpoints and look for
// one that has the same namespace and contract name as your context's EndpointDispatcher
private static Dictionary contractMap = new Dictionary();
private static ContractDescription getOperationContractType(OperationContext operationContext)
{
if(contractMap.Count == 0){
lock(contractMap){
ServiceEndpointCollection endpoints = operationContext.Host.Description.Endpoints;
foreach (ServiceEndpoint endpoint in endpoints) {
string contractKey = endpoint.Contract.Namespace + endpoint.Contract.Name;
contractMap[contractKey] = endpoint.Contract;
}
}
}
EndpointDispatcher dispatcher = operationContext.EndpointDispatcher;
string key = dispatcher.ContractNamespace + dispatcher.ContractName;
return contractMap[key];
}
}


So now we’ve found out the current user's username, the service’s type, the value of our id parameter, and the datacontract’s description. We’re getting close but – where’s the actual operation name (the name of the method being called)??



When using SOAP, you can easily find the action being called by using operationContext.IncomingMessageHeaders.Action. The action looks like this: http://MyService/IMyContract/MyAction1. This would be easy to parse.



Unfortunately, when using REST EndPoints, the Action message header is blank. So where is it the information stored? In an obscure untyped “data” property found in the UriTemplateMatch. When debugging, you’ll see that this property is actually an instance of type WebHttpDispatchOperationSelector+WCFLookupResult, which is a private class. It exposes 2 properties – Method (HTTP method) and OperationName (the method called on the service, which is what we’re looking for).



Why the WCF team would decide to hide the OperationName is beyond me. I kept thinking I was missing something, I went through every single property of the OperationContext class (a never-ending project), and I just couldn’t find it anywhere. How are you supposed to authorize a service call if you don’t know what action is called on the service??



My current workaround is to use reflection. Here’s the method:



	protected override bool CheckAccessCore(OperationContext operationContext)
{
[...]
string operationName = getOperationName(match.Data);
bool isAuthorized = IAuthorizationManager.Validate(username, id, operationName);
}

private static object operationNameLock = new Object();
private static PropertyInfo operationNamePropertyInfo;
private static string getOperationName(object data){
if(operationNamePropertyInfo == null){
lock(operationNameLock){
operationNamePropertyInfo = data.GetType().GetProperty("OperationName");
}
}
try{
return operationNamePropertyInfo == null ? null : operationNamePropertyInfo.GetValue(data, null) as string;
}catch{
return null;
}
}

WCF, REST & POX – a few notes about serialization

I usually use 2 types of endpoints when using WCF: SOAP for server - server communication, and REST/JSON for browser – server service calls. But yesterday, while trying to debug some POST & PUT HTTP calls in Fiddler, I decided to use a REST/XML endpoint. After all, POX is a bit easier on the eyes than JSON, and this would give me an opportunity to test my XML endpoints, which I had created but never used.

Of course all I got were HTTP 400 responses – Method not allowed. The call would fail before ever reaching the service, and therefore was probably related to some DataContractSerializer exception.

My first thought was to use the .Net source code and inspect was going on inside WCF. I had been using the “Enable .Net Source Stepping” feature of VS 2008 for a while, and it had helped immensely for various System.Web & System.Net issues. Unfortunately, I found out WCF libraries (System.ServiceModel etc…) are not included. I sent a quick not to Scott Guthrie (who posted a year ago that those libraries would be coming soon) asking about for an ETA, and he was kind enough to forward my request to Bob Dimpsey, but I haven’t heard back yet  (EDIT: Bob did get back to me last night, it looks like this will be coming out soon, but no ETA yet). So for now, no WCF source code.

Next I found some resources on how to configure WCF tracing. I configured the diagnostics to trace to the main output output window and finally figured out what was going on.

It turns out the DataContractSerializer was requiring a namespace in my message’s XML contents. Duh. I had forgotten to define the xml namespace in the DataContract. I fixed the problem, changed the message to added the xmlns attribute to the root of my xml data, and things started working.

Well, sort of. Some of my properties were missing in the deserialized object. After looking a bit deeper, it turns out DataContractSerializer forces specific ordering of your XML elements. When adding the DataMember attribute, there’s a way to specify an “Order” property. If that property is not defined, DataContractSerializer defaults to alphabetized names. This means if your class has 2 properties Name, FirstName defined, your XML data will need to list <FirstName /> <LastName /> – ordered alphabetically. Apparently it has something to do with performance and versioning.

Once I made sure my elements were alphabetized, I was able to text my REST services using XML without any problem.

Friday, October 24, 2008

Amazon EC2 for Windows is out

I was pretty excited when I received the email this morning (here's a link to the announcement). After looking at the details though - not so much.

The good news is their pricing is cheaper than I originally planned, with basic offering starting at $.125/hour (without authentication). The SQL Server instances are pretty pricey though, starting at $1.10/hr. That's roughly $750/mo. But for a large app you'll probably want to run a high-cpu instance, which will cost you twice as much.

Considering we own a license of SQL Server Standard, I'm guessing we should be able to create our own AMI on top of a base 64-bit AMI and run a high-cpu medium instance for $0.30/hr. That's not too bad.

There are still a few kinks to work out. The C: drive is still limited to 10GB, which can be problematic when installing large applications like Visual Studio. SQL Server itself requires 1.6GB available for temp files on the system drive. I don't know yet if that'll be a problem.

My only real grief is... right now Windows Server 2003 is the only supported OS. I had not planned for that, and it's a real bummer. We built our new app to run on IIS 7, and one of our new audio conversion features requires Windows Server 2008. Our ASP.NET mvc routes won't work on IIS 6, and a couple other custom http modules won't work either.

Windows Server 2008 requires minimum of 10GB available on the system drive (40GB recommended), which is the maximum available on EC2. Could this be the problem? Is this an AMI bundling limitation that will be difficult to circumvent? I really don't know. But considering EC2 is the front-runner in cloud computing platforms, limiting our options to a 5 year-old OS is pretty disappointing.

For now, I guess I'll need to give GoGrid another look.

----------------------------------------------------------

EDIT - this was posted yesterday (Oct 26th) on EC2 forums:

Thanks for all of your feedback.  Our intention is to support the widest variety of options for our customers that we can.  We are already working to support Windows 2008 in EC2, and anticipate being able to offer it publicly in the early part of next year.

Friday, October 03, 2008

Windows Cloud

Back in January I wrote about our serious need for EC2 to run Windows OSes, and since I couldn't get more info from Amazon (although Flexiscale's CEO was kind enough to post more info in a comment) I pretty much gave up and started looking elsewhere for a pay-as-you-go clustering platform to run our .Net code and SQL Server database. We built our architecture to run certain conversions on Linux using EC2, using S3 for file storage, and gluing it all with SQS. I looked closely at GoGrid to run our asynchronous processes running on .Net, IIS web servers and SQL Server database. I wasn't too excited about having to architect a solution that would run on 2 separate networks with a need to potentially transfer files back and forth between S3 and GoGrid, but our only other options were to either

  • Re-write the whole app to run on Linux (php/java/RoR + mysql) - not gonna happen
  • Use Mono. We seriously looked into it and wrote a bunch of code to run our .Net conversion service on Mono, but in the end we encountered weird errors in System.Drawing - it looks like some image formats are not properly supported. So we gave up on that - nice idea, just not stable enough yet.

GoGrid looks nice, pretty UI, easy setup, included load-balancer, and cheap SDL Server licensing. I don't like the fact that you can't create your own images - deploying more nodes in your web cluster would require installing your app on each node. They're working on it though.

Then lo and behold, on Oct 1st I received an email from Amazon announcing upcoming support for Windows and SQL Server on EC2. What a relief! This removes the need for a file transfer queue between both networks and will simplify our app quite a bit. We can still use GoGrid for failover database and web server, but the core app should be able to run 100% on EC2. Yay!

In the web 2.0 storm, where's Microsoft's cloud?

Amazon (AWS), SalesForce (Force.com), Google (app engine) and Yahoo (upcoming) are all big players in the cloud computing space. I have a hard time believe Microsoft is just focusing on upgrading their OS and doesn't see the value of hosting services. Windows Live, Office Live, SharePoint Live, Exchange Live and the new SQL Server Data Services show their commitment.

Back in March I referred to Microsoft "top-secret" cloud computing project. When I asked Steve Ballmer about an Amazon EC2 windows equivalent, he mentioned that something was in the works, and we'd know more over the next 3 months.

Well, it's been over 6 months, and I haven't heard much. Until Amazon made their announcement a couple days ago. Today it looks like Steve Ballmer decided to react to Amazon's new offering by telling the world about a new Windows OS, temporarily named "Windows Cloud". The official announcement should come in 4 weeks.

I expect the service to be pricier than Amazon's and targeted primarily to enterprise customers looking for reliability and a decent SLA, 2 things that AWS is currently sorely missing. We've see S3 and SQS outages, and the S3 SLA is nothing to write home about.

But it's good to know MS is keeping up. I love .Net 3.5, Linq, C#, ASP.Net MVC, IIS 7, SQL Server and Visual Studio 2008. These are great modern developer products and platforms, they make me very productive. I have nothing against LAMP and Linux in general, we do use those platforms for Java and C/C++ applications. But VS and .Net offer so much out of the box they pay for themselves after 2 months of work.

Monday, September 01, 2008

MS AJAX, ScriptManager and ASP.NET MVC

Note: this post is NOT about whether or not to use MS Ajax in ASP.NET MVC, nor is it a comparison between various JS framewqorks. I'll discuss this issue in another post. Also, this code will only enable MS Ajax for true Ajax apps that rely on javascript to render the UI and communicate with the server using services. This tutorial does NOT enable UpdatePanels.

Introduction

We've been writing a public API using WCF lately. After ironing out a few config issues and writing a few HTTP modules to make our API truly RESTful we were able to provide SOAP, REST / XML, REST / JSON and MS Ajax endpoints out of one service class. Pretty nice!

I've been pretty happy using MS AJAX and web service javascript proxies in the past, and when Atlas came out we started supporting its "preview" features (UI, Glitz, XML-Script etc...) so I wanted to leverage our existing javascript controls. But I'm also completely sold on the new ASP/NET MVC framework and probably won't ever go back to the postback model and its viewstate nightmare.


Here's the problem. As you probably know, by default MS Ajax requires a ClientScriptManager on your page, which itself requires a form runat="server" around it. While you can definitely do this using MVC, it kind of defeats the purpose.

The Code


After looking around and trying a few things, this is how we got it to work while still benefitting from the ScriptManager's script handling capabilities:
  • Download the AJAX 3.5 javascript library.
  • Place the javascript files somewhere in your MCV application (we'll use a "js" folder as an example).
  • First we need to hack the master page to enable ScriptManager functionality without usinga server form. On your Master Page, do the following:

    • add runat="server" to your tag
    • in the the header ("head" tag), add a placeholder:


<asp:placeholder id="lit_Header" oninit="lit_Header_Init" runat="server" />






And place this in your Master Page's code-behind:








protected void lit_Header_Init(object sender, EventArgs e)
{
((PlaceHolder)sender).SetRenderMethodDelegate(delegate(HtmlTextWriter output, Control container)
{
typeof(ClientScriptManager).GetMethod("RenderClientScriptBlocks", BindingFlags.Instance BindingFlags.NonPublic).Invoke(this.Page.ClientScript, new object[] { output });
});
}






The above code will enable ScriptManager's script handling capabilities in all the pages that implement your master page.





  • On the AJAX-enabled page or your master page's code behind, register your scripts using the ScriptManager's static methods (you can do this by overriding onload or onprerender)











protected override void OnLoad(EventArgs e) {
#if DEBUG
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjax", VirtualPathUtility.ToAbsolute("~/js/MicrosoftAjax.debug.js"));
#else
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjax", VirtualPathUtility.ToAbsolute("~/js/MicrosoftAjax.js"));
#endif
base.OnLoad(e);
}








ComponentArt users: keep reading









We use ComponentArt Web.UI (2008.1 for ASP.Net 3.5). After using the above code our AJAX code worked fine... as long as we didn't have any ComponentArt control in the page. When we included a tabstrip, all hell broke loose. Here's why.









CA components are ASP.NET AJAX aware. If the AJAX javascript library is present, they use it. If not, they create some objects to emulate basic Sys.* capabilities. They do this by checking whether a ScriptManager instance is located on the page, which makes sense. But in our AJAX implementation, we rely on the ScriptManager's static methods to manually include the Ajax library. Therefore Web.UI can't find a ScriptManager and includes javascsript that conflicts with Microsoft's and breaks it. What we need to do is add one more hack to tell the Web.UI javascript controls the Ajax library is present. This is actually really easy. Just edit your AJAX-enbabled page or Master Page's code behind (we're adding one script block to the above code):












protected override void OnLoad(EventArgs e)
{
#if DEBUG
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjax", VirtualPathUtility.ToAbsolute("~/js/MicrosoftAjax.debug.js"));
#else
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjax", VirtualPathUtility.ToAbsolute("~/js/MicrosoftAjax.js"));
#endif
ScriptManager.RegisterClientScriptBlock(Page, typeof(Site), "ComponentArt_Atlas", "window.ComponentArt_Atlas=1;", true);
base.OnLoad(e);
}








The above code sets a global javascript variable ("ComponentArt_Atlas") to "1" at the top of the page. The is the variable all Web.UI controls to check before rendering themselves.









Service proxies and other .js files









Last step - including the MS Ajax web service client proxies. Just like we registered the framework, we can now use the ScriptManager to register other javascript includes. Just edit your page or user control's code behind to register those scripts:










protected void Page_Load()
{
#if DEBUG
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjaxPreview", VirtualPathUtility.ToAbsolute("~/js/PreviewScript.debug.js"));
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjaxPreviewGlitz", VirtualPathUtility.ToAbsolute("~/js/PreviewGlitz.debug.js"));
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "PresentationService", VirtualPathUtility.ToAbsolute("~/services/MyService.svc/jsdebug"));
#else
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjaxPreview", VirtualPathUtility.ToAbsolute("~/js/PreviewScript.js"));
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MicrosoftAjaxPreviewGlitz", VirtualPathUtility.ToAbsolute("~/js/PreviewGlitz.js"));
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "MyService", VirtualPathUtility.ToAbsolute("~/services/MyService.svc/js"));
#endif
}








Conclusion


It took me a a little while to figure this out, and I hope this will save you some work. However, my experiences with MS Ajax lead me to a more interesting question. Since its preview code (xml-script, Glitz, Preview.UI etc...) did not get updated in months, I'm going to assume those were put back on the shelf and won't ever be released. So what exactly does MS Ajax give me out of the box? How does it compare with Prototype and jQuery? That's what I'm looking at right now, and it's not looking pretty.

Friday, March 07, 2008

Mix - Conclusion

The bad:
  • UX track needs some work.
  • Business panelists were not very impressive and forward-thinking. I found the 2006 sessions with Ebay, MySpace and Amazon to be more interesting. Those guys actually had profitable businesses. Web 2.0 guys make cool stuff but still have no idea how to make a buck out of it other than ads.
  • Keynote was too demo-centric. I understand the need for some wow-factor in order to get developers excited acount SilverLight, but IMO flying images and glossy buttons don't "wow" anybody anymore.

The good:

  • The Ballmer / Kawasaki interview was a lot more fun than the Gates / O'Reilly discussion at Mix 06. Tough questions, good humor, and Ballmer is just fun a guy. I was really thrilled I got to ask him the EC2 question.
  • I got more interesting info on the tech side than I expected. SilverLight finally looks promising, Version 1 was just a toy, more of a CTP than anything else. But this is pretty cool.
  • I'm very impressed with the MVC team. It's so unlike Micrsosoft: hire active smart bloggers, forward thinkers with deep community relationships (small team, only 4 FTE right now), give them complete freedom, and see what happens. They're not even locked into a release schedule. New builds will happen frequently and are completely based on community feedback. Basically it's like an open-source project with virtually unlimited funding. Any developers' dream. These guys were so honest about the company, didn't care about pissing people off, it felt very non-corporate. I loved it.
  • Open Space is a great concept. I wish I had spent more time there. The 45 minutes I spent chatting directly with Scott Hansleman and Phil Haack were worth the $1300.
  • The overall openness and unpretentious tone were promising. Microsoft's always been great at supporting developers, and that hasn't changed. "Web developers, web developers, web developers!!!"

Mix 08 - Day 3

SilverLight / Ajax integration

Some good ideas there, like how to integrate your siliverlight app with the Ajax history manager. I was impressed with how transparent the integration is.

Not only can you can access any DOM element or JS object from SilverLight, but you can even register managed code event handlers for javascript events. That's pretty cool. The JS to SilverLight integration is really good, too. Just mark any method as Scriptable, register it, and JS will be able to access it. The JS proxy converts CLR types to javascript objects automatically. I believe you can register javascript event handlers to CLR events as well.

It did give me a bunch of ideas in terms of expanding my Ajax code without breaking the good old HTML page metaphor. For apps other than email clients and intranet apps, Flash and Silverlight apps just look weird. When developing apps for the masses, you have to always weigh usability vs what users are used to. The Office Ribbon may look nice, and for all I know it may be more usable, but it is so different from the traditional menu system it took employees a long time to get used to it. That can be OK in an enterprise environment where people are paid while trained, but in the web world, this can kill your business right there. Areas that could benefit from Ajax support may be file system access, local storage, rich media display (project management Gant chart etc)... tons of possibilities there.

The one thing I'm still going to use Flash for for a while is audio/video capture. Silverlight doesn't have that capability yet.

Creation internation apps

Not much new here- use resource files, place resources in satellite assemblies etc...
A few good points though.
  • Avoid the conpt of "Countries' for liability reasons
  • Don't create maps and deal with border problems.
  • Don't show flags.
  • Avoid text in images.
  • Of course, build a UI that can accomodate for varying string sizes.
  • Make sure fonts have full Unicode character coverage.
  • Localize javascript and CSS files.

Thursday, March 06, 2008

Mix 08 - Day 2

Out of the 3 sessions I attended yesterday the SEO one really stood out. Great session. I got a ton of cool tips out of it. It pretty much paid for the trip. I'll post the link to the video as soon as I find it.

Oh yeah, and the TAO party was really great.

Steve Ballmer keynote

Great keynote today. Ballmer is a fun guy, and answered tough questions with a smile. He looked like a motivated, smart, and surpisingly honest guy. I got to ask him a question about Micrsofot's plan to offer an Amazon EC2 / S3 alternatice on the MS platform, and he pretty much told me it's in the works, but still confidential. We should know more in 3 months. But basically he admitted MS will have a hosted file storage and utility computing offer pretty soo. Exciting stuff.

UX Track - a failure

When I read about the UX track I got pretty excited. Information architecture. Interaction design. I thought I'd get a bunch of great tips, dos and don'ts that'd help me create great web experiences. I've attended 1 1/2 sessions, and it was quite a disppointment.

In session #1 (interaction design), we learned about the revolutationary concept of "brainstorming", but rebrnded under the name "ieation phase" - they're consultants, they have to pretend to be thought leaders to make money I guess. But nothing about actual interaction design in web apps.

Session #2 (information architecture) unveiled the secrets of folksonomy (fancy consultant word for tagging), and wasted 30 minutes of the attendees time in modeling a "Hotel" class. ("Hmmm.. it should probably have a name and a description, maybe a location as well? What data types could that possibly be?"). Are you kidding me??? This is what my interns do all friggin day!

UX track is a wonderful idea with incredibly poor implementation. 1 hour is not enough time to do group activities (which are overrated anyway) and learn something. Tell me something I odn't already know, or don't bother.

I wasn't the only one feeling that way. Other designers walked out. If Microsoft wants to keep Mix interesting by keeping a mix of designers and developers, they better fix this fast.

Other sessions

ASP.NET Ajax - nice presentation by Nikhil Kothari . Some nice little code snippets and Ajax best practices. I think it's worth mentioning XML-Script is pretty much dead in the water. Micrsosoft is looking at a different approach for client-side databinding and templating.

Great MVC session. Scott Hanselman is clever, funny guy. They're doing a really good job with that framework. The open space discussion afterwards was very interesting. It looks like we'll have to wait for the next preview to get better AJAX support, but they seem to be trying to monthly builds out, so that's encouraging. MS has a good team working on this.

Good quote from Scott: "compilation is really just a series of unit tests". He even went as far as questioning the purpose of compilation altogether. When using test driven development methodolgy (TDD), are strongly typed languages really just useful for intellisense support? Probably. But that's where Sscott and I disagree. Intellisense support and code readablilty are a big deal for me. My app has over 100,000 lines of code. I can guarantee you that if everything was loosely typed, handing code over to new developers / interns etc... would be a nightmare.

I also learned about how to use Linq's dynamic data binding when submitting a form. Pretty cool, but you gotta make sure you don't expose vulnerability. It reminds me a bit of SQL injections. Trusting the query makes coding easy and saves a bit of time, but can lead to serious security holes.

That's where Scott's recommendation of using custom objects between Controller and View makes a lot of sense. Only expose what the view needs to know. It doesn't solve the problem of trusting the query at the controller level though. Here's a concrete example.

Let's say theProduct class has a Name and Description Property. For whatever reason, in a specific context you only want to expose "Name" as editable in your HTML form. In asp.net, injecting more properties in the post data is difficult, if not impossible. When using a FormView/DetailsView, you'd need to inject a new databound control in the data control tree, all on from the client. You just can't do that.

In MVC, if using Linq dynamic data binding (something like Bind(c => Form.Product) - I;d need to look up the exact syntax), you'd basically matching Product properties by name. If your post data contains a "Product.Description" field, it'll get updated.

So... watch out.

Another topic of discussion revolved around building business objects leaning towards the UI tier rather than data tier. A typical business tier might know about DataRows, DataSet etc... But think about business objects containing validation and presentation attributes around its properties. It can make view building pretty easy.

That's basically what SalesForce does. When building custom objects, you define validation rules at the object level. It makes a lot of sense IMO. The biggest complaint I've had from users though is the lack of customization at the presentation level.

Anyway, it was a very interesting chat with very smart people. I'd love to see the ability to set validation rules at the object level.