Beginning my SC Tour!

Tomorrow I'll be beginning my SC user group tour, hitting Florence (Tuesday), Columbia (Wednesday), and Charleston (Thursday).   I'll be presenting on the ASP.NET MVC Framework.  The talk is a 200 level talk, assuming that most people have a basic understanding of ASP.NET Webforms development.   We'll talk about why MVC, some of the history of the pattern, and how to implement this in your site and the importance of SoC (separation of concerns).  We'll also talk about migration strategies and running both webforms and MVC in a "mixed mode" environment.If you're in the area, stop by one of the user groups!

Silverlight Controls Contest

Page Brooks recently told me about a cool Silverlight Controls Contest he's come up with: Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";} Welcome to the Silverlight Control Builder Contest! With this contest, we hope to incite the development of many open and free Silverlight Controls that all developers can use in their applications, and what better way to do this than through a friendly contest! Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4 /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-qformat:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman","serif";} This contest is your chance to demonstrate your control building skills to the Silverlight community and win some pretty cool prizes at the same time!Check out the site here: http://gosilverlight.org/There are tons of great prizes, so either finish that control or dream one up, 'cause time is limited!

Yesterday's Workflow Presentation

Last night I gave a presentation on Windows Workflow Foundation (WF) at the Charlotte Developers Guild.  Following up on that, I figured I'd post some resources for the talk:First, the presentation slides are available on our .NET U site.  The demo app that I built is available here.  Within the project, I commented out the SqlPersistence and SqlTracking initialization -- to use them, you can uncomment those code blocks and setup a database using the scripts available in the .NET 3.0 installation folder.  The script for the bug database is included in the project -- the connection and database will need to be configured to get the application to run, or, alternatively, you can comment out the database calls.  By doing this, no data/workflows will be persisted if the application gets shut down, but it doesn't diminish the application and workflow functionality.

WorldMaps Goodness

I think I finally got Peter hooked on WorldMaps.  My latest victim.  And of course, it wouldn't be possible with the official WorldMaps evangelist, G. Andrew Duthie.  Thanks guys!A few questions came up on Twitter, so I thought I'd take the time to expound on them here.  The first question was: who are the top WorldMap users?  Here's the top 10 at a glance: Site Hits http://dancesportinfo.net 5,137,942 http://blogs.technet.com/askperf 722,489 http://www.structuretoobig.com 427,112 http://www.irritatedVowel.com 309,104 http://www.wynapse.com 243,283 http://blogs.technet.com/benhunter 155,276 http://timheuer.com/blog/ 147,714 http://blogs.msdn.com/gduthie/ 121,912 http://blogs.technet.com/davidcervigon 113,178 http://sharepoint.microsoft.com/blogs/GetThePoint/  109,067So there you have it.  I'm going to build a "live" top 50 page soon that include links so you can view the data breakdown a bit more thoroughly.One question that came up is how my stats (currently #3) are gathered -- for example, do I get a hit for everyone else's hit?   A fair question since I'm using my own service.Looking at the data above, the answer is obviously "no," traffic from other sites doesn't affect my numbers.  The sum of all hits is around 8.5 million compared to my ~400k (see an all-user mashup here).  Indirectly, much of the traffic *is* driven from folks clicking through to my site.  One way to measure this is by looking at the Global Domination and Unique Domination statistics on the maps (bottom right corner).   Global Domination shows how many unique locations you've hit in contrast to all known unique locations.   Remember, though, that this number is relative.  For example, as far as I can tell, all locations in Manhattan are considered 1 location.  So while you may have thousands or even millions of users visiting from Manhattan, it's resolved as only 1 unique location.  Unique Domination is how many of those locations belong _only_ to your map -- locations you are hitting that no one else has.   The cool thing about this number (at least I think it's cool) is that it will continually grow smaller.  Before long, having ANY unique domination above zero will be a prized value.Another question is: How is rank determined?  First, it's completely possible for some users to be lower in rank yet have stunning World/Unique Domination.  Look at Andrew's stats.  The poor guy just fell to #8 ... but holy cow, look at the global/unique domination stats.  He's schooling me and just about everyone else.Quite simply, rank is determined by the sum of all hits.  And I'm thinking it's time for a change.  The question on the table that I ask everyone who uses it is, what is the fair equation for determining rank?  Total hits as it stands today?  Hits/day average?  Unique IPs?  Global Domination?  Or a mix of all of them? As for my stats personally, I have an edge.  I was using the system months before it was available to the public, and even then, users were very slow to sign up.  While my hits/day is lower than many in the top 10, my time on the field has been longer, and has carried me a bit.  I admit that.  :)  But then, I do only use it on my home page nav, not on every page.  For example, I could use the tracking pixel version on my master page so it shows up on every page on my site, and then just display the map on my home page.  The end result would be that my Global/Unique Domination and Unique IPs would remain unaffected, however, total hits and hits per day would skyrocket.  So you see, there are many ways to interpret the stats and hard to treat it as a strict comparison.So what's on my to-do list?  1. Top 10/25/50 page, with links.2. Web services for data portability.3. Silverlight integration (somehow ... anyone want to help with that?)4. 1:many accounts or subaccounts.  5. A "no user" page.  (If you visit the "all user" page, this would be the opposite of that -- what locations have no one hit yet?  Where the all user page has high Global Domination and zero Unique Domination, this page would be the opposite -- zero Global Domination and high Unique Domination.)

My Eyes, My Eyes!

I came across this today while redeeming an online coupon.  Let's just get right to it without the preamble (click for larger version):Oh, how this pains me.  To protect the innocent I blocked off what would otherwise be incriminating, but suffice it to say this came from a large retailer.  And sadly, this is one I've been to -- I don't mean I've been there shopping (though I have), but I mean I've been to their offices, though as far as I know this is outsourced and hosted elsewhere.  Let's look over this...First and perhaps least important, scrambleId is a bigInt or others long numeric field based on the querystring (not visible in the picture, but take my word for it).  Yet, its data type is a string (inferred based on Request.QueryString) and it gets passed into the query as a string.  But it's not a string.  Now you might be thinking: the database column uniqueID may be a varchar or some other string-esque data field, making this "ok."  It might be -- but then, not a very good choice for either a primary key or, as labeled, a unique identifier.  Design-wise, this is just broken.  At the very least, it's confusing.  Since I'm picking on it, let's get nitty-gritty and say I'm not a big fan of a column named barcode in a table named barcode.  Second and mildly broken: never output details like this to the client.  (OK, this is something I'm guilty of at times -- but then, there's a world of difference between a personal site on a shared host with no information of value in the database vs. an e-commerce site collecting PII.)  Handle and log errors, but disable this kind of output via the web.config, especially in a production environment.Last and obviously the "meat" of the problem: HUGE SQL Injection opportunity! There is NO data validation on scambleID, and it's just handed over to the SqlCommand object.  Because another page takes data and presumably writes it to the database, I'm going to make the assumption that this user (based on the connection string -- likely the same one) has write and possibly dbo permissions.  I imagine it would be trivial to cause major havoc by dropping tables, updating values, compromising data, etc.  So how is this problem eliminated?  Don't execute direct SQL.  Abstract that into a stored procedure, and pass in the scrambleID as a parameter.  Change the permissions to allow this user execute only permissions on the sproc, not direct table access.  If possible, correct the data types.  I suspect there may be reasons in play for it being all-numeric (for example: a cash register that may only take numeric values).  A bigint can handle over 9,000,000,000,000,000,000 values, so that ought to be big enough.  Maybe it is a bigint, and SQL is casting it -- can't really tell.  But the nice thing is, if the value must be numeric, it's super-easy to check.  Frankly, even if you must use dynamic SQL like this, it would be easy to check the parameters.  An Int64.TryParse() or Regex would be easy to implement.  Anyway, this goes to show that these kinds of problems are very real in the world, and it's critical to evaluate them.  Peer code reviews, threat modeling, and security education can prevent these!

Raleigh Silverlight Group

Very cool news from Rob Zelt.  The web applications SIG of TRINUG will be doing some Silverlight-focused content.  He'll be speaking this Wednesday (4/2).  From Rob's blog:I've been talking with a number of people about starting a Silverlight focused group here in the Raleigh/Durham/Chapel Hill area. If you're interested, se if you can come out to the presentation I'm giving for the Triangle .Net User Group Web Applications SIG on Wednesday and we can maybe chat afterwards as well about setting another meeting up later in April. I'm thinking maybe April 22nd, 24th, or 29th?If you're interested in Silverlight, be sure to come out.

VSTS Briefings

Just saw the following events coming soon to Raleigh and Charlotte (as well as couple of other locations in the southeast).  If you're interested in VSTS, check 'em out!Come join your technology peers to learn about current and future .NET technologies.  The focus of this 1 day seminar will be around Microsoft Visual Studio 2008 Team System.  You’ll be provided with an overview of each role and the session will wrap up with a preview of the next version of Team System (codenamed “Rosario”). 9:00am Intro Visual Studio Team System/Team Foundation Server Business Value 9:30am VSTS Project Management and Collaboration Features 10:15am Break 10:30am VSTS Tester Features 11:15am Version Control and Build Management 12:00pm Lunch (Provided) 12:30pm VSTS Architect/Developer Professional Features 2:30pm Team System Futures (Rosario+) 3:00pm Closing /Q & A DATES/LOCATIONS When: March 18, 2008 Location: Microsoft Office – Charlotte, NC 8055 Microsoft Way Charlotte North Carolina 28273 United States REGISTRATION: To Register, click HERE or call 877-673-8368 and reference Event ID:1032367770 ------------------------------------------------------ When: March 20, 2008 Location: Microsoft Office – Raleigh, NC 4825 Creekstone Dr., Suite 190 Durham, NC 27703 Phone: (919) 474-4900 REGISTRATION: To Register, click HERE or call 877-673-8368 and reference Event ID:1032367772 ------------------------------------------------------ When: March 24, 2008 Location: New Horizons – Birmingham, AL 601 Beacon Parkway West, Suite 106 Birmingham, AL 35209 REGISTRATION: To Register, click HERE or call 877-673-8368 and reference Event ID:1032369273 ------------------------------------------------------ When: March 25, 2008 Location: Microsoft Office – Alpharetta, GA 1125 Sanctuary Pkwy., Suite 300 Alpharetta, GA 30004 Phone: (678) 629-5700 REGISTRATION: To Register, click HERE or call 877-673-8368 and reference Event ID:1032367769

Increasing Scalability in ASP.NET Apps

Time for another series of posts!This time, I'll talk about a few scalability options in ASP.NET applications.  Getting higher performance and greater scalability isn't a one-time, one-shot thing -- rather, it's something that is measured and tweaked continually.  While it's true that a good design up front is important, it's also true that you can't focus too much on performance tuning early in the game.  What alarmed me recently was taking a look at my performance stats up until the last few days in January, 2008:You can clearly see the worsening performance over time.   Between March of '07 and Oct '07, my page gen time nearly doubled; between August of '07 and September of '07, my WorldMaps gen time _more_ than doubled (!), RSS and home page gen times were somewhat flat. Because some of the numbers were fairly flat, I'm inclined to think that nothing profound happened on the server side (this can happen on shared hosting and is sometimes unavoidable).  Rather, it's likely some "thermal layer" for traffic was crossed -- or perhaps more appropriately, we went off a scalability cliff somewhere.  In the case of WorldMaps, the cliff analogy is certain more appropriate given the sudden change.  This is why it's so important to have ways to measure performance.  In fact, I'm not really interested in the specific numbers in as much as I'm interested in the trends.  I sat back over the weekend, dove into the logs a bit more in depth, and tweaked away.  I deployed some changes in very late January, and looking at the February stats thus far, it seems to have made a dramatic increase in performance across the board:  RSS went from about 45ms to around 5ms, home page from around 75ms to 45ms, average page and WorldMaps from around 225ms to roughly 50ms.  Still too early to call it complete, but without a doubt, a step in the right direction.  (Despite a small WorldMap bug a few folks alerted me to!  Sorry 'bout that!)The most obvious (and cost-effective) ways to increase performance would be to boost the CPU, RAM, or network capacity of the server.  None of these were options for me.The first thing I did is examine _where_ the application was running slow -- not just pages, but specific method calls.  As Jeff Prosise points out in one of his MSDN articles, once I/O requests start queueing, application performance tanks dramatically.  This is what was happening to WorldMaps.My data caching strategy was pretty good, but I needed to open things up with some asynchronous processing.  I implemented this on a few of the pages, including WorldMaps, and I believe that explains the performance increase.   Be sure to check out Jeff's article on implementing asynchronous pages in your application.  Although I implemented my async tasks a bit differently this time around, I have used precisely the methods Jeff points out in the article in past projects -- the nice thing is, it's very easy to change the behavior for debugging purposes (you could even do this via precompiler directives).Finally, especially with WorldMaps and to a lesser extent RSS, I needed some better client-side caching.  The first series I'd like to do will focus on how to pull that off effectively.  Specifically, I'll illustrate to how to do this within HTTP Handlers or within custom code.  Stay tuned!

Silverlight Beta Site: Download Center

I just noticed we released a beta Silverlight site for the Microsoft Download Center -- very cool!  The reason I like this site so much:  you won't instantly realize it's a Silverlight site.  No HD movies, no pictures flying around -- just a nice, streamlined interface.  Check it out here (you need Silverlight installed, of course!):http://www.microsoft.com/beta/downloads/Default.aspxLet me know what you think...

Network Error?

Every time I connect to the corporate network, I get the following error:What's funny about it is that I don't understand the value in limiting my connection nearly a year from now ... not exactly a motivator for immediate action!The problem is likely a missing beta patch, but because I'm running x64, it could be some specific version isn't available yet -- I'm not sure.  I'm not surprised or trying to be critical here -- frankly, if you see how much beta stuff and developer tools we're often running, it's wonderful it works nearly flawlessly.  I just wish I could find the reason for the message.

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List