Sunday 26 April 2009

ASP.NET Model View Controller (MVC)

Another 'link collection' (along the lines of my MVVM list)... about ASP.NET MVC (Model View Controller)...
Chris Tavares' Building Web Apps without Web FormsChris explains the MVC concepts and in the process builds a simple wiki-like tool - great because it is a more 'real life application' type example than you'll see elsewhere.
Rob Conory on why You Should Learn MVCRob Conery's well-thought-out argument for giving ASP.NET MVC is a great read, with some classic quotes such as:
WebForms is a lie. It’s abstraction wrapped in deception covered in lie sauce presented on a plate full of diversion and sleight of hand. Nothing you do with Webforms has anything to do with the web – you let it do the work for you.
This, friends, is a big deal (at least to me): You’re working in a lie. The web is *not* stateful and works with this stuff called HTML sent across wires using another thing called HTTP – you need to know this, love this, and feel it at the bone level.
He provides seven excellent reasons to back up his assertion (I'm paraphrasing the headings here, you should read the original text):
  1. Testability - yes, automated testing can be conducted much closer to your 'ui surface' without needing actual ui automation (ala WatiN et al)
  2. Control over Html - no 'funky' id munging or VIEWSTATE!
  3. Extensibility (my favourite so far - the Spark View Engine)
  4. Makes you think - and that's a good thing :)
  5. Javascript has 'come of age'
  6. Learn new concepts - what are those ALT.NET guys on about, anyway?
  7. It's fun!
Jeremy D. Miller's Oversimplified ASP.Net MVC Pros and ConsTo sum up:
  • CON: ASP.NET MVC is a 'version 1' product - so be warned
  • PRO: It's easy to customize and extend, to get around point #1
Simple eh?
The Book
Professional ASP.NET MVC 1.0
Written by the "fantastic four" (Rob Conery, Scott Hanselman, Phil Haack, Scott Guthrie), I can only imagine it's a good read since I haven't bought it (yet)...
However, the first chapter by Scottgu(180+ pages) is a free download!, and you can view the sample app - nerddinner.com and download the code.
K. Scott Allen's MSDN article Life And Times of an ASP.NET MVC ControllerIntroduces Routing, Controllers, Action/ActionResult and Helpers.

AND 6 Tips for MVC Model Binding (and validation) - a hidden gem in the MVC framework!
Models incSlightly OT for a pure MVC post - applies to MVVM or any of the related patterns really - but I agree with the premise: Keep your system/tier/layer/whatever boundaries simple (DTOs) and
if there is more application specific needs than a simple DTO can provide, then create an Application Model
I guess that kinda leads into this discussion on creating View Models in MVC - I wondered about the "IEnumerable as the Model Type" in NerdDinner - Stephen discusses a 'proper' ViewModel approach too (see Listing 5 and 6 - although I'm not sure I'd put it in *Controller.cs necessarily).
Los Techies' Jimmy Bogard's How we do MVCThe 'voice of experience' from 9 months of MVC, including advice like:
  • Thin (not FAT) Controllers
  • Strongly-typed views, and discouraging the dictionary part of ViewData
  • Distinct ViewModels (seperate from the domain)
  • No magic strings
  • receive the EditModel as an action parameter, not some collection object
  • and my favourite advice:
    • Use partials when you have common markup, and the data is in your top-level ViewModel object.
    • Use RenderAction when you have common markup, but the information is orthogonal to the main concern of your view. Think like the "login widget" at the top of every screen. A filter is too much indirection for that scenario, RenderAction is very explicit.

Also links to Jeremy D. Miller's "Opinions" on MVC which is full of more sage advice!
ASP.NET MVC - the websiteMicrosoft's 'official' MVC home page - download the bits, watch videos, download templates, download sample applications and link to many more useful blog posts than described above!
VideosFrom Scottgu:
MSDN documentationIf you must...
Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helperThis is a 'specific feature' unlike many of the above links, but an important one IMO...
Your application can be vulnerable to cross-site request forgery (CSRF) attacks not because you the developer did something wrong (as in, failing to encode outputs leads to XSS), but simply because of how the whole Web is designed to work.
ALL developers of internet-accessible websites should be making themselves familiar with XSS/CSRF: how they work and how to protect against them. If this feature makes that easier/simpler using MVC... then that's probably another reason to use MVC!
Check out Stephen Walther's draft ASP.NET MVC Framework Unleashed bookRead the great draft chapters Stephen has generously posted on his blog, provide feedback and then buy the book!



UPDATED: Added How we MVC and MVC Thunderdome Principle. Both provide exactly the kind of real-world 'lessons learned' that I want to read before starting an MVC project - to know that others have experienced real-world problems, found real-world (and neat) solutions, and shared them. Now I'm free to go and make my own new mistakes :)

UPDATED: You should NOT use ASP.NET MVC if... lists some reasons why MVC may not be for you: "You rely on 3rd party vendor controls for lots of the UI" is a good one which may not be 'immediately obvious' to those looking at MVC for the first time.

Friday 17 April 2009

Silverlight 3.0 PlaneProjection (with DeepZoom)

I previously built a rather gratuitous PlaneProjection demo flipping around a Silverlight Map Control. A slightly more useful (or at least interesting) use of Silverlight 3.0 PlaneProjection is this Deep Zoom 'tile pyramid visualizer'...


[fullsize image] [try it out]

Rather than just play around with the RotationX and RotationY properties,
  • GlobalOffsetZ is used to 'push back' the larger images to sit 'behind' the smaller, foremost image
  • CenterOfRotation is set to GlobalOffsetZ * -1 so that all the images rotate around the same point
  • RotationY is then used to rotate them all together

Here are some diagrams to explain what that all means:

Firstly, each 'layer' in a Deep Zoom image is double the the size of the previous one (height/width) so when they three layers are rendered on top of each other, you can clearly see the size differences:


However when we apply the PlaneProjection to move the larger images along the Z axis (ie. in/out of the page) we can create the effect that all three images are the 'same size'.

Altering the PlaneProjection attributes listed about let's us zoom and rotate the pyramid to get a totally useless but kinda cool looking view of a Deep Zoom tile pyramid...

UPDATE: For those without Silverlight 3.0 installed, I've recorded (my first!) screencast demo (sorry it's in Flash - something to figure out another time...)

Thursday 16 April 2009

Re-blog: C# 4.0 feature focus (recommended)

Of all the blogs I follow, the one I most often 'bookmark and re-read' is probably Bart De Smet's (ok, Scottgu too).

I think I first started following Bart in 2006 when I was learning about LINQ - A custom implementation of the .NET Standard Query Operators.

However it was this recent post on C# 4.0: Co- and Contra-Variance for Generic Delegate and Interface Types that prompted this 'recommendation'. It's a perfect example of what I like about many of his posts - I learned a lot! Some of the '3.0 examples' he mentions are just the sort of thing I've noticed, wondered about and worked around before: but Bart provides the "language" and "reasoning" that explains why... sure I've probably heard the terms co- and contra-variance before, and I can understand at some 'high level' why
IEnumerable<Person> people = from Student s in db.Students
where s.Age <= 25
select s;

doesn't (currently) work, but Bart's discussion and examples feel just like the 'developer watercooler' type conversation that might take place amongst developers at work - and suddenly I understand the concepts a lot better.

I enjoy reading (and re-reading, just to fully understand them!) Bart's posts, and highly recommend them.

Tuesday 14 April 2009

Worst ecommerce website ever MkII

I blogged about how bad IMG Ecommerce's Events Online ecommerce website was last year. It was therefore with some dismay that I had reason to use the same website again, and to find it just as bad one year on.

It starts off poorly with some truly poor UI design: a button group with no default and poor names:


progressing to bad/incomplete user feedback


awful button layout (and one-question-per-form dragging out the process)


only the breadcrumb gives a hint of what to do here


and the piece-de-resistance: TWO buttons labelled Payment!


What a joke of a website from IMG "the world's premier and most diversified sports, entertainment and media company".

Runner Up...

A close second in the abysmal ecommerce website stakes is the Easter Show online ticketing site.

Lowlights include:
  • you must type in a quantity AND PRESS PURCHASE - but that just updates the quantity (it doesn't actually purchase)
  • you must press COMPLETE ORDER when you are done. But if you enter a number in any box and press COMPLETE ORDER it will not recognise that input (back to step 1).
  • note the instructions at the bottom, which might as well say "DO NOT USE YOUR WEB BROWSER THE WAY YOU ALWAYS HAVE FOR EVERY OTHER WEBSITE EVER, or it'll be your fault when your order is screwed up"!


How do these things make it through user testing?

Tuesday 7 April 2009

Polyline.StrokeLineJoin and tight corners

Sharp corners in Polylines (particularly thick ones) can create unintended artefacts - particularly apparent when converting a (somewhat shaky) GPS track into a line on the Silverlight VE Map Control.

In this screenshot the circled 'line extension' (leading off into the water) is not actually part of the path, but an artefact of a very tight corner:


A few simple additions - StrokeLineJoin being the most important - and the Path looks "correct":

<m:MapPolyline
Stroke="Blue" StrokeThickness="10" x:Name="Course"
StrokeLineJoin="Round"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"

Locations="-33.84780366140732,151.21159315109253 -33.84504135759562,151.2111210823059 -33.84418591636912,151.2106704711914 -33.84374037067171,151.21082067489624...
/>




Just something to be aware of...

Monday 6 April 2009

*.MDF' cannot be opened because it is version 655. This server supports version 612 and earlier

When I'm not playing with Silverlight and Virtual Earth, I've been figuring out MVC (thanks to Scott, Scott and Phil). However pretty early on I hit a weird error in Visual Studio 2008 when trying to 'open' a database via the Server Explorer:

The database 'C:\SOME\FOLDER\MYDATABASE.MDF' cannot be opened because it is version 655. This server supports version 612 and earlier. A downgrade path is not supported.

Background

I had created that database in Visual Studio 2008 (File → Add New Item → SQL Server Database) and now it wouldn't let me open it!

What I had done is opened, edited and closed the database file using SQL Server 2008 Management Studio. Shouldn't be a problem, right, since I'm also using Visual Studio 2008?

The Problem

Well, although I currently have SQL Server 2008 installed, I also have SQL Server 2005 (which was installed with Visual Studio 2008 originally). When I created the database originally I just assumed it was a SQL Server 2008 database - but it wasn't (it was 2005)!

Turns out that when you are create or open a file-based (.MDF) database (as opposed to using a database instance or server connection) Visual Studio needs some 'help' knowing what tools to use.

When I edited the *.MDF file in SQL Server 2008, it made some fundamental "changes" to the file (even though I didn't 'upgrade' it) which prevented SQL Server 2005 from opening it. Why was Visual Studio 2008 confused? It's a configuration setting!

To fix the problem, go to Tools → Options... → Database Tools → Data Connections and change the SQL Server Instance Name from whatever it was (probably a SQL Server 2005 instance) to your SQL Server 2008 instance, hit OK and you should be fine!





Thanks to simple-talk; and SQL 2008 Express edition error/Add new item on ASP.NET forms. A bit OT - HTH someone...

Silverlight VirtualEarth Map Control - with video

Okay - I wasn't going to do any more Silverlight VE Map Control posts... this is definitely the last one! I found some videos on YouTube that I thought suited 'animating' a map so I gave it a try. These would work MUCH BETTER if I had Silverlight-encoded videos that I could sync to/control more easily: but you get the idea...

Sydney City2Surf


Sydney Marathon


p.s. YES I know it's dodgy to have to 'sync' the start of each element manually - but without lots of hassle figuring out if the YouTube video is loaded and running it was the easiest way to proof-of-concept...

Friday 3 April 2009

Script diagrams using SQL Server 2008

Originally this script was ScriptDiagram2005 (on CodeProject), based on a SQL Server 2000 version by Clay Beatty.



I had already tested the '2005' version on "Katmai" betas of SQL Server 2008 and it worked fine, so I hadn't bothered to update the script until I read
this thread (requires login) and learned of the built-in sys.fn_varbintohexstr function.

This made the previous custom function Tool_VarbinaryToVarcharHex redundant, so I have updated the code to ScriptDiagram2008. There isn't really any code to download - just view the script (copy/paste to an .SQL file to apply to your database).

Makes it easy to add your diagrams to source control - still figuring out how to fit it nicely into Visual Studio Team System Database Edition GDR...

Wednesday 1 April 2009

Silverlight VirtualEarth Map Control - with animation MkII

In recent posts I was working to get the new Virtual Earth Silverlight Map Control (CTP) to:
  1. display (pan/zoom) an <Image> overlay

  2. display (pan/zoom) a <Path> line

  3. animate a set of <Ellipse>s that also (pan/zoom)

  4. animate the map center point to 'track' an <Ellipse>

Turns out this was all possible - there are two examples: New York Marathon and Sydney Half Marathon

Each problem was overcome as follows:

1. Use m:MapLayer.MapRectangle not Height/Width

Any "pixel-specific" measurements applied to the Image will intefere with your Map layout. DO NOT specify Height, Width, Canvas.Left, Canvas.Top - just give the NW and SE corners (latitude,longitude) of the geographic region the image should cover, like this:
<Image Source="map.png" m:MapLayer.MapRectangle="40.8325608405556,-74.1015908473376,40.5722860972124,-73.843755459154"...

2. Use m:MapPolyline not Path

Although it was possible to keep the Path inside a Canvas element and place it with MapRectangle, it did not scale well since the Path Data is effectively tied to pixel coordinates. It is possible to write code to manually scale the line, but it was much easier to re-express the line with points specified by Latitude,Longitude in a m:MapPolyline like this:
<m:MapPolyline Stroke="Red" Locations="-33.863502543277534,151.20294570922852...

3. Use m:MapLayer.Position and a custom attached property

Positioning the Ellipses was easy using m:MapLayer.MapPosition, however animating this property was a little tricky. MapPosition is of Type Location but the Latitude and Longitude properties are not easily accessible as the TargetProperty of an animation, so I needed to write custom attached properties and set them as the target in code.
<Ellipse Fill="#FFFF0000" Width="11" Height="11" m:MapLayer.MapPosition="-33.863502543277534,151.20294570922852" m:MapLayer.MapPositionMethod="Center"...

4. Use m:Map.Center and a custom (hacked) attached property

Making the Map 'viewport' itself animate proved slightly trickier again. I created another attached property (code for all properties here) for some reason only one 'axis' (Longitude) would animate.

When I removed the Longitude property, then the Latitude position would animate... but I could not get them both animating together. Figuring it was a timing issue, rather than try to "set" both properties when they Changed, Latitude gets stuffed into a static field and then set in the LongitudeChanged handler - seems to work but not sure if it's a good idea (obviously it would break if you tried to animate two maps at the same time!)

More info on the final example - no more Map Control posts for a while...