Tuesday, 16 October 2007

Pretty Xaml and Search

The Silverlight Virtual Earth/Google Maps tile client v0.9 now has a few more features:
  • Search box to 'geocode' a search term and set the map to that location (eg. search for sydney cricket ground or london eye)
  • Search also accepts latitude, longitude coordinates (searching for 51.505,0.0 will get you pretty close to Greenwich)
  • Xaml controls for the map type, pan and zoom controls

Note that the search results currently default to map zoom '9' -- you should see the flag marker on the map in the top-left -- simply select zoom 14/15/16 to get closer to your target. This will be updated in a future version.

silverlightearth

Xaml tidbit: I expected to have to draw a custom path for the round-corner-rectangles, but turns out that is a supported shape-type... drawing them is as simple as

<Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Fill="#88000066" Stretch="Fill" Stroke="#444444FF" Width="130" Height="65">
<Path.Data> <RectangleGeometry Rect="10,50,130,65" RadiusX="5" RadiusY="5" /> </Path.Data> </Path>

where the RadiusX and RadiusY attributes add the rounded corners.



UPDATE: one of the 'fun' things about being able to switch between Google and Microsoft maps is seeing the differences in imagery. Here is Millenium Park (Chicago) in Google (under construction) and Virtual Earth (finished!):

Friday, 21 September 2007

Silverlight-map integration progress v0.8

TileClient08 is the latest of my efforts to integrate Silverlight with Virtual Earth/Google Maps. The improvements are all focused on the Earth maps (not Moon/Mars for now).

TileClient08_road TileClient08_satellite

It uses Microsoft Virtual Earth tiles for the 'road' view and Google tiles for the satellite view. The navigation is still a bit clumsy (centering isn't quite there yet), so the best way to give it a try is:

- click one of the city locations (Sydney, New York, London, Tokyo) and navigate around from there (up/down/left/right/in/out)

- click (once!) to set a flag and then zoom in (with the nav-link, or mousewheel). You'll notice the flag/centerpoint "dance around" a bit - just trust that it will try to keep the location in the viewport

- use the Long/Lat/Zoom inputs to go direct to any location on Earth

The slightly odd behaviour is due to the reliance on the tile-grid to lay out the images. Once I have the math worked out to make the grid of images larger (and clipped by) the viewport, it should all work a lot more smoothly. I've also fixed the (previously unknown) IE-bug: you can't treat strings as arrays apparently, so I had to make

quadkey[quadkey.length-1]


into



quadkey.charAt(quadkey.length-1)


for the Virtual Earth tiles to load in IE.



WARNING: I've just noticed (after lots of testing today) that Google's servers will eventually think you're attacking their image server if you download too many tiles too quickly (I wonder if/how Silverlight caches images?).



If you see 'Image not available at this zoom level' always on the earthsat view, Google is probably blocking the images. Click this image link to check - http://kh0.google.com/kh?n=404&v=20&t=tsrrtsqrssqqtts - you'll either see the image, or get a CAPTCHA test... haven't noticed Virtual Earth not serving images (yet...)



WOT: This post was my first using Live Writer... so far so good (although the spacing is a bit whack around the code)

Thursday, 13 September 2007

Silverlight, Virtual Earth and Google Moon

Slow progress is being made with tiles from Virtual Earth, Google Moon & Mars, and custom Venus images hosted in a generic Silverlight Map Viewer -- panning kinda works (in addition to zoom)! It's clunky, tile-at-a-time panning (no smooth drag metaphor, yet) but it (mostly) works.

Earth (VirtualEarth tiles)
Moon (Google Maps tiles)
Mars (Google Maps tiles)
Venus (custom tiles)

OK, if you visited the demo you'll know it's not quite done yet... specifically when you zoom in, the zoomed coordinates (row/col) are based on the previous zoom level, so they tend (erroneously) towards the top-left of the map; zooming out sometimes breaks around the edges too... although this is a 'silverlight' project, so far there's only a sprinkling of Xaml - it's mostly math & javascript!

UPDATE: 'earth' view doesn't seem to work in IE. Not sure why... give it a go in Firefox.

Sunday, 2 September 2007

Silverlight map control - progress update

Well, the Silverlight map control is coming along slowly...

There has been some progress on calculating the display image tiles, position, etc which is key to enabling proper pan/zoom using - the Moon map now has 'live' coordinate calculations, and very basic up-down-left-right to try.

To get an idea of what the Base4/Binary numbers mean, read about using a Binary Coordinate System and how it is applied in the Virtual Earth tile system (hint: qrts == 0123).

As for the Venus map...

...it doesn't pan yet, but all the images were custom-generated^ using this quadkey map-tile generator. It's only about 100 lines of code, and seems to be limited by the maximum image size
Bitmap resized = new Bitmap(imageSize, imageSize); //16384
All three 'venus maps' were generated using that code.

^ the moon sample currently uses tiles from Google moon.

Thursday, 23 August 2007

"Moon"light - Silverlight and moontiles

Turns out the lat-long algorithm works on the moon too!

The Apollo landing co-ordinates on faqs.org were mapped in the Silverlight TileClient straight from JSON...
 
var landings = eval('['
+' {"Name":"Apollo11","Y":0.67, "X":23.49}'
+',{"Name":"Apollo12","Y":-3.20, "X":-23.38}'
+',{"Name":"Apollo14","Y":-3.67, "X":-17.47}'
+',{"Name":"Apollo15","Y":26.10, "X":3.65}'
+',{"Name":"Apollo16","Y":-8.99, "X":15.52}'
+',{"Name":"Apollo17","Y":20.16, "X":30.77}'
+']')

Here are the points, mapped with yesterday's Javascript function CoordinateFromLongLat() and overlaid on the 'real' moon.google.com... 
 
The JSON is injected into the Silverlight Canvas using CreateFromXaml() method,

var plugin = document.getElementById("SilverlightControl");// landings is the JSON arrayvar coord = CoordinateFromLongLat(landings[0], world);var xaml = flagXaml (landings[0].Name, coord.X, coord.Y);var xamlC = plugin.content.createFromXaml(xaml); canvas.children.add(xamlC);

Where the Silverlight plugin was instantiated like this:

Silverlight.createObjectEx({ source: 'TileClient.xaml', parentElement: document.getElementById("SilverlightControlHost"), id:'SilverlightControl', 

I mention that because most of the samples discussing CreateFromSilverlight() expect the call to come from an event handler, where the sender argument has the getHost() method available.


 
UPDATE 28/8: the Silverlight-moontile client now zooms in and out (but no panning yet...)

Wednesday, 22 August 2007

Lat/Long to pixel conversion (for Silverlight, in Javascript)

Greg Schechter's Silverlight 1.1 VirtualEarth Viewer is a very cool sample (ot: as is tafiti Silverlight search interface, which I just came across today).

However the VirtualEarth Viewer is written for Silverlight 1.1, and I want RaceReplay.net to be able to display & animate maps in Silverlight 1.0. Hence the work on a custom TileClient for Silverlight - the most recent sample of which uses a few lines of Greg's codes (converted from C# to Javascript) to dynamically translate screen coordinates to latitude/longitude values (and vice versa)

See it in action here, and check out the ported code below.

/* Original Author http://blogs.msdn.com/greg_schechter
License http://msdn.microsoft.com/vstudio/eula.aspx?id=c8bf88e7-841c-43fd-c63d-379943617f36 */
function RadiansToDegrees (rad)
{
return (rad / Math.PI * 180.0);
}
function DegreesToRadians (deg)
{
return (deg * Math.PI / 180.0);
}
/* SLVirtualEarthViewer */
// Extent maps to +-180 for Longitude and +-85 for Latitude
function LongLatFromCoordinate (coordinate, worldRect)
{
var x = ((coordinate.X - worldRect.Left) * 360.0 / worldRect.Width) - 180.0;
var y = RadiansToDegrees (2 * Math.atan(Math.exp(Math.PI * (1.0 - 2.0 * (coordinate.Y - worldRect.Top) / worldRect.Height))) - Math.PI * 0.5);
var point = eval('({"X":'+x+', "Y":'+y+'})');
return point;
}
function CoordinateFromLongLat (longLat, worldRect)
{
var coordinate = eval('({"X":0, "Y":0})');
coordinate.X = worldRect.Left + (longLat.X + 180.0) * worldRect.Width / 360.0;
coordinate.Y = worldRect.Top + (worldRect.Width * 0.5) * (1 - (Math.log(Math.tan(DegreesToRadians(longLat.Y) * 0.5 + Math.PI * 0.25))) / Math.PI);
return coordinate;
}


And to use it...

var world = eval('({"Left":0, "Top":0, "Width":512, "Height":512})');
/* wired up to Silverlight event */
function onMouseMove (sender, mouseEventArgs)
{
var currX = mouseEventArgs.getPosition(null).x;
var currY = mouseEventArgs.getPosition(null).y;
var coo = eval('({"Y":'+currY+', "X":'+currX+'})');

var ll= LongLatFromCoordinate(coo, world);
document.getElementById('output').innerHTML = 'Lat/long: ' + ll.X + ', ' + ll.Y;

var coord = CoordinateFromLongLat(ll, world);
document.getElementById('output').innerHTML += '

Screen: ' + coord.X + ', ' + coord.Y;
}

Now to hook this up with a conversion to Virtual Earth image tile 'quadkey' values...

p.s. if you are interested in a slightly different version of the lat/long-coordinate conversion, download the sample code for Roll Your Own Tile Server and examine the XToLongitudeAtZoom() and YToLatitudeAtZoom() javascript functions. It's also a very cool sample.

Monday, 20 August 2007

Silverlight map 'saga' continues

After posting about my Silverlight/Virtual Earth overlay on RaceReplay and my plans for a Silverlight VirtualEarth viewer on codeplex, I got a friendly message from Microsoft about using the Virtual Earth tile servers "outside of the terms of service".

I figured it would be 'more responsible' to ensure that the Tile Client at least supported the Virtual Earth logo & copyright details, so I spent a bit of time working on displaying the correct copyright notice in Silverlight - the goal being that the Silverlight client would be indistinguishable from the "real thing".

Turns out Greg Shechter from Microsoft has come up with a similar concept (it's pretty obvious, after all) - a Virtual Earth Viewer (but using Silverlight 1.1, not 1.0)... (screenshot below)

It's a pretty cool sample - but even he didn't bother with the copyright; and it seems like a double-standard for MS to 'ask' me about accessing the tile images directly while at the same time releasing demo/samples that do exactly the same thing! Particularly since Greg's stuff actually works whereas my posts consist of a 4-tile proof-of-concept and a pile of ideas...

Thursday, 16 August 2007

Try doing THIS with javascript-driven maps



OK, I'm still working on getting the tile-grid 'working' beyond a simple 2x2 fixed quadkey BUT that doesn't mean we can't play around with the display capabilities of a Silverlight-hosted map control.

No, there's no business application per-se for randomly animating, zooming and translating the map tiles like this, but it looks cool (view larger image)

[OT] BTW, apparently there are some element names that "just don't work", this being one of them: <Storyboard x:Name="TimelineTranslate" RepeatBehavior="1x">. Had me confused for a minute when a SILVERLIGHT ERROR "TimelineTranslate has no properties" was thrown - but a simple name change and the animation worked.

Wednesday, 15 August 2007

Virtual Earth custom tile client (in Silverlight)



While RaceReplay.net works "acceptably" overlaying Silverlight and Virtual Earth to visualize animated/map data, it would be even better (smoother, easier to synchronize) if there was a Virtual Earth client in Silverlight, rather like this Flash map client for Yahoo Maps.

So, using tips from these instructions on
rolling your own tile server here is a first attempt at a Silverlight Virtual Earth Tile Client. I could post the source code - but as with all Silverlight 1.0 stuff, it's right there on the page!

The real question is - how much work to get from here to something that actually works?

Monday, 13 August 2007

Map-a-likes: where to map your running routes

Rundown of interactive mapping sites I've come across, primarily for mapping running (or other exercise) track data using either Google Earth or Microsoft Virtual Earth/Live Maps... (no, I haven't seen one using Yahoo Maps yet). Some require you to draw/trace the route, others allow upload of GPX, KML or other GPS-format data.

MapMyFitness
Includes MapMyRun, MapMyRide and MapMyTri. Uses Google Maps to draw routes, enter training data and search for others. Imports Gpx and from gmap-pedometer. Exports to Kmz. 5 star favourite.
www.mapmyfitness.com

Gmap-Pedometer
The original (as far as I'm concerned) - if there was a site around before this one, I didn't find it.
www.gmap-pedometer.com

MotionBased
Focussed on GPS data integration using Google Earth maps - since I don't have any toys, haven't really used it. Apparently has lots of 'analysis' features for your data & fitness.
www.motionbased.com

ShareMyRoutes
Uses Microsoft Virtual Earth. Exports to Gpx and Kml.
www.sharemyroutes.com

CompareTracks
Not so much a website, but a piece of software to manage maps (see NYC below)
www.comparetracks.com

ninemsn's rip-off site
Rip-off of my favourite site (above) at mapmyfitness.ninemsn.com.au - slow maps and pretty basic functionality.

BikeMap.de
In German, but you get the idea...
www.bikemap.de

Run.com
Great URL but seems relatively new (ie. very few runs in the database)... uses Google Maps.
www.run.com

and for watching only

BBC
Tour de France map - the BBC always does great stuff on the web.

New York City Marathon
NYC marathon simlator requires Java, and provided by Sportsim (who have open-sourced their software as CompareTracks - see above).

...and "sorta" related
RunPix
RunPix doesn't have an interactive map, but does do 'race statistics visualization', including a static map of where you were on the course when the leaders finished.

Thursday, 9 August 2007

RaceReplay 'RC1' (now with Silverlight & Virtual Earth)


www.racereplay.net release 3 is now live:The Designer will be mortified that I've munged the beautiful work he did by adding those dodgy arrows, but I'm sure you'll agree it's a big improvement!

Tuesday, 7 August 2007

When non-runners strike...



This is what happens when a "non-runner" publishes a race map on the web... That's a big jump off the Cahill Expressway onto Macquarie Street, guys.

Who would do such a thing? It's ninemsn's new "mapmyfitness" site, with a blatant ripoff (even the name!) of a better established, better written US-based site http://www.mapmyfitness.com/.

Too bad the ninemsn site is slow as a wet-week - I "think"' they've missed the point about JSON being light-weight
value="[
{"__type":"Ninemsn.Simba.WebControls.VE.ShapeLayer,
Ninemsn.Simba.WebControls, Version=1.0.2708.32310, Culture=neutral,
PublicKeyToken=null","Title":"Edit
Layer","Description":"","Shapes":
[{"__type":"Ninemsn.Simba.WebControls.VE.Shape,
Ninemsn.Simba.WebControls, Version=1.0.2708.32310, Culture=neutral,
PublicKeyToken=null","_id":null,"ShapeType":1,
"Title":null,"Description":null,"CustomIcon":null,
"CustomType":"Line","PhotoUrl":null,
"Points":[{"__type":"Ninemsn.Simba.WebControls.VE.LatLong,
Ninemsn.Simba.WebControls, Version=1.0.2708.32310, Culture=neutral,
PublicKeyToken=null","Latitude"
:-33.8479105875013,"Longitude":151.211593151093},
{"__type":"Ninemsn.Simba.WebControls.VE.LatLong,
Ninemsn.Simba.WebControls, Version=1.0.2708.32310, Culture=neutral,
PublicKeyToken=null","Latitude":
-33.8460304508373,"Longitude":151.211292743683},
or, if you preferred:
value="[
{"Title":"Edit Layer"
,"Points":[
{"Latitude":-33.8479105875013,"Longitude":151.211593151093}
,{"Latitude":-33.8460304508373,"Longitude":151.211292743683}
,{"Latitude":-33.8450770007942,"Longitude":151.211131811142}
Okay okay, I'm being harsh - maybe it's generated output from astoria - but the maps are slow to navigate. I wonder how the sponsor "Kellogg's Special K" feels about it - maybe they should go back to ninemsn to get it sped up (and maybe the map resized?)

Road view - big jump!Satellite view - big jump!

It's certainly no "RaceReplay" :)

Wednesday, 1 August 2007

Silverlight 1.0 RC - bug fixed!

Yes, RC1 of Silverlight 1.0 has been released (in case you missed the announcements).

Thankfully the breaking changes haven't really affected the stuff I've been playing with - it's been a fairly painless change to swap in the updated Silverlight.js file and tweak the createSilverlight() function (Sys.* has been removed - shouldn't clash with ASP.NET AJAX now):
Silverlight.createObjectEx({
source: 'Scene.xaml',
parentElement: document.getElementById("SilverlightControlHost"),
id:'SilverlightControl',
properties:{
width:'100%',
height:'100%',
framerate:'24',
enableFramerateCounter:false,
version:'1.0'},
events:{
onError:null, onLoad:null, onResize:null
},
context:null
});
What's even better is that it fixes the bug on this 400-element animation. The beta used to just 'freeze' about two-thirds of the way through the animation: all the dots stopped moving until the timeline 'finished', then they'd all disappear (jump straight to end). Now it works seemlessly - time to try it with more animated objects!

Monday, 23 July 2007

What is Astoria?

While I wait for amazon to deliver RESTful Web Services, there's plenty to read on the web...

Jon Udell posts an interesting example of a RESTing transaction... seems to me there are very few 'example interactions' around to help people understand how REST is 'different', so it makes an interesting read.

If you prefer an explanation rather than a lot of reading, watch Pablo Castro introduce Astoria Data Services (pre-MIX) and at MIX "Accessing Data Services in the Cloud" (then subscribe to his blog about Astoria and Entity Framework stuff).

SOT: If, like me (after doing a bit of reading about REST and then JSON), you started to wonder if JSON isn't superior to Xml in many respects, you'll want to download JSON Viewer as you start to build applications with it.

P.S. How do you get a job like Pablo's?

Monday, 16 July 2007

Microsoft admits: "Xml isn't everything"

With Xml, Serialization and Web Services baked into the first .NET Framework at a time that the Java world only had fairly rudimentary optional add-ons, it seemed like Microsoft was 'finally embracing an open standard' ahead of the curve... Xml has continued to become a cornerstone of .NET and Office (and BizTalk, and SharePoint, and...) ever since.

The "problem" with Xml is the growing 'weight' of Xml implementing even a basic solution "properly" - namespaces, XSD, WSDL, SOAP, WS-* standards, etc. It's no longer just a simple case of throwing a few tags together to get something done.

While Microsoft continued down the Xml-and-WS-in-.NET road, others (the Ruby community, for a start) popularised Representational State Transfer (REST Web Services).

It's light-weight and much easier to use with AJAX and other RIAs, in part because it's not Xml-centric but open to simpler 'data syntax' such as JSON. JSON slots seemlessly into browser script interpreters without pesky translations or reliability on XmlHttp implementations, so the cross-browser/standards crowd cottoned on quickly. Even 3rd party Microsoft solutions like Ajax.NET Pro used JSON.

Which brings us back to Microsoft, who appear to have 'got the message'.

MSDN recently featured an Introduction to JavaScript Object Notation (JSON) in JavaScript and .NET, comparing JSON to XML, and then subsequently released Astoria at Mix07 (an announcement likely overshadowed by the release of Silverlight).

Astoria enable(s) applications to expose data as a data service that can be consumed by web clients within corporate networks and across the internet. The data service is reachable over regular HTTP requests, and standard HTTP verbs such as GET, POST, PUT and DELETE are used to perform operations against the service.
The payload format for the service is controllable by the application, but all options are simple, open formats such as plan XML and JSON.
The use of web-friendly technologies make it ideal as a data back-end for AJAX-style applications, Rich Interactive Applications and other applications that need to operate against data that is across the web.

Compare the request format
http://astoria.sandbox.live.com/encarta/encarta.rse/Articles[Title%20eq%20'Aerobics']?$expand=RelatedArticles to a comparable SOAP-formatted request... and if it wasn't disabled by default, you'd get JSON back instead with http://astoria.sandbox.live.com/encarta/encarta.rse/Articles[Title%20eq%20'Aerobics']?$expand=RelatedArticles&$format=json

For now Astoria is an alpha/beta to help us become familiar with the concepts behind it. It is (apparently) based on Windows Communication Foundation (.NET 3.0), so it may not end-up being as 'light' as you think.

Would/could/should you base your SOA on REST/JSON, or stick with XML/SOAP? The answer may be in O'Reilly's RESTful Web Services, but then there's no substitute for trying it out yourself... your application's authorization, authentication, topology, scalability, complexity, distribution, platform, usergroup/s can only begin to guide you towards the right decision.

UPDATE: Came across these links after posting:
Will Web 2.0 displace the WS-* protocols?
The Merging of SOA and Web 2.0

Tuesday, 10 July 2007

Synchronized dragging: Silverlight and Live Maps/Virtual Earth

Further to this post on Synchronizing Live Maps & Silverlight canvas, you can now pan by dragging rather than just using the rather clumsy up/down/left/right links: both the Silverlight Canvas containing the animation AND the underlying Microsoft Live Maps can be dragged (together)!

You can try out the demo of a Silverlight & Live Maps overlay with synchronized dragging to pan (it's not yet integrated into RaceReplay.net).

It was a relatively simple implementation of the sample code provided by then Silverlight Mouse Support documentation on MSDN. As with most Silverlight stuff, you can just View Source to see how it works...

Look out MapCruncher (joking!)

UPDATE: zooming now works too. When 'implementing' the Mouse Support example, I blindly copied
    canvasT.X = canvasPixel.x;
canvasT.Y = canvasPixel.y;
into onMouseUp(), forgetting that I was also updating
        sender["Canvas.Left"] += currX - beginX;
sender["Canvas.Top"] += currY - beginY;
in onMouseMove(). Oops. Better to update that same property and avoid applying the 'transformation' twice...
    sender["Canvas.Left"] = canvasPixel.x;
sender["Canvas.Top"] = canvasPixel.y;
Also added a new cursor to indicate the map is 'draggable' - unfortunately Silverlight has a limited set of cursors to choose from, so the hand-pointing is used rather than open-hand.

Wednesday, 4 July 2007

Thinq Linq

If your initial impressions of Linq are that it's mainly for data-access (because of the syntax similarities to SQL, and the availability of Linq to SQL), thinq again!

The Linq Cookbook (although in Visual Basic) demonstrates the sorts of problems you can now solve in a couple of lines of code:
  • Change the font for all labels on a windows form

  • Find all capitalized words in a phrase and sort by length (then alphabetically)

  • Find all complex types in a given assembly

  • Find all the prime numbers in a given range

  • Concatenating the selected strings from a CheckedListBox

If you do want to read more about Linq and SQL/data access, Explore LINQ, SQLMetal and SqlTac courtesy of Red-Gate.

Wednesday, 27 June 2007

"Corporate"Book?

Interesting article about Facebook for the Enterprise.
"Today, I see a combination of Twitter and Facebook as having the potential to replace 90% of the email I receive while improving my personal productivity."

Many companies still don't see IM as anything other than a nuisance to be blocked, so it's sorta interesting to think about whether spending time on Facebook can be 'productive'.

Quote from Facebook generations
"...my 14-year-old daughter is appalled that I am a member of Facebook, and refuses to let me friend her, lest her other friends find out via News Feed."
raises an issue with I suspect would extend into "Corporate"Book - do you really want everyone knowing everything about you... at work?

[sot] Apparently Australia is the 5th biggest Facebook community, after USA, Canada, UK & Norway!

UPDATE: Looking for Facebook applications or ideas? - someone's already started a 'portal' for Facebook apps and news. Helps find neat new stuff, like the Facebook ToolBar for Firefox - because you don't spend enough time checking Facebook already...

Saturday, 23 June 2007

Synchronise Live Maps & Silverlight canvas


If you overlay a location-specific Silverlight canvas on a Live Map (or is it Virtual Earth?, you'll probably want to 'synchronise' the canvas with the underlying map as it is panned/zoomed.

Although it might seem a tough task, with the help of the Virtual Earth 5 SDK it's relatively easy.

Firstly, check out the end result - a Silverlight canvas/animation that zooms and pans with the Live Map underneath it.

To accomplish the effect, I needed to:

0. Load the map and Silverlight controls
map = new VEMap('myMap');
map.LoadMap(
new VELatLong(-33.865052673579655, 151.22375965118408),
16, VEMapStyle.Hybrid);
//...
Sys.Silverlight.createObject( "xaml/Domain.Xaml", ...
Remembering to set isWindowless:'true' and the position of the elements so they float together.

1. Add Scale and Translate Transforms to the canvas
lt;Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"
x:Name="canvasScale" />
<TranslateTransform X="0" Y="0"
x:Name="canvasTranslate" Name="canvasTranslate" />
</TransformGroup>
</Canvas.RenderTransform>
(this was the only change required to the Xaml). You will use the x:Names later to make it easy to transform the canvas.

2. Determine the lat-long of the canvas

So that you can always position it accurately, regardless of how the map has been panned or zoomed. In this case, the top-left of the canvas should be is at 33.858210507117995, 151.2127733230591, and the map center when loaded is -33.865052673579655, 151.22375965118408.

3. Support panning
Simply shift the map and canvas by the same pixel delta, eg. simply call the Pan function on the map object, and modify the named TranslateTransform on the canvas.
function MoveNorth()
{
map.Pan(0, -100);
var sl8 = document.getElementById("WpfeControlHost_1");
var canvasT = sl8.content.findName("canvasTranslate");
//canvasT.X = canvasT.X - 100;
canvasT.Y = canvasT.Y + 100;
}

4. Support zooming
Other than a little bit of hardcoding, the zoom javascript is pretty simple
function ZoomIn()
{
map.ZoomIn();
var zoom = map.GetZoomLevel();
media_scale(zoom);
return false;
}
function media_scale(zoomLevel)
{
var sl8 = document.getElementById("WpfeControlHost_1");
var canvasT = sl8.content.findName("canvasTranslate");
var canvasS = sl8.content.findName("canvasScale");

var canvasLatLong = new VELatLong(-33.858210507117995, 151.2127733230591);
var canvasPixel = map.LatLongToPixel(canvasLatLong);

canvasT.X = canvasPixel.x;
canvasT.Y = canvasPixel.y;

if (zoomLevel == 17)
{
canvasS.ScaleX = 2;
canvasS.ScaleY = 2;
}
else if (zoomLevel == 16)
{
canvasS.ScaleX = 1;
canvasS.ScaleY = 1;
}
else if (zoomLevel == 15)
{
canvasS.ScaleX = 0.5;
canvasS.ScaleY = 0.5;
}
else if (zoomLevel == 14)
{
canvasS.ScaleX = 0.25;
canvasS.ScaleY = 0.25;
}
else if (zoomLevel == 13)
{
canvasS.ScaleX = 0.125;
canvasS.ScaleY = 0.125;
}
else if (zoomLevel == 12)
{
canvasS.ScaleX = 0.0625;
canvasS.ScaleY = 0.0625;
}
// haven't supported tinier zoom levels - might need to just hide content?
}

As long as your canvas and map loaded 'in sync', the panning should work without trouble, and if the top-left lat-long of your canvasis set, zooming should work too. Note that the scale-factors will depend on what 'resolution' your original Xaml was drawn in - I was tracing a map at zoom level 16 (as you can see).

There's a lot more you could add to this - including animating the zoom and supporting 'drag' for the canvas and map...


Thursday, 21 June 2007

Silverlight/Live Maps overlay

sydney landmarks is based on
Using Opacity with a Silverlight / Virtual Earth Mashup (Remix) - in addition to changing the locations it's also using v5 of the map sdk (rather than v4).

The idea is to eventually get RaceReplay.net working with 'live' maps rather than using embedded images.

No source is "posted" - it's all right there in the browser for the View Source Reflector tool for Silverlight to see.

Monday, 18 June 2007

New code online...

New code uploaded on

RaceReplay.net - more courses, satellite imagery

RecipeNow.net - new look, SEO friendly pagenames (Silverlight 'recipe book' "coming soon")

Nothing new on Searcharoo.net but came across some more 'users': Ultimate Safari, Health service. Kinda funny seeing it in the wild.

Saturday, 16 June 2007

Silverlight z-order, html layering, etc

Took longer that it should to figure this one out: the Silverlight control on RaceReplay.net was obscuring the CssControlAdaptor menus.

Anyway, short story is that the solution is simple - WindowlessMode - and is introduced in this post on Using Opacity with a ... Mashup.

However, it shows javascript new agHost for "WPF/E", which looks slightly different now we have "Silverlight", so find your createSilverlight() function and add the bolded line (don't forget the comma):
function createSilverlight()
{
var scene = new Blend1.Scene();
Sys.Silverlight.createObjectEx({
source: "Scene.xaml",
parentElement: document.getElementById("SilverlightControlHost"),
id: "SilverlightControl",
properties: {
width: "100%",
height: "100%",
version: "0.9",
isWindowless: "true"
},
events: {
onLoad: Sys.Silverlight.createDelegate(scene, scene.handleLoad)
}
});
}
[UPDATE] isWindowless works just fine on:

  • Windows/IE

  • Windows/Firefox

  • MacOS/Firefox - Css menus look/work great versus the standard ASP.NET control

... but there seems to be a little problem with MacOS/Safari -- the menus pop-down behind the Silverlight control (making them slightly useless) BUT if you know their content, the mouseclick actually seems to go through the Silverlight control and trigger the relevant menuitem/link! Weird.
BTW, Silverlight doesn't even install on Safari 3.0 for Windows (yet)

Friday, 15 June 2007

HtmlAgilityPack rocks (again)

I've said it before, but have to say it again... the HtmlAgilityPack is awesome.

If you are doing any sort of scraping or other Html processing and aren't using it, you're writing too much code!

Today's task was parsing 38 html pages of html-tabular data into SQL INSERT statements (37,919 statements in the end). Create a ConsoleApplication, using System.IO and HtmlAgilityPack, and use this Main (redirecting the output to a textfile program.exe > inserts.sql)

string[] filenames = Directory.GetFiles(@"C:\Temp\", "*.htm", SearchOption.TopDirectoryOnly);
foreach(string filename in filenames)
{
string file = File.OpenText(filename).ReadToEnd(); // parsing out the <table> i want here
int tableStart = file.IndexOf("<table"); tableStart = file.IndexOf("<table", tableStart + 1);
int tableEnd = file.IndexOf("</table>") + "</table>".Length;

string table = file.Substring(tableStart, tableEnd - tableStart) + Environment.NewLine;
HtmlAgilityPack.HtmlDocument hd = new HtmlDocument();
hd.LoadHtml(table); // you can load a fragment, in this case just a <table></table>

HtmlNode tableNode = hd.DocumentNode.ChildNodes[0];
foreach (HtmlNode rowOrText in tableNode.ChildNodes)
{
if (rowOrText.NodeType == HtmlNodeType.Element)
{
if (rowOrText.Name == "tr")
{
if (rowOrText.Attributes["class"] == null) // only 'header' rows have a class in my example
{
String Place = rowOrText.ChildNodes[0].InnerText.Trim();
String Name = rowOrText.ChildNodes[3].InnerText.Trim();
String Time = rowOrText.ChildNodes[4].InnerText.Trim();

Console.WriteLine("INSERT INTO RaceRunner ([Name], [Time]) VALUES ('{1}', '{2}')", Name, Time);
}
}
}
}
}

p.s. in case you were wondering, the source Html was NOT valid Xml that could be loaded into XmlDocument or other built-in .NET class
p.p.s. I really must find a reliable code prettifier...

Thursday, 14 June 2007

Facebook takes off...

The 3 week old 'Facebook Platform' is getting some interesting write-ups, not only that but they've partnered with Microsoft (/Popfly) to give Yahoo Pipes a run for it's money.

Furthermore, all of a sudden everyone I know is on Facebook.com, so I'm uploading photos of
Cuba and Mexico there as well as on Flickr (maybe there's a mashup to 'share' them, but couldn't be bothered with that for now).

Where will social networking go now?

EDIT: As if in answer, SMH published OMG, mum's joined Facebook! today...

EDIT2: (the other?) Paul Allen makes a big call: Prediction: Facebook will be the largest social network in the world. There's additional coverage in SMH 19-Jul-07, but the article isn't online...

Friday, 8 June 2007

ASP.NET Ajax vs Silverlight

Not quite 'Alien vs Predator', but an interesting experiment nevertheless.

I stumbled across this post using the ASP.NET Ajax AnimationExtender to move points around and immediately recognised the similarities to the Silverlight 'race simulator' demos I've been playing with.

It seemed a natural progression to try animating same North Head (Sydney) race runner data using ASP.NET AJAX to animate the runner markers. A quick massage of the Silverlight XAML (using Excel!) and I had a couple of JSON arrays ready to go.

The result, as you can see, is not quite as smooth as Silverlight - and I suspect that Ajax would have even more trouble than Silverlight with 400 elements to animate!

You can View Source of the AJAX page - it's all there.

Saturday, 2 June 2007

Silverlight docs (link drop)

Silverlight Learning Guide is a very complete list of links about Silverlight (1.0 and 1.1), including this one which helps explain the connection between Ruby/Python and C#/VB.NET (dynamic vs 'managed'?) langauges : Clearing the air about Silverlight and the DLR.

OT1: Awesome video explaining Seadragon and Photosynth technologies from MS research. Seadragon seems like a natural progression from a viewer like Flickrleech.
Ultimately the 'player' for both should/would be Silverlight (you'd think...) The Photosynth 'Notre Dame' poster example is cool (WOT: parts of the Photosynth site are Flash9 :)

OT2: Apple will want to release a non-iPhone multitouch iPod before Microsoft launches a milan/surface based Zune

Tuesday, 29 May 2007

RaceReplay.net released

RaceReplay.net is 'live'... well, in beta form anyway.

Turns out Silverlight is a great medium for .NET developers to get on the RIA bandwagon. Flash always had a big learning curve - probably due to it's "designer-focused" background - but Silverlight and Xaml just seems to 'make sense' (to me, at least).

OT: Russ just pointed me to Flickrleech - waaay cool viewer for flickr photos.

EDIT: Silverlight vs. Flash: The Developer Story is an interesting point-of-view... although it was a loong time ago that I last developed anything in Flash, certainly they Silverlight platform makes a lot more "sense" to me.

Thursday, 10 May 2007

More Silverlight

First, thought this platform comparison (Silverlight v Flash) was interesting - not sure how complete it is thought (and it's a bit early to claim Silverlight has a "Robust video publishing tools and third-party ecosystem" but Flash does not. Thought the SEO angle was interesting (wonder how many engines do follow links to "Xaml-behind", and not sure 'DRM' is a feature everyone likes.

Anyway, the saga of RaceReplay continues... after getting race splits (mostly) working I decided to give Silverlight a 'stress test' by loading all 400 competitors into the simulation (warning: the Xaml-behind is 7Mb, so loading may take a while).

The first thing that came to mind was "that Xaml is too big!". One way to solve this will be to send the animation data via JSON and pump Xaml from Javascript into Silverlight - pretty sure that will be a lot less verbose than repeated

While googling for other options, it turns out Silverlight also supports the ZIP format. The post suggests using it to package images, but ZIPping up Xaml (text/xml) would surely show much better compression gains - my 7Mb animation canvas compresses to 576kb, so now all I need to do is figure out if it's possible to extract and inject it into the Xaml DOM. Will see how that goes - the City2Surf has 60,000 runners (wonder how close Silverlight will get to animating those...)

Sunday, 6 May 2007

Playing with Silverlight...

After mapping race courses, the next logical step seemed to be visualizing the races themselves, similar to BBC Tour coverage (link thanks to Russ) and at least one overseas marathon I've seen online (but can't remember which).

This 10k race demo shows how it could work, using Microsoft Silverlight beta 1.0 and Microsoft Expression Blend.

Got some other Silverlight ideas... stay tuned.

EDIT: Now calculates km markers automatically, and shows altitude as well. Now it really needs to support split times rather than race-average (so the 'runners' slow down on the hills!)

EDIT2: Although some 'matrix glitches' are present, km splits are now supported. Watch red catch green in the 2nd lap! The 'jumping' is due to a bug when a line segment is "split" to accomodate an intra-segement marker... kinda know where it is but too late (at night) to fix it now...

Sunday, 29 April 2007

Linqaroo I

Playing with 101 LINQ samples and Searcharoo...

The simplest query (say, for the word "recent") over the existing 'index' looks like this
var x = from wf in catalog.WordFiles
where wf.Text == "recent"
select wf;
Digging deeper into the HashSet introduced in .NET 3.5, boolean search queries (which took ages to discuss & code in Searcharoo 2) can be easily described in Linq


so that a simple method call


will produce the these results (Console Apps - the easiest way to play with any new tech :)


Of course there's little indication of well it performs, or how it will work in the code itself (no query tree parser yet, so some work still to do)... maybe i4o - Indexed LINQ will come in handy, or at least provide some ideas for proper Searcharoo-backed Linq classes.

EDIT 30-Apr: It seems possible to play with the underlying structure of LINQ in .NET 2.0, although there's a bit more work to do exploring how robust the implementation is and how good the 3rd party (Hash)Set class is.

Monday, 2 April 2007

Searcharoo.net gets a facelift...

The Searcharoo.net website has a new skin... much less 'fluro' than the old one (below :)



and a new, improved RecipeNow.net is coming soon...

Wednesday, 28 March 2007

Compact Framework... link drop

It's been a while since I've worked on CE/mobile, but getting back into it. All the stuff that's new/changed since my last 'real' mobile app makes for interesting reading...

What's New for Developers in Windows Mobile 6

Windows Communication Foundation (Compact Edition) is a great read.

OpenNETCF was an essential reference last time I checked...

Synchronization Strategies: email?!

SQL Server CE - latest name for SQL Everywhere; no it doesn't just run on Windows CE...

Thursday, 22 March 2007

'Declarative' Google Maps - store locator sample

Just added another 'sample' app:
Store Locator: Help customers find you with Google Maps to CodeProject.

I started playing with GMapEZ declarative Google Maps API in Feb, originally just for mapping 'race' courses in Sydney for my running club. Later adapted it for a couple of 'proof of concept' samples related to mapping customer data and delivery truck routes (using Google's driving directions feature).

As well as the article, you can play with the NeedCoffeeNow sample online.

Monday, 19 March 2007

Open DOCX using C# to extract text for search engine

Parsing text-content out of different file formats for Searcharoo (or other search engines) can be accomplished a number of ways, including writing your own parser (eg. not too difficult for Html) or using an IFilter loader.

However there's always going to be new document types or formats where you want to build a custom parser... and today the new Word 2007 DOCX format is an example: I don't have Word 2007 installed on my PC so I doubt there's any IFilter implementations for it lying around here either.

A bit of background: the DOCX format is basically a ZIP file containing a directory-tree of Xml files, and from what I can gather the main body of a (Word 2007) DOCX file is located in word/document.xml within the main ZIP archive.

Using a .NET ZIP library based on System.IO.Compression it's relatively simple to open a DOCX file, extract the document.xml and read the InnerText, like this:
using System;
using System.IO;
using System.Xml;
using ionic.utils.zip;
... your code to populate the DOCX filename here ...
using (ZipFile zip = ZipFile.Read(filename))
{
MemoryStream stream = new MemoryStream();
zip.Extract(@"word/document.xml", stream);
stream.Seek(0, SeekOrigin.Begin); // don't forget
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(stream);
string PlainTextContent = xmldoc.DocumentElement.InnerText;
}
If you're using NET 3.0, the System.IO.Packaging.ZipPackage class is probably a better bet than the open source ZIP library for 2.0.

Now to do some reading on XLSX and PPTX formats...

Sunday, 18 March 2007

Don't forget SQL Server 2005 'Compatibility Level' (ARITHABORT error on Xml query)

Working on a database recently that has been 'upgraded' from SQL Server 2000 to 2005. As part of the process, I added some 'Tools' stored procedures I commonly use (eg. ScriptDiagram).

For "some reason" that wasn't immediately obvious to me, I could execute these procs without trouble in SQL Server Management Studio BUT when I added some C# code that referenced a '2005-feature' stored procedure (such as using the new xml column.query syntax)...

SELECT failed because the following SET options have incorrect settings: 'ARITHABORT'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or query notifications and/or xml data type methods.

I started off trying to debug the C# code, thinking I'd done something wrong there... but then realised the Database Properties - Options - Compatibility Level must still be set to SQL Server 2000 (80). Changing that to SQL Server 2005 (90) got rid of the SELECT failed error... because I hadn't really 'upgraded' the database at all, just restored a 2000 backup into 2005.

Why the queries work in Studio still confuses me a little bit... but I'll worry about that some other time. Hope that helps someone - I didn't find anything useful on my first google for the error message.

Saturday, 17 March 2007

Searcharoo C# search engine indexes Word, PDF and more...

The latest version of Searcharoo (4) is now available for download (and read about, of course) --
C# search engine: refactored to search Word, PDF and more.

The coolest feature - searching Microsoft Office docs (Word, Excel, PowerPoint) and Acrobat/PDF files - is based on someone else's article Using IFilter in C#.

Also put a bit of work into refactoring the code structure, layout, naming, etc. At least now it might pass a "code review" (if anyone cared to conduct one:)

The project now also has it's own website www.searcharoo.net - the latest article isn't quite there yet (requires some formatting) but over time I'll post more frequently to that site; it takes forever to write, format and upload decent, CodeProject-quality work...

Thursday, 22 February 2007

Parsing DBP (Visual Studio Database Project) files

I was surprised how few people appeared to be trying to 'parse' Visual Studio Database Projects (*.dbp files). Why is it useful? If you want to construct a database from scripts in a project, you want to get exactly those scripts run - not any others that might be lying around the filesystem because Studio was too lazy to 'delete' them when they were removed from the Project (or perhaps they were retrieved from VSS).

Captain LoadTest had the same issue in 2005, and developed a
NAnt script to parse VS.Net database project files, which is a nice idea - but I really wanted to access the 'tree' of scripts from C#.

Thankfully, the open-source project AnkhSVN (which integrates the Subversion source control tool into Visual Studio) has exactly the code needed: ParsedSolution.cs and ParsedSolutionItem.cs.

I commented out some code ('context') and added this method, and that pretty much worked. Make sure you check the licence before using...
/// <summary>
/// Borrows code from the solution parser to JUST parse Database Project Files
/// </summary>
/// <param name="projectFileName">The full path to a *.DBP file</param>
public static ParsedSolutionItem OpenDatabaseProject(string projectFileName)
{
string projectFile = projectFileName; //GetProjectFile(projectFileName);

ParsedSolutionItem project = new ParsedSolutionItem();
project.Name = "Database"; //projectName;
project.FileName = projectFile;

if (System.IO.File.Exists(projectFile))
{
using (StreamReader reader = new StreamReader(projectFile))
{
string extension = Path.GetExtension(projectFile);
switch (extension)
{
case ".dbp":
ParseDatabaseProject(project, reader);
break;

default:
throw new ApplicationException("Trying to parse unknown project of type " + extension);
}
}
return project;
}
else
{
return null;
}
}

Tuesday, 17 October 2006

How to program it...

This brief 'essay' on developing a functional algorithm How to program it... is based on a 1945 book describing methods of problem solving.

The four basic steps are:
  1. First, you have to understand the problem.

  2. After understanding, then make a plan.

  3. Carry out the plan.

  4. Look back on your work. How could it be better?


I think it should be required reading for all developers - even pasted on your cubical wall!

Particularly when hiring, one of the "metrics" I try to measure in candidates is their sense of 'logic'. This is easier said than done, however; and actually what I am really interested in their natural ability or inclination to follow such a process.

It's easy to spot less 'logical' developers. They start at (and sometimes only ever do) Step #3! Sometimes, in the process of thrashing about in Step #3 they may accomplish some of Step #1. While fixing the inevitable bugs, they may also accidentally get some Step #4. But it's not an efficient process...

Sunday, 3 September 2006

The best developers are built not bought

The best developers are built not bought

At the very bottom of Bloom's taxonomy of educational objectives for cognitive skills is knowledge. That is recall (or recognition) of data or information. Applied to development terms this means recognizing the C# syntax or recalling the correct syntax to execute a loop.

At the top of the cognitive taxonomy is synthesis and evaluation. Synthesis is to be able to bring together diverse elements to form a new whole solution. Evaluation is the ability to make judgments about the value of ideas, approaches, or materials. Developers need to consistently apply these higher levels of cognitive ability to effectively perform their work.

Most people find the idea expressed as thinking more natural than describing the difference as cognitive process. In general, the more thinking that is being done about higher level ideas, such as how to integrate pieces to form a solution, the better the developer.

Sunday, 20 August 2006

Visual Studio 2005 Snippets - literal dollar sign $$$

Been using Visual Studio 2005 snippets since I installed it... double-[tab] is a common keystroke now. Of course, my first attempt to create a Snippet wasn't as simple as it should be thanks to the dollar sign escaping of variables. I wanted a 'standard' VSS region-wrapper as a snippet (yes, I realise I can also add it to our class file template).
#region Page History
/*
* $History: $
*/
#endregion
but the editor interprets $History: $ as a variable and doesn't display it. Tried Google, but not easy to search for '$' and get useful results... after a few false starts trying to Xml entity encode it (ie. &#62;) which also didn't work, I tried the double-dollar-sign $$ at random - and it worked!

Got Snippets is a great place to start when looking for useful snippets (or ideas/samples to build your own). Some of them are pretty complex.

Some other useful snippet links:

Monday, 10 July 2006

Generics, Serialization and NUnit

Latest article Generics, Serialization and NUnit posted on CodeProject.com. The googling I've done so far hasn't turned up much info on Unit Testing and Generics... seems to me that any time you write a class, you want to be able to test it, and Generic classes should be no exception; but there's not much support in NUnit for it at the moment...

Monday, 3 July 2006

NCover 'connection not established' error

I recently tried to set-up NCover 1.5 with a .NET 2.0 project on a new PC, but could not get past the error message Profiled process terminated. Profiler connection not established... the BAT file I was using looked like this (and was working fine on the build server)
@echo off
C:\DevTools2\NCover-1.5\NCover.Console.exe "C:\DevTools2\nunit-2.4.b1\bin\nunit-console.exe" "C:\Projects2\APPNAME\UnitTests\APPNAMEUnitTests.nunit" //a "Common.APPNAME.DataAccess;Common.APPNAME.Common; Common.APPNAME.RulesEngine;Common.APPNAME.Client" //ea "Common.CodeCoverageExcludedAttribute" //w "C:\DevTools2\nunit-2.4.b1\bin" //l "C:\Projects2\APPNAME\Build\NCover\NCover.log.txt" //x "C:\Projects2\APPNAME\Build\NCover\NCover.xml"


Of course, because NCover was working OK on other .NET 1.1 projects, I immediately assumed it was a 'framework' issue and spent fruitless time trying to 'figure out' why NCover couldn't "connect" to my application.

I gave up, only to be embarrassed a day or two later when this
NCover Error Message thread: Profiled process terminated. Profiler connection not established gave me the simple solution: I needed to register one of the NCover components (presumably so it can hook in to the CLR instrumentation or whatever)
regsvr32 CoverLib.dll

Doing an install of NCover from the .MSI would also have worked, but I've gotten so used to .NET applications being able to be 'xcopied' that I had just moved the NCover files from one PC to another and expected them to work.

Thursday, 22 June 2006

atlas:UpdatePanel Cancel/Abort UpdateProgress

Thanks to this blog Trabalhando com o ASP.NET Atlas Framework - Parte III for finally giving me the hint on how to add a Cancel/Abort option to the atlas:UpdatePanel UpdateProgress template.

Just add an <input runat="server" type="button"> <asp:LinkButton id="abortButton" runat="server">

The trick is id=abortButton! You don't need to add any further client or server code/jscript/whatever. The presence of that control id is enough. When the UpdateProgress is displayed, you can click to cancel the Ajax XmlHttpRequest.

Why was this so difficult to figure out? I guess because if you use the Designer to create the ProgressTemplate it adds the button for you... but i was creating the controls in Source view, and it was NOT immediately obvious how the Abort/Cancel should be implemented.

EDIT 22-Feb-07 This post is out-of-date; the released version of ASP.NET AJAX doesn't work this way... just one of the breaking changes - check the Migration Guide: Converting Applications from “Atlas” CTP to ASP.NET AJAX RTM

Sunday, 18 June 2006

,NET 3.0!

How did I not already know this... .NET Framework 3.0 will be released with Vista, and available for Windows XP and Windows Server 2003.

Interestingly (I think) it will just compile with the existing FX2.0 CLR, so I guess WinFX is just a mass of managed code? Still doesn't include LINQ or ObjectSpaces, so for database-focussed (ie. business) applications, what benefit does the renamed WinFX provide?

OT: great discussion-starter on Who needs value types anyway?, and this on .NET Framework 3.0 Naming...

Monday, 12 June 2006

RefreshPanel: precursor to Atlas

The Atlas UpdatePanel control seems to have it's genesis in the April 2005 RefreshPanel on gotdotnet.

The UpdatePanel has it's own 'book lite' on OReilly.com - USD9.99 doesn't seem to bad, although the fact they want to charge 'delivery' for overseas customers is very frustrating! The PDF itself is like an extended CodeProject article...

Sunday, 4 June 2006

Migrating to *ASP*.NET 2.0... from a Class Library project

In ASP.NET 1.1, Web Projects and the way they bind to Visual SourceSafe and a specific website make it *very* difficult to manage. I have always followed this advice to use
ASP.NET without web projects: the Project becomes a class library, and with a few minor VisualStudio configuration changes the source-control integration becomes a LOT easier.

But what happens when you want to migrate to ASP.NET 2.0? Do you:

  1. keep using the 'class library hack', but maybe forgo VisualStudio 2005's cool new features for ASP.NET Designer Support

  2. convert back to a Web Project in 1.1 then migrate to 2.0 (ie undo/reverse these instructions)

  3. migrate the 'class library' project to 2.0 first, then convert it to the new (ie post Visual Studio 2005 released add-in) Web Application Project/li>
  4. create a Web Site Project and copy all the existing pages into it

  5. or something else...



If your website is part of a larger solution (ie other projects such as Business Objects), or you have more than one developer, or you are actually using source-control, let me save you some time and recommend number 3.

  1. First open the Visual Studio 2003 Solution using 2005 and follow the steps to migrate to Framework 2.0.

  2. Then make any code changes to get it to compile

  3. Now for the tricky bit, open the <WebApplication>.csproj in NOTEPAD
    1. Add
          <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
      near <ProjectGuid>

    2. Add
      <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v8.0\WebApplications\Microsoft.WebApplication.targets" />
      near whatever other Import elements exist near the end of the file

    3. Add this to the end of the file (you may need to update some settings)
        <ProjectExtensions>
      <VisualStudio>
      <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
      <WebProjectProperties>
      <UseIIS>False</UseIIS>
      <AutoAssignPort>True</AutoAssignPort>
      <DevelopmentServerPort>2555</DevelopmentServerPort>
      <DevelopmentServerVPath>/</DevelopmentServerVPath>
      <IISUrl>
      </IISUrl>
      <NTLMAuthentication>False</NTLMAuthentication>
      </WebProjectProperties>
      </FlavorProperties>
      </VisualStudio>
      </ProjectExtensions>
      </Project>



  4. If you left the Solution open while editing, Visual Studio will detect the changes and offer to re-load. The first thing you should notice is the little 'world' in the Project icon (instead of the class-library square). The Project-Properties will also have a [Web] item, and all the benefits of ASP.NET Design-time, etc should be available.



Oh, and don't forget, if IIS is still pointing at the site's directory, you need to map the Framework 2.0 Handlers to it, using the Command Prompt...
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -s W3SVC/1/ROOT

Friday, 2 June 2006

ILMerge is my 'tool of the week'

I've already been using ILMerge to merge output from a number of different projects in a solution into a single EXE or DLL for redistribution (or inclusion in other projects). It works fantastically, particularly via an ILMerge NAnt Task.

There are a few tricks, like remembering that Type info includes the assembly name! If you're directly referring to a Type in code, or a .config file, those references MUST CHANGE if that Type is subsequently merged into a 'new' assembly with ILMerge.

That's pretty basic stuff thought. Both
K. Scott Allen: Using MSBuild and ILMerge to Package User Controls For Reuse
and
David Ebbo : Turning an ascx user control into a redistributable custom control describe another interesting use : packaging up ASCX-type User Controls into redistributable DLLs. Great idea if you find building User Controls with a Design surface to be much easier than programmatically building Server Controls.

Seems like 2.0 has plenty of cool tricks to offer if you can think of them...

Friday, 26 May 2006

ASP.NET Atlas April CTP Installation Error

It was nice to know I wasn't the only one having problems installing Atlas April CTP due to cabinet file '_28942B4D9DE730210E7C27BD4FBAD377'...is corrupt.

I originally downloaded Atlas and did "Save As" (which is my habit, to install on multiple PCs). But as with quite a few others, it didn't work: "The cabinet file '_28942B4D9DE730210E7C27BD4FBAD377' required for this installation is corrupt and cannot be used. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package."

I tried again, in both IE and FF, from my desktop and laptop (so four times) - clearing browser cache, etc (after the first time it broke, and I started googling for answers).

Then I noticed one of the comments on ASP.NET Atlas forum about the Publisher being 'Microsoft' versus 'Unknown', and it seemed like the versions I downloaded [Save As] and 'double-clicked' on were 'Unknown Publisher.
While not believing it would work , I tried again (with IE) BUT clicked [Run] instead... and the first dialog that appeared showed Publisher: Microsoft! The install worked fine from that point.

I don't know how/why the authenticode/whatever process would be different for a saved versus 'run straight away' install^, but after four failures across browsers/pcs and one success, I'd encourage others to at least give it a go -- click [Run] when you download!

^ actually, another post makes an interesting point about the effect of security/permissions in your IE 'downloads' folder versus your /My Documents/, /Desktop/ or wherever you might be placing the file when you [Save As]. I don't know enough about it to comment - but sounds feasible...?

Wednesday, 24 May 2006

Searcharoo v3 is LIVE

Ok, maybe not ALL CAPS exciting, but a new version of my 'basic' C# search engine and web spider Searcharoo is now 'ready'.

There's a pile of stuff I still wanted to add to it: creating interfaces and plug-ins for the Word and Number Normalization, a UK/Australian version of the stemmer, at least putting the 'language/culture' into the Stop/Go/Stemmer/Stopper interfaces so they could be language-specific and a lot more. They'll all have to wait for the next version...

'Support' and 'thanks' emails trickle in fairly regularly, hopefully that will continue.

I think the old articles are still worth reading...
Searcharoo: C# File system indexer and search (version 1)
Searcharoo: C# Search Engine and Web Spider (version 2)