mo.notono.us

Tuesday, January 11, 2011

"Microsoft has completely lost the web development community."

Last year Mark Pilgrim released a free e-book/site called “Dive Into Html5” (http://diveintohtml5.org/).  The site/book has served as a valuable resource on a recent Html5 project we’re working on here at AIS, and I have frequently gone back for details on topics such as local storage and canvas.  It is an excellent book for any bleeding edge web developer.  It is so choice. If you have the means, I highly recommend picking one up.

This week, Mark posted his observations on how publishing a free e-book (which is also purchasable in print format) works well for him, and that it gives great insight into what parts of the book are being read, and by whom. He then makes the following observation:

6% of visitors used some version of Internet Explorer. That is not a typo. The site works fine in Internet Explorer — the site practices what it preaches, and the live examples use a variety of fallbacks for legacy browsers — so this is entirely due to the subject matter. Microsoft has completely lost the web development community. (emphasis mine)

I forwarded this internally within AIS, and a nice debate ensued.  One common complaint was the hyperbole of the statement, and I agree; a more accurate line would likely be "Microsoft as a browser vendor has lost significant mindshare in the bleeding edge web development community."

Personally one of the things I love about Html5 (using the term the way the hypers would – to mean modern web development with client-driven UI interactions using JavaScript, CSS(3) and some HTML5 semantics) is that it has in some ways unified the web development community:  The debate a few years ago was about JSP vs .NET vs PHP vs Python vs Rails vs someotherservertechnology.  Folks from different camps seldom interacted and learned from each other.  With Html5, the backend processes are completely irrelevant, as long as they don’t muck with the Html (ASP.NET webforms is still a major sinner here, unfortunately) and developers using all sorts of backend software and operating systems are now adding to the collective knowledge, mostly working towards the common goal of getting as much functionality as possible, pushed to end users through mostly standards compliant browsers. 

For instance, our Html5 app is backed by ASP.NET MVC 2 and SQL server.  We do all our development on Windows, in Visual Studio – we’re looking to deploy to Azure.  Clearly we’re MS developers.  But we could just as well have done the app in Php against MySql running on linux and apache, and we’re taking cues from folks using python, java, Rails, Node.js, php and God knows what on the backend.

At the same time I haven’t used IE by choice for about 5 years, maybe more…

I was asked what I thought MS could do to gain back some developer mindshare – so here goes:

  • My thoughts are that if Html5 and the set of bleeding edge technologists that go with it are any kind of priority for MS,  they need to do some or all of the following:
  • Find a way to upgrade the legions of IE 6, 7  and 8 users to IE9.  This will obviously not be easy,  but they could do something similar to what Google did with Chrome frame (i.e. make IE9 a plugin for the older browsers),  or they could do something like the makers of the “IE Tab” Chrome and Firefox extensions do,  allow IE to be hosted inside Chrome,  and only activate it for certain sites.  Or let users install IE9 side by side with the older versions.   All of these would have as goal to encourage end users to use the latest possible browser for the task they need it for,  and to make them install IE9 instead of Chrome or Firefox.
  • Make IE9 the paragon of standards compliance.   (They are actually getting close to this...)
  • Bring IE9 to WP7 and whatever tablet software they're coming out with.
  • Reduce the focus of Silverlight as a browser plugin,  and make it more about web-deployed desktop apps.
  • Drastically improve the support for css and javascript in Visual Studio, including debugging and unit testing.   And give this toolset away in the form of VS Express.
  • Evolve the Dev tools in IE9 to become better than Chrome's inspector and the Firebug plugin.
  • Separate the IE development from Windows to allow quicker iterations
  • Do more things like the jQuery deal. The world of CSS is a mess (we desperately need mixins and code forks like those provided by media queries), MS could take the lead here…

The point is, whether Mark’s browser percentages are statistically valid as an indication of web developer’s preferences, or to what degree Microsoft is lagging/losing developer mindshare; these are not the pertinent questions.  The fact is that Microsoft is now not a leader in emerging web development areas – maybe they never were – but should they want to be, they need to take action. IE9 is shaping up to be a great browser, and they need to push it aggressively.

Labels: , , , , , , , , , , , , , , , , , , ,

Wednesday, January 06, 2010

MVC Route Constraint to Exclude Values

For Album Credits I wanted to allow personalized urls of the format http://albumcredits.com/yournamehere.  This turned out to be quite an interesting routing exercise.

Since this is an MVC app, our standard url format is of the usual http://albumcredits.com/{controller}/{action}/{index} kind, and for some pages, I need to allow the url to simply specify the controller, defaulting the action to index – again, the usual ASP.NET MVC pattern.

I was familiar with the constraint parameter option for the AddRoute method, but had never studied it in much detail – we’d used it to limit certain indexes to be numeric, but that was all.  For the root-level personalized urls we needed a more robust constraint – specifically we needed to exclude any controller from the list of valid personalized Urls.

I first spent more time than I cared to trying to come up with a regular expression pattern that would NOT match the list of controller names – it looked something like this:
^(?:(?!\b(foo|bar)\b).)*$
(thanks to Justin Poliey/stackoverflow.com) where foo and bar, etc were the controller names to NOT match.

Not until after I got that to work did I think to google “mvc custom route constraint”.  Of course the MS MVC team was smarter than that – custom route constraints are really very straight forward…

For my purposes, I went with David Hayden’s approach – the code below is essentially the same as his, just with the logic reversed.

using System;
using System.Linq;
using System.Web;
using System.Web.Routing;

namespace AlbumCredits.Web
{
	/// <summary>
	/// Route constraint that returns true if the parameter value is not one of the excluded values.
	/// </summary>
	/// <example>A controller constraint like 
	/// <code>new { controller = new ExcludeValuesConstraint("foo", "bar") }</code>
	/// will match "blah" or "snort" but will not match "foo" or "bar".
	/// </example>
	public class ExcludeValuesConstraint : IRouteConstraint
	{
		private readonly string[] _excludeValues;
		/// <summary>
		/// Initializes a new instance of the <see cref="ExcludeValuesConstraint"/> class.
		/// Example: <code>new { controller = new ExcludeValuesConstraint("foo", "bar") }</code>
		/// will match "blah" or "snort" but will not match "foo" or "bar".
		/// </summary>
		/// <param name="excludeValues">The excluded values.</param>
		public ExcludeValuesConstraint(params string[] excludeValues)
		{
			_excludeValues = excludeValues;
		}

		/// <summary>
		/// Determines whether the URL parameter contains a valid value for this constraint.
		/// </summary>
		/// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
		/// <param name="route">The object that this constraint belongs to.</param>
		/// <param name="parameterName">The name of the parameter that is being checked.</param>
		/// <param name="values">An object that contains the parameters for the URL.</param>
		/// <param name="routeDirection">An object that indicates whether the constraint check is being performed when an incoming request is being handled or when a URL is being generated.</param>
		/// <returns>
		/// true if the URL parameter contains a valid value; otherwise, false.
		/// </returns>
		public bool Match(HttpContextBase httpContext, Route route, string parameterName, 
			RouteValueDictionary values, RouteDirection routeDirection)
		{
			return !(_excludeValues.Contains(values[parameterName].ToString(), StringComparer.InvariantCultureIgnoreCase));
		}
	}
}

I can now use this when setting up my Route Table like this:

	routes.MapRoute("PersonalizedUrl",
		/* for urls like  */ "{personalizedUrl}",
		/* route defaults */ new { controller = MVC.Profile.Name, action = MVC.Profile.Actions.IndexByPersonalizedUrl, personalizedUrl = string.Empty },
		/* where          */ new { personalizedUrl = new ExcludeValuesConstraint(ControllerNameArray) }
	);

Labels: , , ,

Friday, August 28, 2009

Making T4MVC comply with CLS

FXCop rule CA1014 tells you to mark your assembly as CLSCompliant. If you adhere to this, your T4MVC (as of build 2.4.01 at least) will throw compiler warnings saying stuff like

Identifier

‘xxxController._Actions’
’xxxController._Views’
’T4MVC._Dummy’

is not CLS-Compliant.

If you have 10 controllers and 50 views this will result in 61 warnings…

The reason is that these are public members that start with an underscore, which is a CLS no-no:

http://stackoverflow.com/questions/1195030/why-is-this-name-not-cls-compliant

 

To solve this, edit the T4MVC.tt file to mark the code with a [CLSCompliant(false)] attribute.  Once you start this, you’ll also find additional warnings from mebers that implement the now-explicitly-non-compliant members, but a few more [CLSCompliant(false)] attribute handles that. Full code in gist below.

Labels: , , , , , ,

Monday, August 24, 2009

Web Setup MSI woes on IIS7 + solution

Just a note to my future self and to anyone else who might stumble on this:

We created an MSI to install our MVC app, but the new test server refused to install it:

The Installer simply stopped, with an Installation interrupted message, and the application event log listed the following:

Windows Installer installed the product. Product Name: XXXXX. Product Version: x.y.z. Product Language: 1033. Installation success or error status: 1603.

The correct google search term here is: Installation success or error status: 1603.

It will lead you to the solution by Ben Noyce at NInitiative:

Long nights and story short, in order to install a web setup project on Windows Server 2008 and IIS 7, you need to install the IIS 6 Metabase Compatibility role service.

Thanks, Ben!

Labels: , , , , , , ,

Making T4MVC comply with StyleCop

On a current MVC project we’re also using the excellent T4MVC template by David Ebbo.  StyleCop however, thinks the generated code is well, less than perfect – it generates some 500 warnings at the moment. 

The solution to this is a simple choice between two options:

Fix the TT file to generate StyleCop compliant code, or exclude the generated T4MVC.cs class from StyleCop.

The pragmatic choice here is of course to exclude the file.  But how?

I first tried to add <ExcludeFromStyleCop>true</ExcludeFromStyleCop> to the Compile entry in the csproj file. Unfortunately that only works with builds from OUTSIDE Visual Studio.

Sergey Shishkin has the answers:

Encapsulating the code in a region that contains the string “generated code” does the trick, but even easier is to simply put a // <auto-generated /> comment at the top of the generated file – which of course means edit the TT file to stick it there.

Would be nice to see this included in the next release….

Labels: , , , , ,

Friday, July 31, 2009

ASP.NET MVC: TagBuilder Extension Methods

I wasn’t happy with the TagBuilder class, so I improved it… See gist below:

This kind of thing could be useful in MOSS WebPart development as well…

Labels: , , , , , , , ,

Wednesday, July 29, 2009

ASP.NET MVC: Corrected Moq based MvcMockHelpers

I've been reading the mostly excellent Pro ASP.NET MVC Framework book by Steven Sanderson, but when trying to implement some of his code in my current project (yay – not SharePoint for a change), I encountered a bug by omission.  In Chapter 8, page 248, he shows how to mock the HttpContext using Moq.  Works great for most urls, but bombs if you include a Query String parameter.
 
Steve Michelotti pointed me to what he uses: the Hanselman/Kzu based MvcMockHelpers class.  Unfortunately it too has some issues (at least as written in Scott’s old post), so below is an updated version.  Get it from github.
 
Use and abuse at will

Labels: , , , , , ,