|
|
These blog entries are written by industry experts and leaders. We consider this content to be a good read for any software developer or web technologist.
April 2007 - Posts
-
Mortimer is taking up TDD, and starts a new project by writing the following test. _
Public Sub CanReverseString()
Dim input As String = "OdeToCode"
Dim result As String = Utility.ReverseString(input)
Assert.AreEqual("edoCoTedO", result)
End Sub
Yes, it's another one of those big projects that reverses strings all the time.
With a test in place, Mortimer writes the following stub. Public Class Utility
Public Shared Function ReverseString( _
ByVal input As String) As String
Return Nothing
End Function
End Class
Good news - the test fails! Now it's time to provide a real implementation... Public Class Utility
Public Shared Function ReverseString( _
ByVal input As String) As String
Dim chars As Char()
chars = New Char(input.Length) {}
For i As Integer = 0 To input.Length - 1
chars(i) = input(input.Length - i - 1)
Next
Return New String(chars)
End Function
End Class
Mortimer thinks he has everything straight - but the test still fails! What could be wrong with Mortimer's ReverseString? 
|
-
-
I almost can't believe the great news that came from MS today. That's right, the ADO.NET Entity Framework has been delayed ! I bet most of you think I'm being sarcastic, but I am serious. I've got at least three reasons why this is good news to me. First, this gives Linq to Sql a better opportunity to thrive. Linq to Sql is the "simpler" OR/M that's looking good enough for the vast majority of cases, while ADO.NET EF is far more complex -- and yet most gurus only wanted to talk about the EF. Next, since ADO.NET EF is so complicated, it absolutely must have a great designer ship concurrently, which was not the plan. MS has apparently accepted this feedback since this is at least the publicly given rationale for the delay in shipping the EF. Finally, and this one may not pan out, but it is my own hope that ADO.NET EF is being re-aligned somewhat with Linq to Sql. These two O/RMs are similar enough to share at least some code, and I believe that some of the MS guys have hinted at this too. So I'm happy that at first there will be one O/RM -- Linq to Sql. The gurus may be disappointed, but the vast majority of MS devs will be new to O/RMs anyhow, and Linq to Sql will be good enough. Very much like my simple WilsonORMapper has been so widely used. 
|
-
This week we shipped IIS 7.0 Beta 3 as part of the Windows "Longhorn" Server release. IIS 7.0 is the biggest release of IIS in the history of the product, and brings with it major improvements to the Microsoft web-server stack. This article and this blog post list just a few of the major improvements it delivers. New IIS 7.0 Beta3 Features This week's IIS 7.0 Beta3 release introduces a bunch of new features and capabilities above and beyond what shipped in the IIS 7.0 release that came with Windows Vista. These include: - Web Farm Shared Configuration: You can now configure your web-servers to be stateless, and centralize all configuration, code and content across web farms (making it much easier to scale out and manage). Learn more about how to use this new feature here.
- Delegated Remote Administration: You can now use the IIS7 admin tool to remotely manage web-servers over HTTP/SSL. Server administrators can now lock down and "delegate" settings to site administrators - enabling much more fine-grained control over who can manage sites on the machine (ideal for hosted scenarios).
- Automatic Application Pool Isolation: IIS 7.0 makes it much easier to provision and isolate application pool worker processes on the web-server. This is ideal for hosting scenarios, as well as enterprise scenarios where you want complete isolation and sandboxing between applications.
- Built-in FastCGI Support for PHP and other extensions: In addition to providing rich .NET extensibility, IIS 7.0 now ships with built-in support for FastCGI extensions - making it easy to use with dynamic web server frameworks like PHP.
- New FTP Server: The new IIS7 FTP Server now adds support for secure publishing with FTP/SSL, host header FTP support, integrated admin tool support, and support for plugable authentication (using the same provider model as the ASP.NET Membership system).
Make sure to check out Bill Staples' blog post here to learn more about all the above features. IIS 7.0 Go Live License After months of stress testing in our labs, we think IS7 is now ready for broad customer deployments. To facilitate this, Microsoft is now offering a special Go-Live License for IIS7 and Windows Server "Longhorn" Beta3. This allows you to deploy IIS7 servers into production environments immediately (note: we have already deployed www.microsoft.com on this build). You can learn more about the IIS7 go-live license, as well as how to freely download Windows Server "Longhorn" Beta3 here. Alternatively, you can also sign-up for a free IIS7 Beta Hosting Account from one of several web hosters who have deployed IIS7 Beta3 already. You can learn more about their free IIS7 offers here. Hope this helps, Scott 
|
-
Here is a pop quiz for language aficionados.
Examine the following class:
public
class Foo
{
public
int GetUpperLimit()
{
Console.WriteLine("GetUpperLimit
invoked");
return
5;
}
public
IEnumerableint> GetCollection()
{
Console.WriteLine("GetCollection
invoked");
return
new
int[] { 1, 2, 3, 4, 5 };
}
}
Now examine the following console mode program:
class
Program
{
static
void Main(string[] args)
{
Foo
foo = new
Foo();
for
(int i = 1; i
{
Console.WriteLine(i);
}
foreach (int
i in foo.GetCollection())
{
Console.WriteLine(i);
}
}
}
Without using a compiler, do you know:
- How many times "GetUpperLimit invoked" will appear in the output?
- How many times "GetCollection invoked" will appear in the output?
Now, examine the same console program in VB:
Sub Main()
Dim
foo As
New Foo()
For
i As
Integer = 1 To foo.GetUpperLimit()
Console.WriteLine(i)
Next
For Each
i As
Integer In foo.GetCollection()
Console.WriteLine(i)
Next
End Sub
Bonus third question:
- Will the output of the VB program be the same as the C# program?
I was suprised by the answer to the last question ... 
|
-
Jeff Atwood recently published a blog entry titled How Now to Write a Technical Book, in which he compared Charles Petzold's latest book to Adam Nathan's. In short, Charles's book - Applications = Code + Markup - lacks the color, diagrams, screen shots, and structural elements (like bullet points, tables, sidebars, and so forth) that are found throughout Adam's book, Windows Presentation Foundation Unleashed. To highlight the difference in style/layout, Jeff includes screen shots from both books. Charles's text is drab and gray, Adam's is bright and dynamic. The code looks like it does in Visual Studio; the figures, headings, and bullet points help break up the flow of the text.
Jeff's analysis follows:
“Beyond the obvious benefit of full color printing, which adds another dimension to any text, it's not even close. The Nathan book is the clear winner:
- It's full of diagrams, screenshots, and illustrations showing the meaning of the code.
- The text is frequently broken up by helpful color-coded sidebars such as "digging deeper", "FAQ", and "warning".
- The code/markup snippets are smaller and easier to digest; they don't dominate page upon page of the text.
- Liberal use of bullets, tables, subheadings, and other textual elements provides excellent scannability.
- The book has a sense of humor without being obnoxious or cloying.
- Did I mention it's in color?
“The Nathan book is brilliant. It reads like a blog and competes toe-to-toe with anything you'd find on the web. Petzold's book, in contrast, is a greyscale sea of endless text and interminable code. There are so few diagrams in the book that you get a little thrill every time you encounter one. It also artificially segregates code and markup: the first half is all C# code; it's not until the second half that you see any XAML markup whatsoever, even though XAML is one of the most important new features of WPF, and the one developers will be least familiar with.“
Charles has responded to Jeff's comments via a blog entry of his own titled, The Future of Writing?
“I've been mulling over Coding Horror's analysis of two WPF books, not really thrilled about it, of course. The gist of it is that modern programming books should have color, bullet points, boxes, color, snippets, pictures, color, scannability, and color.
“Does that remind you of anything?
“Apparently the battle for the future of written communication is over. Prose is dead. PowerPoint has won.“
I don't know Charles personally, but from his online reaction it sounds like he is taking Jeff's (constructive) criticism a little too personally. And Jeff's comments do remind me of something - web developers (like myself) who develop very functional but very ugly web applications only to have customers and managers and the graphics guys come in and say, 'Holy crap, that's an ugly website, we need to add some icons and background images.' When this happens, there's two ways to response:
- Take their suggestions/comments/changes as an insult to your web development skills, or
- Realize that you do some things well (backend web development, data modeling, software architecture, etc.) and there are other things that you are not so hot at and others excel at (layout, design, usability, etc.).
Charles response sounds similar to the discourse you'll hear from a coworker who decides to response to criticism on his website's layout using option #1 above. And just like that coworker, Charles is wrong. Design matters. It doesn't trump functionality, but it does matter as design affects usability, which, for a book, is its readability. As one commenter in Jeff's entry wrote: 'I have both books and Petzold's book actually made me loose interest in WPF. It's just depressing to read that thing.'
Adam Nathan's book is published by Sams Publishing, which doesn't surprise me. I've written all but one of my books with Sams and their editors have always encouraged using different elements to break up the flow of text, be it figures, bullet points, notes, sidebars, warnings, code listings, notable quotes from the book's text, and so on. When submitting chapters for review to my editor at Sams, I found that if I had a page or more of solid text, I'd get a comment suggesting various elements to break up the text. And while my technical books with Sams were all in gray scale, I also wrote a book for Sams for the beginners market titled, Create Your Own Website. This book was in color and on every other page (or so) the margin included a sidebar that had further information or ideas for developing their own website or online tools they could use (such as validators, free images and clipart, free design templates, and so on).
For more on this discussion on this topic, check out the comments in Jeff's blog post. There's also a good entry by Phil Haack: Prose Is Dead. Long Live Prose.
(An aside - Jeff provided his own constructive criticism at my last book's title in his post, Teach Yourself ASP.NET 2.0 in 23 Hours, which highlights the flaws in titling books Learn X in TimeUnit. And while the naming scheme does have its drawbacks, I vehemently disagree with Jeff's final conclusion 'that books with titles like Teach Yourself ASP.NET 2.0 in 24 Hours cheapen our craft.' My response was a long-winded blog entry titled, Can You Learn ASP.NET in 24 Hours?)
|
-
Over the next several months there will likely be a severe shortage of blog posts here at ScottOnWriting.NET. My wife and I are taking a bit of a sabbatical this summer and doing a lot of traveling and hiking. During this stretch - from about now until late September - my ASP.NET work will be curtailed to only include writing my weekly article for 4GuysFromRolla.com and my monthly Toolbox column for MSDN Magazine. Seeing as I try to keep this blog's focus on technology, .NET, and writing, I don't anticipate much content will be added here until our return. Any trip-related blogging will be done on my personal blog site, ScottOnLife.com. The most recent entry, The Upcoming Summer of Travel, provides more detail on our trip, for those interested.
On a slightly related note... when I first started this blog back on July 2, 2003 (see the first post), I used Scott Watermasysk's .Text blogging software. Since then, .Text has turned into a much more feature-rich and mature product called Community Server, which also includes features like galleries, forums, and so forth. However, I've stuck with .Text throughout these years, mostly because .Text worked. Updating was a low priority and work kept me busy. Anywho, as I started winding down my writing and consulting gigs in anticipation of our travels, I ended up with some free time on my hands and decided to convert ScottOnLife, which was also running the same antequated version of .Text, to the latest and greatest version of Community Server. I've still got some rough edges to work out, like ensuring that the old .Text links still work and don't 404, but overall the transition went fairly smoothly. But once those get resolved my plan is to upgrade ScottOnWriting.NET, too. I am a little doubtful that this will happen prior to the start of our trips, but I write it here to sort of make sure I make this conversion when we get back in September/October. :-)
Finally, I get a lot of emails from people asking when the next set of tutorials will be published in my Working with Data in ASP.NET 2.0 series. There are currently 57 tutorials published online at www.asp.net, but I have written 75 in total. Those will appear on the site over time, based on the availability/schedule of the folks maintaining the www.asp.net website. I have been told to expect the next batch within one to two weeks, but nothing more specific. Wish I could provide a more definitive timeline. In any event, you can always subscribe to the tutorial series's RSS feed so that you will know when new tutorials are published.
See you in September!
|
-
The skill of writing is to create
a context in which other people can think.
-- Edwin Schlossberg
Jeff Atwood presents a visual
contrast of two WPF books in "How Not To Write A
Technical Book". I haven't read either WPF book, but Jeff's post did provoke some
thinking…
Color Me Code
It's amazingly difficult to read code in monochrome these days. Language keywords, program comments, and string literals all blur into lumps. There is now chance to scan the source code for the important bits. Unfortunately, many publishers are unwilling to accept the higher cost of full color printing (except for technical books in the higher-education market, where the consumer is a PHY 101 student and at the publisher's mercy). Most college textboxes are printed in full color, but full color computer text books are a rare find.
If we look at some currently shipping WPF books, we see they are all heavily discounted from their list price and fall into the same price range:
It seems that publishers are pricing their books based on the competition and not on the production costs. Shrinking margins don't bode well for features like color.
I Have a Tip for You
Another topic in Jeff's post was the use of sidebars and callouts. Some people
love sidebars. I don't.
A good technical book makes me think. An even better technical book
makes me get to the keyboard to try something. Books with colored sidebars on every
page are telling me there is something more important to read and rarely make
me think or code. Instead, I'm burning cycles on context switching.
Warning: In 5
billion years, the sun will run out of hydrogen and become a red giant. Make sure your
offspring will be located at a safe distance.
I see sidebars used as a copout. The
author gave up trying to work an important fact into the technology's storyline, and instead
threw the content inside a cartoon box. To be fair, it's not the author's fault. All publishers encourage this behavior. I think the publishers want books to look more like the web…
Can I Get An Ad?
Books are competing with the web, to be certain. Magazines are, too. Many tech
magazines are free because they are chocked full of ads. Perhaps book publishers will
one day start including advertisements to offset the cost of color printing - I hope not. 
|
-
In February I did a blog post called My "First Look at Orcas" Presentation. It provided a good summary of some of the cool web development features coming with Visual Studio "Orcas". If you haven't had a chance to read it, I recommend checking it out here. One of the most highly anticipated features is the support for client Javascript Intellisense within Visual Studio "Orcas" (this feature also works in the free Visual Web Developer Express edition). If you have ever been frustrated by manually typing Javascript before, you are going to be in for a pleasant treat with "Orcas". Visual Studio now provides full Javascript Intellisense completion in .aspx files, .htm files, as well as in external .js files. It delivers Intellisense for vanilla Javascript code, as well as provides rich support for the new ASP.NET AJAX client Javascript framework and Javascript code built with it. You can read more about some of the Visual Studio "Orcas" Javascript features in these two overview posts from the VS Web Tools Team here: As Wally recently blogged about, one of the cool things about the VS "Orcas" Javascript Intellisense support is that it has been designed to "just work" out of the box. This means you don't have to run any tools on your Javascript files to build-up the Intellisense hints. Nor do you have to decorate your Javascript in a specific way in order to make it work. If you have a standard Javascript function or prototype class you've built in your external Javascript file, you should get Intellisense completion against it within Visual Studio automatically. Optional Javascript Doc Comments Visual Studio also allows you to optionally add documentation comments to your code/libraries that can further help the Intellisense engine, as well as enable developers to provide documentation comments that the VS Intellisense engine can pick up and use for summary comments and type descriptors/validation checking. For example, if you added this XML summary comment to your code: Visual Studio will automatically display the summary details, as well as provide in-line help when typing the parameter values: The Format for Javascript Doc Comments Bertrand Le Roy from the ASP.NET Team recently made a great blog post that details the documentation summary comment format that is used by both ASP.NET AJAX and Visual Studio "Orcas". Among other great things it includes details on: - How to Add Summary Details for Classes, Methods and Parameters
- How to localize Documentation in Javascript
- How to indicate that one external Javascript file requires (or references) another external Javascript file and should have its Javascript Intellisense assume that the other methods and classes are "in-scope" when the external JavaScript file is used (which is super useful anytime you are using any AJAX framework library).
I highly recommend checking out his blog post here. The ASP.NET AJAX Control Toolkit also now has a built-in MSBuild task that you can add to your web projects that can automatically strip out these documentation comments (along with whitespace and other non-needed content) from your JavaScript files when compiling a project in "release" mode. This provides a really useful utility that enables you to maintain debug/descriptive versions of your Javascript at development time, and then allow you to throw a switch to generate versions optimized for efficient download at runtime. Hope this helps, Scott 
|
-
Two weeks ago I posted about the availability of a public hotfix patch for some ASP.NET 2.0 compilation issues. You can read about this patch in my post here. In the comments of that post several people asked about an issue they've encountered with Visual Studio SP1 when they use the "Publish Website" command with a web project configured to use the built-in ASP.NET Development Web Server with a "/" as the virtual path (a cool technique that I previously posted a tip/trick about). Specifically, people who have installed VS 2005 SP1 have reported encountering an "Index was outside the bounds of the array" error message during publishing: This bug was unfortunately a regression in VS 2005 SP1. The good news is that we have just posted a public hotfix for the issue that you can directly download here. Omar Khan has also posted more details about the issue and patch in the WebDevTools Blog on MSDN here (which I highly recommend subscribing to). Important: People sometimes ask me whether they should install QFE HotFixes proactively (before they ever see an issue). I always recommend against doing this - since QFE hotfixes go through targeted testing (to verify a specific issue is fixed), and don't go through a complete product end to end sign-off. As such, I'd recommend only applying one of if you are running into the specific issue it targets above. If you have any problems installing the patch or find that you still see compilation issues after you install it, you'll want to contact Microsoft product support for assistance and they'll help debug it further. Calls to Microsoft Product Support are free if they are related to a product bug (either a QFE HotFix request or a product bug you are running into). You can find details on how to contact Microsoft product support on this page (it allows you to lookup the local phone number to use by country). Hope this helps, Scott 
|
-
Your mind is racing and your fingers are struggling to keep pace. Clickety-clackety-clickety-clackety.
New code, test code, refactored code – it pours across the screen. Clickety-clackety-clickety-clackety.
There is no passing of time in this superb condition of lucidity. Clickety-
clackety-clickety-T-T-TWACK.
Opps. What was that?
Something went wrong. A finger slipped! You hit the wrong combination of keys, for sure – but which keys? Was that a menu that flashed by? The intensity of that red disk light fills you with dread. Did you trigger some hidden doomsday command that is now writing 0s to the system drive? When was the last system backup? When was your last commit? Why isn't this computer responding? What on earth is this disk drive
doing? Should you cut power now and salvage what you can? Oh, it's back <exhale>.
It's just the Visual Studio "Add New Reference" dialog.
Cancel.
For a fleeting moment, you thought all was lost.
Now, about that backup….

|
-
Over the years I have spoken at a number of user group meetings and conferences and have been teaching at the University of California - San Diego Extension since 2001. In all of these instances, my primary responsibility has been to speak, present, and teach. I have not had to worry about the plethora of other concerns, such as: advertising or marketing; procuring a venue; handling sign ups and collecting and processing payment; providing printouts; arranging for catering; ensuring that comforts like snacks, water, coffee, and soda were available to attendees; and set up and tear down. All of these responsibilities became mine when I decided to put on a one day conference/training event back in February of this year. This event was held on Saturday, April 21st, and I'm happy to report that it went off as smooth as I had hoped for in my wildest dreams.
I learned so much from this experience and wanted to share some lessons learned from my experience for those interested in arranging their own developer-related conferences, events, or user group meetings. Note that the event held this past Saturday had 48 attendees. My comments and suggestions might not apply of be applicable for significantly smaller or larger events. Also my advice is geared toward those who are putting on such an event by themselves or as part of a non-profit group and that they don't have the resources of a large company to tap into.
Marketing and Advertising I marketed this event in the following ways:
- Direct interaction. I do consulting and training work for some businesses local to San Diego, and told them of this event in person
- Via this blog
- By emailing my past UCSD Extension students
- Attending the ASP.NET SIG meeting in March here in San Diego and promoting the event
- Asking Dan Mathson and David McCarter (who help run the ASP.NET SIG and San Diego .NET Developer group, respectively) to email their email lists with a blurb announcing the event
Unfortunately, I didn't keep detailed statistics as to what source my sign ups came from, but based on the dates of the sign ups I can make educated guesses as to the marketing campaign that resulted in the sign up.
As the following chart shows, the emails coming directly from Dan and David were, by far, the largest source of attendees. The second largest source of sign ups was from emailing my past UCSD students. While Dan and David's emails provided a larger total number of sign ups, the emails to my students had a much higher sign up rate. Dan and David sent emails to nearly 1,800 local developers for a conversion rate of about 1.5%, whereas I contacted less than 100 past students for a conversion rate roughly ten times higher.
Note that no one signed up from the user group meeting promotion. My guess is because the conversion rate here is on par with the email blast (~1.5%). In short, my results show that it is more cost effective to focus on getting the word out in less personal ways to a larger group than to make a person presentation to a small group. Of course, all forms of marketing should be pursued, time permitting, but if you have to focus on one, a far reaching email blast seems to be the best route.
I did not spend any money on advertising.
Since large scale email marketing appears to be the most effective marketing tool, talk to local User Group leaders about promoting your event. Also, if you are doing an event about Microsoft technologies, get in touch with your local Microsoft Regional Director for suggestions and help on promoting your event.
Procuring a Venue Finding and reserving a venue is, obviously, an important step, and needs to be done prior to marketing the event. I had some people with event hosting experience recommend hotels as venues. They usually have onsite catering and rooms to accommodate various sizes. A more affordable option might be to find a local .NET consulting firm and see if they are interested in volunteering their site. If there is a Microsoft office in your city, that might be another option. To be honest, I didn't explore venue options in depth. UCSD Extension was able to offer me a room for the day at a very competitive rate.
One thing that is important is to scope out the room before agreeing to use it. The site may say that it can fit 50 people, but on inspection 50 people might be a tight fit. Also, make sure that the projector, amentities, and facilities are what you expect.
Handling Sign Ups and Processing Payment Events and conferences should always have a corresponding website that provides information about the event including: a high-level overview of the event; a more detailed outline; and directions. Moreover, the website should allow attendees to register via the web. I created such a website for my event (see http://fuzzylogicinc.net/BlackBelt/). The website was very straightforward, containing only four web pages:
- Home - provides a one paragraph description of the event, key information (where, when, and how much), and a paragraph about the instructor.
- Sign Up
- Outline - a detailed outline of the material to be covered
- Directions - the address of the venue, directions, and a map
I used PayPal to handle payment processing. After entering their name and email address, the user would be redirected to PayPal's website where they would be prompted to pay for their purchase (either using a credit card, a check, or from their own PayPal account). A more professional approach would be to use PayPal's SDK or some other payment gateway and handle the payment processing logic entirely on the event's website.
Printouts For my event I provided each attendee with a bound printout of the 300 or so PowerPoint slides examined throughout the course of the day. I initially contemplated doing the printouts on my own, but instead opted to use a print shop. In particular, I chose Kinkos because they were within walking distance of my home and they have a slick application for submitting your order: namely, you install a program that adds a printer to your system. You then 'print' your slides (or whatever) to this special printer, which launches a program that let's you choose the paper type, whether to use one-sided or two-sided, if you want a binding, color or black and white, how many copies, and so on. It then lets your preview your order, shows the amount due, lets you specify a pickup time, and collects payment information. Very easy to use and highly recommended.
Catering, Beverages, and Snacks Some venues provide onsite catering, but chances are you will be on the hook for catering. You will have to find a reputable caterer and also provide your attendees with snacks and beverage refreshments throughout the course of the day. For this event, I used Come On In Restaurants, a caterer recommended by the UCSD Extension staff. I had sampled their food at a previous UCSD Extension event and it was quite tasty. I was also pointed to Restaurants on the Run, which is an online directory of 'catering and delivery specialists.' A good caterer will help you craft the menu and will be sensitive to your budget.
You will also need to procure water and soda and snacks for your attendees to enjoy throughout the course of the day. We bought water and soda from Costco. In the end, we bought too much soda and too little water (which is understandable, given my predilection for carbonated beverages). Specifically, we purchased 36 cans of non-diet soda, 108 cans of diet soda, and 70 bottles of water for 48 attendees. We ended up bringing home about 70% of the soda and ran out of water by mid-afternoon. We also grossly overbought coffee from Einstein Bros., which serves 'catering coffee' in boxes that each have 8-10 servings. I bought four boxes of regular and one of decaf, and we ended up going through two boxes in total, throwing out the rest.
We didn't buy snacks, although in hindsight we should have. The caterer provided an assortment of cookies and brownies, which were decimated. Around 3:00 PM, many attendees seemed to be seeing if there were any sweets left over. While the catered desserts were completely consumed (as were the selection of chips), the sandwhiches and pasta and green salad had a bit of leftovers. We brought it all home and had the sandwhiches and salads for three meals before throwing away another couple of meals worth of food.
Setup and Teardown Hosting an event of this size requires a non-trivial amount of setup and teardown time and energy. In addition to setup and teardown, the beverages and snacks need to be attended to throughout the course of the day. And the caterer may need assistance and/or directions on where and how to setup the spread. Naturally, hosting such an event is not a one-man show, so you'll need to recruit your spouse or a friend or colleague to help out. My very helpful and wonderful wife spent her Saturday restocking the beverages, assisting the caterer, and answering any logistical questions (where are the bathrooms, are there any more cookies, and so forth). She is also an ASP.NET developer, so she could have fielded technical questions!
Final Thoughts I was pretty nervous the days leading up to this event because of my inexperience at handling all of the miscellany involved. Fortunately, everything went according to plan! There were no 'surprises' and I didn't forget anything essential. I was pleased at the turnout, the quality of the catered lunch, the attendee participation, and so on. The only disappointments I had were minor ones. For example, the thermostat wasn't very effective and the room got pretty warm, but opening a door to the outside cooled it off fairly effectively. And buying too much soda and coffee and too little water.
I had a blast putting on this event and presenting the material, and plan on hosting future one-day events similar to this one on additional topics (AJAX, ASP.NET v3.0/3.5, and so on).
|
-
Last month I started a series of posts covering some of the new VB and C# language features that are coming as part of the Visual Studio and .NET Framework "Orcas" release. Here are pointers to the first three posts in my series: Today's blog post covers another fundamental new language feature: Query Syntax. What is Query Syntax? Query syntax is a convenient declarative shorthand for expressing queries using the standard LINQ query operators. It offers a syntax that increases the readability and clarity of expressing queries in code, and can be easy to read and write correctly. Visual Studio provides complete intellisense and compile-time checking support for query syntax. Under the covers the C# and VB compilers take query syntax expressions and translate them into explicit method invocation code that utilizes the new Extension Method and Lambda Expression language features in "Orcas". Query Syntax Example: In my previous language series posts, I demonstrated how you could declare a "Person" class like below: We could then use the below code to instantiate a List<Person> collection with people values, and then use query syntax to perform a LINQ query over the collection and fetch only those people whose last name starts with the letter "G", sorted by the people's firstname (in ascending order): The query syntax expression above is semantically equivalent to the below code that uses LINQ extension methods and lambda expressions explicitly: The benefit with using the query syntax approach is that it ends up being a little easier to read and write. This is especially true as the expression gets richer and more descriptive. Query Syntax - Understanding the From and Select Clauses: Every syntactic query expression in C# begins with a "from" clause and ends with either a "select" or "group" clause. The "from" clause indicates what data you want to query. The "select" clause indicates what data you want returned, and what shape it should be in. For example, let's look again at our query against the List<Person> collection: In the above code snippet the "from p in people" clause is indicating that I want to perform a LINQ query against the "people" collection, and that I will use the parameter "p" to represent each item in the input sequence I am querying. The fact that we named the parameter "p" is irrelevant - I could just have easily named it "o", "x", "person" or any other name I wanted. In the above code snippet the "select p" clause at the end of the statement is indicating that I want to return an IEnumerable sequence of Person objects as the result of the query. This is because the "people" collection contains objects of type "Person", and the p parameter represents Person objects within the input sequence. The datatype result of this query syntax expression is consequently of type IEnumerable<Person>. If instead of returning Person objects, I wanted to return just the firstnames of the people in the collection, I could re-write my query like so: Note above how I am no longer saying "select p", but am instead saying "select p.FirstName". This indicates that I don't want to return back a sequence of Person objects - but rather I want to return a sequence of strings - populated from each Person object's FirstName property (which is a string). The datatype result of this query syntax expression is consequently of type IEnumerable<string>. Sample Query Syntax Against a Database The beauty of LINQ is that I can use the exact same query syntax against any type of data. For example, I could use the new LINQ to SQL object relational mapper (ORM) support provided in "Orcas" to model the SQL "Northwind" database with classes like below (please watch my video here to learn how to-do this): Once I've defined the class model above (and its mapping to/from the database), I can then write a query syntax expression to fetch all products whose unitprice is greater than $99: In the above code snippet I am indicating that I want to perform a LINQ query against the "Products" table on the NorthwindDataContext class created by the ORM designer in Visual Studio "Orcas". The "select p" indicates that I want to return a sequence of Product objects that match my query. The datatype result of this query syntax expression is consequently of type IEnumerable<Product>. Just like with the previous List<Person> collection query syntax example, the C# compiler will translate our declarative query syntax into explicit extension method invocations (using Lambda expressions as the arguments). In the case of the above LINQ to SQL example, these Lambda expressions will then be converted into SQL commands and evaluated within SQL server (so that only those Product rows that match the query are returned to our application). Details on the mechanism that enables this Lambda->SQL conversion can be found in my Lambda Expressions blog post under the "Lambda Expression Trees" section. Query Syntax - Understanding the Where and OrderBy Clauses: Between the opening "from" clause and closing "select" clause of a query syntax expression you can use the most common LINQ query operators to filter and transform the data you are querying. Two of the most common clauses you'll end up using are "where" and "orderby". These handle the filtering and ordering of results. For example, to return a list of alphabetically descending category names from the Northwind database - filtered to only include those categories where there are more than 5 products associated with the category - we could write the below query syntax that uses LINQ to SQL to query our database: In the above expression we are adding a "where c.Products.Count > 5" clause to indicate that we only want to return category names where there are more than 5 products in the category. This takes advantage of the LINQ to SQL ORM mapping association between products and categories in our database. In the above expression I also added a "orderby c.CategoryName descending" clause to indicate that I want to sort the results in descending order. LINQ to SQL will then generate the below SQL when querying the database using this expression: SELECT [t0].[CategoryName] FROM [dbo].[Categories] AS [t0] WHERE (( SELECT COUNT(*) FROM [dbo].[Products] AS [t1] WHERE [t1].[CategoryID] = [t0].[CategoryID] )) > 5 ORDER BY [t0].[CategoryName] DESC Notice how LINQ to SQL is smart and only returns back the single column we need (the categoryname). It also does all of the filtering and ordering in the database layer - which makes it very efficient. Query Syntax - Transforming Data with Projections One of the points I made earlier was that the "select" clause indicates what data you want returned, and what shape it should be in. For example, if you have a "select p" clause like below - where p is of type Person - then it will return a sequence of Person objects: One of the really powerful capabilities provided by LINQ and query syntax is the ability for you to define new classes that are separate from the data being queried, and to then use them to control the shape and structure of the data being returned by the query. For example, assume that we define a new "AlternatePerson" class that has a single "FullName" property instead of the separate "FirstName" and "LastName" properties that our origional "Person" class had: I could then use the below LINQ query syntax to query my origional List<Person> collection, and transform the results to be a sequence of AlternatePerson objects using the query syntax below: Notice how we can use the new Object Initializer syntax I talked about in the first post in my language series to create a new AlternatePerson instance and set its properties within the "select" clause of our expression above. Note also how I am assigning the "FullName" property by concatenating the FirstName and LastName properties of our origional Person class. Using Query Syntax Projections with a Database This projection feature ends up being incredibly useful when working with data pulled from a remote data provider like a database, since it provides us with an elegant way to indicate which columns of data our ORM should actually fetch from a database. For example, assume I use the LINQ to SQL ORM provider to model the "Northwind" database with classes like below: By writing the LINQ query below, I am telling LINQ to SQL that I want a sequence of "Product" objects returned: All of the columns necessary to populate the Product class would be returned from the database as part of the above query, and the raw SQL executed by the LINQ to SQL ORM would look like below: SELECT [t0].[ProductID], [t0].[ProductName], [t0].[SupplierID], [t0].[CategoryID], [t0].[QuantityPerUnit], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitsOnOrder], [t0].[ReorderLevel], [t0].[Discontinued] FROM [dbo].[Products] AS [t0] WHERE [t0].[UnitPrice] > 99 If I didn't need/want all of these columns for some scenarios, I could alternatively define a new "MyProduct" class like below that has a subset of the properties that the Product class has, as well as one additional property - "TotalRevenue" -- that the Product class doesn't have (note: for people not familiar with C#, the Decimal? syntax indicates that UnitPrice property is a nullable value): I can then use the projection capability of query syntax to shape the data I want returned from the database using a query like below: This is indicating that instead of returning a sequence of "Product" objects, I instead want "MyProduct" objects, and that I only need 3 properties of them filled. LINQ to SQL is then smart enough to adjust the raw SQL to execute to only return those three needed product columns from the database: SELECT [t0].[ProductID], [t0].[ProductName], [t0].[UnitPrice] FROM [dbo].[Products] AS [t0] WHERE [t0].[UnitPrice] > 99 Just to show-off, I could also populate the 4th property of the MyProduct class - which is the "TotalRevenue" property. I want this value to be the aggregate amount of revenue that our products have sold for. This value isn't stored anywhere as a pre-computed column within the Northwind database. Instead you need to perform a join between the "Products" table and the "Order Details" table and sum up all of the Order Detail rows associated with a given product. What is cool is that I can use the LINQ "Sum" extension method on the Product class's OrderDetails association and write a multiplication Lambda expression as part of my query syntax projection to compute this value: LINQ to SQL is then smart enough to use the below SQL to perform the calculation in the SQL database: SELECT [t0].[ProductID], [t0].[ProductName], [t0].[UnitPrice], ( SELECT SUM([t2].[value]) FROM ( SELECT [t1].[UnitPrice] * (CONVERT(Decimal(29,4),[t1].[Quantity])) AS [value], [t1].[ProductID] FROM [dbo].[Order Details] AS [t1] ) AS [t2] WHERE [t2].[ProductID] = [t0].[ProductID] ) AS [value] FROM [dbo].[Products] AS [t0] WHERE [t0].[UnitPrice] > 99 Query Syntax - Understanding Deferred Execution, and using ToList() and ToArray() By default the result of a query syntax expression is a variable of type IEnumerable<T>. In my samples above you'll notice that all of the query syntax assignments are to IEnumerable<Product>, IEnumerable<string>, IEnumerable<Person>, IEnumerable<AlternatePerson>, and IEnumerable<MyProduct> variables. One of the nice characteristics of IEnumerable<T> interfaces is that objects that implement them can defer the actual execution of the queries until a developer first attempts to iterate over the values (this is accomplished using the "yield" construct that was first introduced with C# 2.0 in VS 2005). LINQ and query syntax expressions take advantage of this feature, and defer the actual execution of queries until the first time you loop over the results. If you never iterate over the IEnumerable<T> result, then the query is never executed. For example, consider the below LINQ to SQL example: The database will be hit and the values to populate our Category objects will be retrieved not when the query syntax expression is declared - but rather when we first try and loop over the results (indicated above with the red arrow). This deferred execution behavior ends up being really useful because it enables some powerful composition scenarios where we can "chain" multiple LINQ queries and expressions together. For example, we could feed the result of one expression into another - and by deferring the execution allow an ORM like LINQ to SQL to optimize the raw SQL based on the entire expression tree. I'll show examples of how to use this in a later blog post. How to evaluate the query syntax expression immediately If you don't want to defer the execution of queries, and instead want to execute them immediately, you can use the built-in ToList() and ToArray() operators to return either a List<T> or an array containing the results. For example, to return a generic-based List<T> collection: and to return an array: In both cases above the database will be hit and the Category objects populated immediately. Summary Query syntax provides a very convenient declarative shorthand for expressing queries using the standard LINQ query operators. It offers a syntax that is very readable, and which works against any type of data (any in-memory collection, array, XML content, or against remote data providers like databases, web-services, etc). Once you become familiar with the syntax, you can immediately apply the knowledge everywhere. In the not too distant future I'll finish the last segment of this language series - which will cover the new "anonymous types" feature. I'll then move on to cover some super practical examples of using all of these language features in the real world (especially using LINQ against databases and XML files). Hope this helps, Scott 
|
-
I've got a small app in production that's been running without a glitch until the other day. It turned out to be a case where the server didn't have enough disk space and nothing more. That should have been the end of it, but I also decided to add myself to the error emails. The next day someone reported not getting their regular email, and I couldn't figure it out. Why would something that had been working perfectly and not been changed just fail randomly? I looked everywhere in the code and could find no reason, and nothing was logged about this. That said, there was an exception that was logged, but it was about my email, not the other. My email address was on another domain, and that wasn't allowed, but I just shrugged it off. Then it happened again today and all the sudden I realized what should have been very obvious. That small configuration change I had made to send myself error emails was the actual problem! My code first sent error emails before sending routine emails, all of which was one try/catch So when I added myself to the error emails, I introduced an exception that skipped the others. This was now easy to fix -- just make each email send be in its own try/catch, instead of one. And the lesson learned: any change, even a tiny configuration change, can introduce problems. Even bigger lesson: when problem occurs after small change, then your change is likely cause. Those should really have been obvious in retrospect, but I managed to convince myself otherwise. 
|
-
A few months ago I posted about the new SQL Server Database Publishing Hosting Toolkit built and published by the SQL Server team. You can read about what it offers and how to use it in these previous two blog posts of mine: The SQL Server Hosting Toolkit is a free download that makes it super easy to create a .SQL script file capable of re-creating your database (including the schema, sprocs, and actual data content). When it is installed you can simply right-click on a database inside Visual Studio or Visual Web Developer and walkthrough a wizard to script it out: You can then FTP this script up to your remote server environment and execute it (my second post above shows a technique you can use even if you don't have admin access on the machine). Alternatively, you can use the built-in web-service support provided by the database publishing wizard to directly export and copy the database over the Internet to your remote hosting provider. SQL Server Database Publishing Toolkit V1.1 Update Earlier this month the SQL team released a V1.1 update to the toolkit. You can learn more about it and download it here. The V1.1 update includes the following improvements: • It adds the ability to select individual objects/tables for publishing in the wizard (and not have to create/recreate everything in the database each time) • It improves performance up to 30-40% when scripting and publishing • It delivers usability improvements when publishing over the Internet to a hosting provider • It fixes several bugs submitted on the CodePlex forums I'd definitely recommend checking it out. If you are hosting your applications remotely today this free tool can be a super useful addition to your toolbox. Thanks, Scott 
|
-
When adding client-side script to a web page, the JavaScript can be embedded directly within the page's HTML or provided via an external reference similar to include files in programming languages. When using JavaScript include files, the browser will cache the file so that it doesn't need to be downloaded on subsequent postbacks and page visits. By embedding the script directly wthin the page's markup, the script must be downloaded on each page visit (with the rest of the markup), which is wasteful if the script content is static. Therefore, JavaScript include files lessen the amount of data the client must download, improving the end user's experience. So JavaScript includes are a Good Thing. In fact, when using certain ASP.NET Web controls (like validation controls, the Menu, and so on), script includes are used to inject the necessary client-side plumbing).
JavaScript includes have a simple enough syntax:
<script src="pathToJavaScriptFile"></script>
Of course, XML rules allow for elements with no inner content to use “/>” as a shortcut rather than needing the closing tag. In a recent project I assumed this would work for JavaScript includes and added a number of includes using syntax like:
<script src="pathToJavaScriptFile" />
Well, guess what? That doesn't work, at least not in Internet Explorer. IE ignores the JavaScript include altogether, not sucking in any of the JavaScript content from pathToJavaScriptFile. If your JavaScript file contains only infrequently-used functions, you of course don't find this out until you perform some action that calls one of these functions in pathToJavaScriptFile and you end up getting a script error. And then, of course, you spend the next hour pouring over the JavaScript code and the page's rendered markup to find what's wrong, not realizing that the browser hadn't sucked down the JavaScript include file because you used “/>” instead of “</script>”.
What's particularly odd is that if you use a tool like Fiddler to inspect the HTTP traffic, the browser still makes a request to pathToJavaScriptFile! It just doesn't 'execute' the script or 'register' the functions if you end the <script> reference with “/>“ instead of “</script>“. Ditto if you fail to end the <SCRIPT> element (that is, if you have <script src="pathToJavaScriptFile">).
Long story short - make sure you don't make the same mistake I did. Save yourself an hour of frustration by adding the verbose “</script>” when externally referencing a JavaScript file instead of trying to save six bytes by omitting it.
|
-
MSDN says the List.ForEach method will "perform the specified action on each element of the List".
The following program does print out a haiku to the console, but does not make the haiku all lowercase.
using System;
using System.Collections.Generic;
class WWWTC
{
static void Main()
{
List<string> haiku = new List<string>();
haiku.Add("All software changes");
haiku.Add("Upon further reflection -");
haiku.Add("A reference to String");
// make it lowercase
haiku.ForEach(
delegate(string s)
{
s = s.ToLower();
}
);
// ... and now print it out
haiku.ForEach(
delegate(string s)
{
Console.WriteLine(s);
}
);
}
}
What's wrong? 
|
-
A ton of great articles and tutorials on working with data in ASP.NET 2.0 applications has been published recently. This post highlights a few of them (including tools like SubSonic and NHibernate): Working with Data in ASP.NET 2.0 Tutorial Series Scott Mitchell recently finished writing his multi-part Working with Data in ASP.NET 2.0 tutorial series for the www.asp.net site. This tutorial series contains more than 75 data tutorials (and over 750 pages of content!). There are VB and C# versions available for all of the tutorials, and the articles can optionally be downloaded in PDF format. If you haven't read the tutorials yet, I'd highly checking them out here. Below is the table of contents and links to the articles already published: Scott still has 18 more tutorials in the series that will be published soon covering: - Caching (4 tutorials)
- Data and the Site Map Provider (1 tutorial)
- Working with Batched Data (including transactions; 4 tutorials)
- Advanced Data Access Layer Scenarios (9 tutorials).
You can subscribe to this RSS feed to learn about updates when these tutorials are published. Using ASP.NET 2.0's DataSource Controls In addition to publishing the articles above on www.asp.net, Scott Mitchell is also writing some great data articles on using the ASP.NET 2.0 DataSource controls for the excellent www.4GuysFromRolla.com ASP.NET site. If you don't visit www.4GuysFromRolla.com, I highly recommend checking it out (it has tons of great, all free, content). You can also subscribe to an RSS feed of the published 4GuysFromRolla RSS articles here (if you are an ASP.NET developer you should absolutely do this). Here is a pointer to the current articles in the most recent 4GuysFromRolla ASP.NET 2.0 DataSource Control Series: SubSonic 2.0 Beta 3 SubSonic 2.0 Beta 3 is now available for download. SubSonic is a great (totally free) tool that helps you quickly build data driven web-sites. It includes a DAL builder that enables you to rapidly create strongly typed collections and an object model for your data (it builds this at compile-time based on the schema of your website), as well as rich scaffolding support for automatically creating UI against this data. Jon Galloway has a quick write-up of some of the new SubSonic 2.0 features that you can read here. If you are attending the MIX conference in two weeks, make sure to say hi to Rob Conery, who is the chief architect of SubSonic. He will also be on a great Open Source Panel at the MIX conference, together with Miguel de Icaza (of Mono) and others. NHibernate Best Practices with ASP.NET, 1.2 Ed. Billy McCafferty updated his popular "NHibernate Best Practices with ASP.NET" article earlier this month. You can read the latest version here. This article covers some of the core things to think about when building an enterprise data layer using this popular (totally free) ORM implementation for .NET. Also keep an eye out for this upcoming NHibernate in Action book scheduled to be released in July. Hope this helps, Scott 
|
-
Joseph Raatz emailed me about posts I wrote last year covering ASP.NET event validation (see ASP.NET Event Validation
and "Invalid Callback Or Postback Argument" Part
I and Part II). In the posts I describe one
scenario where an event validation exception can appear, and describe how to prevent the exception. In the scenario, client
side script dynamically adds values to a list (select) control. When the user POSTs the form to the server, ASP.NET sees a
new value and concludes something is wrong. The list comes back to the server with a value that wasn't present when the
list left the server. ASP.NET tracks the legal values by serializing them into a hidden input control with an ID of
__EVENTVALIDATION. This event validation feature helps to prevent all sorts of form spoofing attacks.
Joe's scenario was odd, not only because the invalid postback argument exception appeared sporadically, but because
the source of the exception was a TextBox control!
ArgumentException: Invalid postback or callback argument. ...
System.Web.UI.ClientScriptManager.ValidateEvent(..) ...
System.Web.UI.Control.ValidateEvent(..) ...
System.Web.UI.WebControls.TextBox.LoadPostData(..) ...
What could ASP.NET possibly validate about a TextBox? A server can expect specific values from a DropDownList, but
a plain TextBox allows free form text entry by the user. The answer (via Reflector), is that the TextBox control only
validates that its UniqueID is present in the legal arguments described by the __EVENTVALIDATION data. Even after knowing
this information, it's hard to see what could go possibly wrong with a TextBox.
Joe's theory, which I believe to be correct, is that the user might create a postback before their browser
even receives the __EVENTVALIDATION form input. This could happen, for example, over a poor connection. The resulting POST
won't contain the __EVENTVALIDATION input, and thus ASP.NET cannot validate the postback arguments. The klaxons wail. Glass
breaks. The runtime throws an exception.
One way to validate this theory is to simulate network congestion with the following control. We flush out the
output stream, sleep, and then continue rendering.
using System; using System.Web.UI; using
System.Threading;
namespace OTC
{ public
class
FlushAndSleep : Control { protected
override
void Render(HtmlTextWriter writer) { writer.Write
("Begin Render<br>");
base.Render
(writer);
Page.Response.Flush();
Thread.Sleep(2000); writer.Write("End Render<br>"); } } }
Stick the control into the following page:
<%@
Page
Language="C#" %> <%@
Register
TagPrefix="otc"
Assembly="App_Code"
Namespace="OTC" %>
<form
id="form1"
runat="server"> <div> <asp:textbox
runat="server"
id="TextBox1"
/> <asp:button
runat="server"
id="Button1"
text="Submit"
/> <br
/> <otc:FlushAndSleep
runat="server"
ID="FlushAndSleep"
/> </div> </form>
Run the page and click the button as soon as it appears in the browser. Voila! Instant "invalid callback or
postback argument" exception! If you ever see the exception occur sporadically, this might be the reason. 
|
-
My Toolbox column in the May 2007 issue of MSDN Magazine is now avaiable online. The May issue examines three products:
- NDepend - a program for graphically exploring the interdependencies among methods, classes, and assemblies in a .NET application.
- ApexSQL Edit - a rich SQL editor with IntelliSense, source control, and other interesting features. Like SQL Query Analyzer on steriods!
- Cropper - a free screen capture utility; written in C# with the source code available.
This month's issue reviewed How to Code .NET, by Christian Gross. Here is an excerpt from the review:
Most successful computer trade books either focus on a very specific subset of a technology or provide a broad overview of the entire technology. How to Code .NET, by Christian Gross (Apress, 2006), doesn’t fall into either of these categories. While its title implies that the book is a weighty tome on creating .NET applications, its mere 232 pages indicate otherwise. It neither focuses on a specific subset of .NET nor does it provide a sweeping overview. Instead, it provides 30-50 pages each on four disparate topics: Test Driven Development (TDD), low-level .NET runtime and framework information, text-processing tips, and C# coding tricks.
...
At 232 pages, How to Code .NET does not cover any topic in great detail and therefore is not intended for the reader who wants to explore these topics in great depth. But the book provides a well-written, informative look at a smattering of topics. Most intermediate .NET developers would benefit from reading How to Code .NET as it provides a number of useful tips and serves as a good starting point for exploring some of the more advanced .NET concepts.
As always, if you have any suggestions for products or books to review for the Toolbox column, please send them into toolsmm@microsoft.com.
|
-
I woke up this morning, sat down to the computer, and pulled up the Yahoo home page. There it was, the headline I had known would be coming someday. It wasn't unexpected, he was 84 years old and his health had been gradually deteriorating. My favorite author since my junior year in high school had passed away. I first came across Vonnegut when my English teacher had us read Slaughterhouse-Five, which is still one of my favorite books today. Since that time I have read just about all of Vonnegut's books, I think there are only a couple essay collections and a play that I haven't read. Cat's Cradle, Breakfast of Champions, Fates Worse than Death, God Bless You, Mr. Rosewater, and Mother Night are some of my other favorites. I have always connected with his writing and ideas more than any other author. Vonnegut introduced me to the idea of morals without religion. I had never heard of Humanism before reading Vonnegut, but now it is the easiest answer when someone asks what I believe in. I am sad that he is gone. And because it has to be said. Kurt is up in Heaven now. -James 
|
-
Over the last year we've found and fixed a few ASP.NET 2.0 compilation bugs that people have reported running into. The root cause of these bugs is varied - but the root cause usually is related to having projects structured with particular cross page circular dependencies, and they are often triggered when massive file-changes occurs on the system (for example: an anti-virus program updates all of the timestamps on files at once). Example Error Messages The below error messages are examples of the types of runtime exceptions you might see if you run into one of these compilation issues: Unable to cast object of type 'ASP.masterpage_master' to type 'ASP.masterpage_master'. Or: Could not load file or assembly 'App_Web_e9dbmaj, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. Or: Compiler Error Message: CS0006: Metadata file 'C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\cms.web\44e73607\b028acb3\App_global.asax.fakktchx.dll' could not be found Or: System.InvalidOperationException: The resource class for this page was not found. Please check if the resource file exists and try again Workaround for these issues If you have an application that starts throwing one of these errors, you can usually apply an immediate workaround that fixes it by opening your application's web.config file and setting the batch="false" attribute on the <compilation> section: <configuration>
<system.web> <compilation debug="false" batch="false"></compilation> </system.web>
</configuration> This tells ASP.NET to dynamically compile individual .aspx/.ascx files into separate assemblies. This avoids the circular reference issue that triggers the exception. You can also temporarily fix it by deleting the files within the "Temporary ASP.NET Files" Cache using the below steps: - Click the Windows Start button, click Run, type iisreset /stop, and then click OK.
- Open the DriveLetter: WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files directory.
- Delete all files and all folders in the directory that you located in step 2.
- Click Start, click Run, type iisreset /start, and then click OK.
More details on these workarounds can be found in Microsoft KB #934839. QFE HotFix Patch for these issues now available for download As an alternative to applying the above configuration workaround, you can also now download and apply a Microsoft QFE HotFix patch that fixes the reported compilation issues we've seen. The direct download link to this compilation QFE HotFix patch is here. You can find other commonly requested Visual Studio and .NET Framework QFE HotFixes on this page here. Important: People sometimes ask me whether they should install QFE HotFixes proactively (before they ever seen an issue). I always recommend against doing this - since QFE hotfixes go through targeted testing (to verify a specific issue is fixed), and don't go through a complete product end to end sign-off. As such, I'd recommend only applying one of if you are running into the specific issue it targets above. Contacting Microsoft Product Support If you have any problems installing the patch or find that you still see compilation issues after you install it, you'll want to contact Microsoft product support for assistance and they'll help debug it further. Calls to Microsoft Product Support are free if they are related to a product bug (either a QFE HotFix request or a product bug you are running into). You can find details on how to contact Microsoft product support on this page (it allows you to lookup the local phone number to use by country). Most versions of Visual Studio also come with free product support tickets (for example: VS Pro with MSDN Premium comes with 4 support tickets per subscription). You can use these support tickets for getting help using .NET or Visual Studio (for example: to get help chasing down a bug or performance problem in your own code, or to learn how to use a particular feature in the framework or IDE). There are some really, really phenomenal engineers in Microsoft product support who are great to work with if you have problems. Here are some fantastic blogs that I highly recommend subscribing to from a few of them in the .NET Framework / Visual Studio space: If you ever run into a problem you can't figure out, or have an issue with a production application that you want immediate help on, give Microsoft product support a call and you'll have someone like the folks above attach a debugger and help you figure out what is going on. Thanks, Scott 
|
-
DTS has always worried me.
Unfortunately, I have 331 reasons to worry:
PS > gci -r -i *.dts | group Extension
Count Name
----- ---- . . .
331 .dts
Five years ago, ADO.NET didn't have a bulkload API, and DTS seemed like the best tool for moving and transforming
millions of records. This was despite the fact that the binary DTS packages check into source control as opaque blobs, and
the cumbersome UI makes even simple changes difficult. We thought we'd need to write and distribute ~50 packages total, but
feature growth and support for additional 3rd party databases has ballooned the original estimate.
The application using these packages has to support SQL 2000 for the foreseeable future. Not every customer has
budgeted for a new SQL 2005 license, unfortunately. The good news is that SQL 2005 will run the DTS packages, even though
it cannot migrate but a handful of them to the new SSIS platform.
Another piece of good news is that you can edit DTS packages in the SQL 2005 Management Studio after downloading some designer components. The bad news is that the designer is still suboptimal. For instance, the Home, End,
Backspace, PageUp, and PageDown keys will quit working in the designer. The good news is that this problem is fixed in SP2. The bad news is
that the fix changed the designer into a modal dialog. Modal dialogs should be banned from all software in the universe.
If you haven't started your DTS migration yet, here are a few resources I've collected.
DTS Services for SQL 2005 FAQ
SQL Server 2005 Integration Services
Backward Compatibility
Known Package Migration Issues
A tool to improve DTS to SSIS
migration
Any other good ones out there? 
|
-
I was doing some research for my little smart-client side project and came across a couple of nice articles on form-design and label placement: Web Application Form Design by Luke Wroblewski - This article covers the best ways to arrange labels and submission buttons. Web Application Form Design Expanded by Luke Wroblewski - Another great article from Luke W. expanding on the same topics. Label Placement in Forms by Matteo Penzo - Matteo takes Luke's advice but applies eyetracking to evaluate how usable it is. After going through these I decided on non-bold labels above the input fields, and the users are happy. -James 
|
-
My publisher pinged recently to show me Jesse's review of my WF book on
Amazon.com:
"Every once in a while an author is able to take a
subject that others struggle with but fail to make understandable, and succeeds in making so crystal clear that it seems
obvious. Allen brilliantly illuminates Windows Workflow, and his book is required reading."
I've never met Jesse, but I've enjoyed his
writing over the years. Coming from an expert writer like Jesse, this comment is high praise.

|
-
Here's a nice library function useful when loading enum-typed properties from your database: public static T ToEnum<T>(int typeValue) { return (T)Enum.ToObject(typeof(T), typeValue); } 
|
-
-
-
"What ASP.NET Developers Should Know About JavaScript" is the title of a presentation I'll be giving at VSLive! next month.
I don't plan for this to be a talk that features ASP.NET AJAX, or JavaScript data types. Instead, I want to focus on
two key concepts I had to discover after I decided that I couldn't ignore client-scripting any longer:
- Every JavaScript function is an object.
- Every JavaScript function has an execution context.
I think these concepts are keys to understanding modern JavaScript libraries. I hope that driving home these
two concepts will let a developer understand what the following code is doing, and why it works. The example is contrived,
but if you can understand the following code you can follow many of the JavaScript patterns in use today.
<script src="msajax/MicrosoftAjax.debug.js"></script>
<input type="button" value="Print!" id="button" />
<script>
Type.registerNamespace("Geometry");
Geometry.Point = function(x,y)
{
this.x = x;
this.y = y;
$addHandler($get("button"), 'click',
Function.createDelegate(this, this.print));
}
Geometry.Point.prototype =
{
print: function()
{
alert(this.x + ' ' + this.y);
}
}
Geometry.Point.registerClass('Geometry.Point');
var p = new Geometry.Point(2,5);
</script>
There are lots of ancillary topics in the above code: object notation, prototypical inheritance, and the evils of
the global object, just to name a few. However, given just 60 minutes I think that coming to grips with #1 and #2 lays a
solid foundation for moving forward in the AJAX jungle. 
|
-
Last month I started a series of posts covering some of the new VB and C# language features that are coming as part of the Visual Studio and .NET Framework "Orcas" release. Here are the first two posts in the series: Today's blog post covers another fundamental new language feature: Lambda Expressions. What are Lambda Expressions? C# 2.0 (which shipped with VS 2005) introduced the concept of anonymous methods, which allow code blocks to be written "in-line" where delegate values are expected. Lambda Expressions provide a more concise, functional syntax for writing anonymous methods. They end up being super useful when writing LINQ query expressions - since they provide a very compact and type-safe way to write functions that can be passed as arguments for subsequent evaluation. Lambda Expression Example: In my previous Extension Methods blog post, I demonstrated how you could declare a simple "Person" class like below: I then showed how you could instantiate a List<Person> collection with values, and then use the new "Where" and "Average" extension methods provided by LINQ to return a subset of the people in the collection, as well as compute the average age of people within the collection: The p => expressions highlighted above in red are Lambda expressions. In the sample above I'm using the first lambda to specify the filter to use when retrieving people, and the second lambda to specify the value from the Person object to use when computing the average. Lambda Expressions Explained The easiest way to conceptualize Lambda expressions is to think of them as ways to write concise inline methods. For example, the sample I wrote above could have been written instead using C# 2.0 anonymous methods like so: Both anonymous methods above take a Person type as a parameter. The first anonymous method returns a boolean (indicating whether the Person's lastname is Guthrie). The second anonymous method returns an integer (returning the person's age). The lambda expressions we used earlier work the same - both expressions take a Person type as a parameter. The first lambda returns a boolean, the second lambda returns an integer. In C# a lambda expression is syntactically written as a parameter list, followed by a => token, and then followed by the expression or statement block to execute when the expression is invoked: params => expression So when we wrote the lambda expression: p => p.LastName == "Guthrie" we were indicating that the Lambda we were defining took a parameter "p", and that the expression of code to run returns whether the p.LastName value equals "Guthrie". The fact that we named the parameter "p" is irrelevant - I could just have easily named it "o", "x", "foo" or any other name I wanted. Unlike anonymous methods, which require parameter type declarations to be explicitly stated, Lambda expressions permit parameter types to be omitted and instead allow them to be inferred based on the usage. For example, when I wrote the lambda expression p=>p.LastName == "Guthrie", the compiler inferred that the p parameter was of type Person because the "Where" extension method was working on a generic List<Person> collection. Lambda parameter types can be inferred at both compile-time and by the Visual Studio's intellisense engine (meaning you get full intellisense and compile-time checking when writing lambdas). For example, note when I type "p." below how Visual Studio "Orcas" provides intellisense completion because it knows "p" is of type "Person": Note: if you want to explicitly declare the type of a parameter to a Lambda expression, you can do so by declaring the parameter type before the parameter name in the Lambda params list like so: Advanced: Lambda Expression Trees for Framework Developers One of the things that make Lambda expressions particularly powerful from a framework developer's perspective is that they can be compiled as either a code delegate (in the form of an IL based method) or as an expression tree object which can be used at runtime to analyze, transform or optimize the expression. This ability to compile a Lambda expression to an expression tree object is an extremely powerful mechanism that enables a host of scenarios - including the ability to build high performance object mappers that support rich querying of data (whether from a relational database, an active directory, a web-service, etc) using a consistent query language that provides compile-time syntax checking and VS intellisense. Lambda Expressions to Code Delegates The "Where" extension method above is an example of compiling a Lambda expression to a code delegate (meaning it compiles down to IL that is callable in the form of a delegate). The "Where()" extension method to support filtering any IEnumerable collection like above could be implemented using the extension method code below: The Where() extension method above is passed a filter parameter of type Func<T, bool>, which is a delegate that takes a method with a single parameter of type "T" and returns a boolean indicating whether a condition is met. When we pass a Lambda expression as an argument to this Where() extension method, the C# compiler will compile our Lambda expressions to be an IL method delegate (where the <T> type will be a Person) that our Where() method can then call to evaluate whether a given condition is met. Lambda Expressions to Expression Trees Compiling lambdas expressions to code delegates works great when we want to evaluate them against in-memory data like with our List collection above. But consider cases where you want to query data from a database (the code below was written using the built-in LINQ to SQL object relational mapper in "Orcas"): Here I am retrieving a sequence of strongly typed "Product" objects from a database, and I am expressing a filter to use via a Lambda expression to a Where() extension method. What I absolutely do not want to have happen is to retrieve all of the product rows from the database, surface them as objects within a local collection, and then run the same in-memory Where() extension method above to perform the filter. This would be hugely inefficient and not scale to large databases. Instead, I'd like the LINQ to SQL ORM to translate my Lambda filter above into a SQL expression, and perform the filter query in the remote SQL database. That way I'd only return those rows that match the query (and have a very efficient database lookup). Framework developers can achieve this by declaring their Lambda expression arguments to be of type Expression<T> instead of Func<T>. This will cause a Lambda expression argument to be compiled as an expression tree that we can then piece apart and analyze at runtime: Note above how I took the same p=>p.LastName == "Guthrie" Lambda expression that we used earlier, but this time assigned it to an Expression<Func<Person, bool>> variable instead of a Func<Person,bool> datatype. Rather then generate IL, the compiler will instead assign an expression tree object that I can then use as a framework developer to analyze the Lambda expression and evaluate it however I want (for example, I could pick out the types, names and values declared in the expression). In the case of LINQ to SQL, it can take this Lambda filter statement and translate it into standard relational SQL to execute against a database (logically a "SELECT * from Products where UnitPrice < 55"). IQueryable<T> Interface To help framework developers build query-enabled data providers, LINQ ships with the IQueryable<T> interface. This implements the standard LINQ extension method query operators, and provides a more convenient way to implement the processing of a complex tree of expressions (for example: something like the below scenario where I'm using three different extension methods and two lambdas to retrieve 10 products from a database): For some great blog post series that cover how to build custom LINQ enabled data providers using IQueryable<T>, please check out these great blog posts from others below: Summary Hopefully the above post provides a basic understanding of how to think about and use Lambda expressions. When combined with the built-in standard query extension methods provided in the System.Linq namespace in "Orcas", they provide a really rich way to query and interact with any type of data while preserving full compile-time checking and intellisense. By taking advantage of the Expression Tree support provided with Lambdas, and the IQueryable<T> interface, framework developers building data providers can ensure that the clean code that developers write executes fast and efficiently against data sources (whether a database, XML file, in-memory object, web-service, LDAP system, etc). Over the next few weeks I'll complete this language series covering the new core language concepts from a theoretical level, and then move on to cover some super practical examples of using them in action (especially using LINQ against databases and XML files). Hope this helps, Scott 
|
-
Back in November I decided to turn over the presidency of the group to Mike Wood. I started the group two years before because the old group in Cincinnati was un-focused and I wanted to start a group more like the great groups in Columbus and Cleveland. I think it went reasonably well. Our attendance gradually grew and we ended up stabilizing around 35-40 people a night. I think with our move to the new facility in Mason the attendance will grow even more. Over time I became distracted with work and other side projects and spent less and less time on the group. Mike started to take an interest and did a great job setting up the new web site and working on ways to improve membership so it made sense to pass the reigns to him. I am staying on the board of directors for the group and we have just finished setting up the group as a non-profit corporation. The goal of doing this was to allow sponsors to cover the costs of the free pizza at every meeting, and to also perhaps pay for some extra give-aways or to bring in speakers. So far I think Mike is doing a great job (we had over 60 people show up recently!) and I look forward to going to the meeting as an attendee. -James 
|
-
This book was universally praised when initially released and every trip to the bookstore I would spot it on the shelf and consider taking it home. It wasn't until I saw the new copy of the book with the movie cover on it that I decided I had to pick it up since there were still a few copies of the book with the original cover left. I detest the movie cover edition of books. It is sacrilege to change the original work based on an adaptation to the screen that usually falls short of the original. I think the only book I own with a movie cover is Fight Club, and that is because I absolutely had to read the book after seeing the movie and it was the only version available. Everything is Illuminated sat on my shelf for a couple months after I brought it home until I again selected it from the stack of books to read next. Everything Is Illuminated is an excellent book that makes use of some interesting writing techniques to tell a unique and incredible story. The book comes dangerously close to being too clever, but in the end the story and writing won me over. The basic premise of the story is that the main character, who shares the same name as the author, is going to the Ukraine to try and find a woman who saved his Jewish grandfather from the ***. Now the clever part is how the story is told. The book consists of a number of different stories being told at the same time in alternating "chapters". The first story is from a book being written by the fictional main character about his ancestors and the shetl they live in. This story has a supernatural quality and in some places includes what must be intentional historical ignorance (but is often pointed out by Amazon reviewers who just don't get that these are chapters from a fictional book, a book within a book). The second story is written by Alex, a young tour guide who was hired to help Jonathan to find what he was looking for in the Ukraine. It details their trip through the Ukraine and everything they encounter. Alex's grandfather is their driver, and their dog Sammy Davis Jr. Jr. is along for the ride as well. The third story consists of letters from Alex being written at the present and sent to Jonathan. These letters are often mentioned for Alex's humorous use of the English language but more importantly are a method of foreshadowing the events in the second story (and in some ways the first story). Through all three of these narratives a wonderful, sometimes hysterically funny, sometimes heartbreakingly sad, story is woven together. -James 
|
-
Simple is the new complex. The goal of software used to be to create the most powerful and complex piece of software possible. Look at Visual Studio and Eclipse. Now compare it to TextMate, the most talked about IDE (if you can even call it an IDE) in recent months. Compare the Yahoo or MSN homepage to the Google homepage. Compare Outlook to Gmail. Compare Yahoo or MSN Messenger to Google Talk. Compare a fancy animated presentation with a Takahashi Method presentation. The goal isn't to create the largest most complex powerful application anymore, it's to create the simplest application without sacrificing essential functionality. Unfortunately it's not as easy as it sounds. Creating an application that does what you need it to, but remains simple, is incredible difficult and tricky. The Laws of Simplicity (Simplicity: Design, Technology, Business, Life) by John Maeda, an MIT professor, is a collection of 10 laws about attaining simplicity . The book has large type, in a small binding, and is still only 100 pages long. (It would surely be hypocrisy to write a massive book on simplicity.) Each law makes a simple statement and then discusses how it works and how it is applied often including useful examples. As I read each of the ten laws I could quickly see how these laws have been used and applied in recent applications. One great example is law number 2 which extols the benefits of organization as a means of making something simpler. The law states: "Organization makes a system of many appear fewer." Office 2007 is an excellent example of this. The new ribbon interface took one of the most complex applications around and tried to simply it by organizing the essential features and hiding the rest. Whether you like the feature or not it is hard to argue that it doesn't make using Word much simpler. The line from the book that sticks with me the most is the following: "Simplicity is about subtracting the obvious, and adding the meaningful." I think this is a great statement that can really be applied to many things in life. In particular it plays a huge role in good writing. Subtracting obvious or meaningless words and adding meaningful words is a sure way to improve your writing. For instance this sentence: "The fact of the matter is that SubText is a cool blogging engine" is much better simplified to: "SubText is a cool blogging engine" The removed text is just meaningless complexity. It's probably needless complexity at this point to say it; but I thoroughly enjoyed this book and I encourage all of you to pick it up and spend the couple of hours it will take to read through it. -James 
|
-
SSL enables browsers to communicate with a web-server over a secure channel that prevents eavesdropping, tampering and message forgery. You should always use SSL for login pages where users are entering usernames/passwords, as well as for all other sensitive pages on sites (for example: account pages that show financial or personal information). Configuring SSL on Windows with previous versions of IIS has been a pain. Figuring out how to install and manage a certificate, and then associate it with a web-site, is something I bet most web developers don't know how to enable. The good news is that IIS 7.0 makes it radically easier to configure and enable SSL. IIS 7.0 also now has built-in support for creating "Self Signed Certificates" that enable you to easily create test/personal certificates that you can use to quickly SSL enable a site for development or test purposes. Using IIS 7.0 you can SSL enable an existing web site in under 30 seconds. The below tutorial demonstrates how to-do this. Step 1: Create a New Web Site We'll start by creating a new web-site using the new IIS 7.0 admin tool. This admin tool is a complete re-write of the previous IIS admin tool (and was written entirely in managed code using Windows Forms), and provides a more logical organization of web features. It provides a GUI admin experience for all ASP.NET and IIS settings: To create a new site on the box, right click on the "Web Sites" node in the left hand tree-view pane and choose the "Add Web Site" context menu option. Enter the appropriate details to create a new web-site: One nice feature of IIS7 on Windows Vista is that you can now have an unlimited number of sites on a box (previous versions of IIS on Windows Client only allowed 1 site). The 10 simultaneous request limitation on Windows Client versions of IIS also no longer exists with IIS 7.0. Once we've completed the above steps, we will now have a brand new site running on our IIS web-server. Step 2: Create a new Self Signed Certificate Before binding SSL rules to our new site, we need to first import and setup a security certificate to use with the SSL binding. Certificates are managed in IIS 7.0 by clicking the root machine node in the left-hand tree-view explorer, and then selecting the "Server Certificates" icon in the feature pane on the right: This will then list all certificates registered on the machine, and allow you to optionally import and/or create new ones. I could optionally go to a certificate authority like Verisign and purchase a certificate to import using this admin UI. Alternatively, I can create a "self-signed certificate" which is a test certificate that I can use during the development and testing of my site. To-do this, click the "Create Self-Signed Certificate" link on the right-hand side of the admin tool: Enter a name to use for the certificate (for example: "test") and hit ok. IIS7 will then automatically create a new self-signed crypto certificate for you and register it on the machine: Step 3: Enable HTTPS Bindings for our New Site To SSL enable the web-site we created earlier, select the web-site node in the left-hand tree-view, and the click the "Bindings" link in its "actions" pane on the right-hand side of the screen: This will then bring up a dialog that lists all of the binding rules that direct traffic to this site (meaning the host-header/IP address/port combinations for the site): To enable SSL for the site, we'll want to click the "Add" button. This will bring up an "add binding" dialog that we can use to add HTTPS protocol support. We can select the self-signed certificate we created earlier from the SSL certificate dropdownlist in the dialog, and in doing so indicate that we want to use that certificate when encrypting content over SSL: Click ok, and we now have SSL enabled for our site: Step 4: Test out the Site Add a "default.aspx" page to the site, and then try and hit it with the browser by typing https://localhost/default.aspx (note the usage of "https" instead of "http" to indicate that you want to connect over SSL). If you are using IE7, you'll likely see this anti-phishing error message kick in Don't panic if this happens - it is just IE being helpful by suggesting that a self-signed certificate on your local machine looks suspicious. Click the "Continue to this website" link to bypass this security warning and proceed to the site. You'll find that your default.aspx page is now running protected via SSL: You are all done. :-) Appendix: A Few Last SSL Notes A few last SSL related notes: - The IIS 7.0 admin tool has an "SSL Settings" node that you can select for each site, directory or file that allows you to control whether that particular resource (and by default its children) requires an SSL request in order to execute. This is useful for pages like a login.aspx page, where you want to guarantee that users can only enter their credentials when they are posting via an encrypted channel. If you configure the login.aspx page to require SSL, IIS 7.0 will block browsers from accessing it unless they are doing so over SSL.
- Within an ASP.NET page or handler, you can programmatically check whether the current request is using SSL by checking the Request.IsSecure property (it will return "true" if the incoming browser request is over SSL).
- You can set the "requireSSL" attribute on the <forms> configuration section within web.config files to have ASP.NET's forms-authentication system ensure that forms-authentication cookies are only set and used on SSL enabled pages and URLs. This avoids the risk of a hacker trying to intercept the authentication cookie on a non-SSL secured page, and then trying to use a "replay attack" from a different machine to impersonate a user.
For more information on IIS 7.0, please read my earlier IIS 7.0 overview blog post. Also make sure to check out the www.iis.net website. To read more of my "Tips and Tricks" blog posts, please visit my Tips and Tricks Summary Page. Hope this helps, Scott 
|
-
-
Recently some reports have been issued by security researchers describing ways hackers can use the JSON wire format used by most popular AJAX frameworks to try and exploit cross domain scripts within browsers. Specifically, these attacks use HTTP GET requests invoked via an HTML <script src=""> include element to circumvent the "same origin policy" enforced by browsers (which limits JavaScript objects like XmlHttpRequest to only calling URLs on the same domain that the page was loaded from), and then look for ways to exploit the JSON payload content. ASP.NET AJAX 1.0 includes a number of default settings and built-in features that prevent it from being susceptible to these types of JSON hijacking attacks. Below are some details of how these attacks are mitigated: ASP.NET AJAX Web Methods do not enable HTTP GET requests by default Script files loaded via an HTML <script src=""> element within a browser can only be retrieved via HTTP GET verb requests. By default ASP.NET AJAX's web services layer does not allow web methods to be invoked via the HTTP GET verb. For example, assume a developer writes a web service method like below: [WebMethod] public StockQuote[] GetQuotes(string symbol) {
}
ASP.NET will only allow the above GetQuotes method to be called via the HTTP POST verb, and will reject all attempts to invoke the method via an HTTP GET verb. To make an ASP.NET AJAX web-method callable via HTTP GET-access, a developer must explicitly attribute each method using ASP.NET's ScriptMethod attribute (and set the UseHttpGet property to true): [WebMethod] [ScriptMethod(UseHttpGet=true)]
public StockQuote[] GetQuotes(string symbol) {
}
Although this type of modification is easy to make, it requires a developer to intentionally GET enable a web service. ASP.NET AJAX web services can never be non-deliberately GET enabled, and the ASP.NET AJAX documentation explicitly recommends against GET enabling web-service end points for a number of reasons (risk of url tampering being one of them). Note: the ASP.NET AJAX "UpdatePanel" control, as well as the other server controls that ship with ASP.NET AJAX 1.0, do not use HTTP GET and instead use HTTP POSTs when doing asynchronous postbacks. ASP.NET AJAX Content-Type Header Validation There is built-in layer of protection that ASP.NET enforces for both GET and POST based ASP.NET AJAX web methods, which is that regardless of the HTTP verb being used, ASP.NET always requires that the HTTP Content-Type header is set to the value application/json. It this content type header is not sent, ASP.NET AJAX will reject the request on the server. Using the stock quote method shown earlier, an HTTP trace of an ASP.NET AJAX GET invocation must look like the following: GET /StockService/Stock.asmx/GetQuotes?symbol=%22msft%22 HTTP/1.1 Accept: */* Accept-Language: en-us,fr;q=0.5 Referer: http://xxxxxx/StockService/test.aspx Content-Type: application/json; charset=utf-8 UA-CPU: x86 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2) Host: xxxxxx Proxy-Connection: Keep-Alive
Note that even though the above is a GET request, the client-side ASP.NET AJAX JSON stack still inserts a Content-Type HTTP header that tells the server to consider this an AJAX web service request. The server-side web services stack for ASP.NET AJAX 1.0 always checks for this specific content type, and if it is not found it will reject the request. If a malicious developer attempted a cross site request forgery attack using HTTP GETs against this web service, they might include a script tag in their page like the following: <script type="text/javascript" src="http://contoso.com/StockService/Stock.asmx/GetQuotes?symbol=msft" /> However, browsers will not set the Content-Type to application/json when parsing a <script src=""> element and making the request. As a result when ASP.NET receives a request made from a <script /> include, it will not recognize it as a request to an ASP.NET AJAX web service, and it will result in an error from ASP.NET stating that it does not recognize the requested URL. This will prevent JSON Hijacking attempts (even if you have the GET verb enabled for a web method). Summary ASP.NET AJAX 1.0 by default only allows the HTTP POST verb to be used when invoking web methods using JSON, which means you can't inadvertently allow browsers to invoke methods via HTTP GET. ASP.NET AJAX 1.0 requires a Content-Type header to be set to "application/json" for both GET and POST invocations to AJAX web services. JSON requests that do not contain this header will be rejected by an ASP.NET server. This means you cannot invoke an ASP.NET AJAX web method via a <script src=""> include because browsers do not allow append custom content-type headers when requesting a JavaScript file like this. Hope this helps, Scott 
|
-
A familiar question in the ASP.NET world is: "How do I show the progress of a long-running background operation?"
ASP.NET AJAX has given us new tools to answer this question. It's easy to drop an UpdatePanel and a Timer inside a web form, and partially update the
page when the Timer control posts back. There are still some fundamentals to remember when taking this approach, however.
For example:
protected
void Button1_Click(object sender, EventArgs e) { HeavyDutyWorker
worker = new
HeavyDutyWorker
(); worker.ProgressNotification += new
ProgressEventHandler
(worker_ProgressNotification); worker.DoWork(); }
void worker_ProgressNotification(object
sender, ProgressEventArgs args) { Session
[ProgressKey] = args.PercentComplete; }
protected
void Timer1_Tick(object sender, EventArgs e) { Label1.Text = String.Format("Percent Complete = {0}",
Session[ProgressKey]); }
The button click event handler creates an object whose DoWork method is going to work asynchronously on some task.
Let's pretend the object fires an event each time it completes 10% of the work. The Page subscribes to this event, and the
event handler (worker_ProgressNotification) updates a session variable with the percentage of work complete.
To update the page with the completion percentage, the AJAX Timer fires a Tick event on the server. The Tick event
handler (Timer1_Tick) tries to read the completion percentage out of the session variable and update a Label control.
This approach will fail.
The problem lies in the worker_ProgressNotification event handler. The Page class uses HttpContext.Current to
retrieve the current Session object, but the asynch worker will raise this event on a background thread that is not
associated with an HttpContext. The line of code in the event handler will throw a System.Web.HttpException. Even if the
event fired on the right thread, the event will fire long after the Page has rendered and the original request that started
the asynch work is complete. All bets on having a valid HttpContext would be off at that point.
Interestingly, this approach does work if you use the Cache object (with a unique key for the user / work item, of
course). A Page always uses HttpContent.Current to fetch the Session object, but always carries a direct reference to the
Cache object. This is, of course, an implementation detail that could change in the future.
A good rule of thumb is to never let a Page subscribe to an event that doesn't originate from inside the Page (where user
controls and master pages are considered inside the Page). Anything else is asking for trouble.

|
-
Last December Microsoft announced the new Expression Studio products. These products enable designers to build awesome user experiences, and are designed to help facilitate great designer/developer workflow collaboration on projects. The Expression products share a common project file format with Visual Studio, which enables designers using Expression and developers using Visual Studio to open and edit the same projects together. They also share common UI declarative markup formats (HTML and XAML), which enables clean design/coding interaction. When we originally announced Expression, one of the common questions/complaints was over why we weren't planning on including the products (especially Expression Web and Expression Blend) within MSDN subscriptions. Today we announced that we were changing this (you can read details on Soma's blog post announcing it here). Expression Web and Expression Blend will now be available at no extra charge to all MSDN Premium Subscribers (this includes customers with the "VS Professional with MSDN Premium" subscription). This means many more developers will have awesome design tools for building great ASP.NET, WPF and "WPF/E" solutions. Visual Studio will also have integrated WYSIWYG designers for HTML, WPF and WPF/E as well. As I mentioned in my "First Look at Orcas for Web Development" blog post last month, the HTML designer within Visual Studio "Orcas" is actually the same one that ships in Expression Web (but integrated into the Visual Studio shell). VS "Orcas" also ships with a great new designer for WPF that integrates nicely within the Visual Studio IDE and adds rich developer features (for example: like live split-view designer/source editing and rich control extensibility). If you haven't tried out Expression Blend or Expression Web yet, I'd highly recommend giving them a spin. You can download free 180 day trial editions for them on the Microsoft Expression web site. Hope this helps, Scott 
|
-
Over the past year or so I've been creating a series of ASP.NET 2.0 tutorials for Microsoft that focus on working with data. These tutorials have been published on www.asp.net and on the MSDN website with the first batch published in June 2006. The Working with Data in ASP.NET 2.0 tutorials were modeled after the tutorial series started by Scott Guthrie and aimed to provide step-by-step instructions (with lots of screen shots) on how to perform common data-related patterns. I use the past tense here because, this past weekend, I wrapped up the final milestone for the data tutorials, turning in the final VB and C# versions of the 75th tutorial!!
At the time of this writing the most recent tutorials to be published were the Working with Binary Files tutorials (#54-#57). The upcoming tutorials examine:
- Caching (four tutorials)
- Data and the Site Map Provider (one tutorial)
- Working with Batched Data (looks at using transactions; four tutorials)
- Advanced Data Access Layer Scenarios (nine tutorials)
Writing these tutorials was very similar in process to writing a book. I'd wager that the average tutorial is about 10 printed pages in length, so the series is equivalent to authoring a 750 page book. It should come as no surprise, then, that I feel as spent as when sending off the final author review to a publisher. And, like after authoring a book, I am more than ready for a break from this time-intensive writing.
There are plenty of differences between writing a book and writing a book-length online tutorial series, of course. With a book you don't see a physical manifestation of the hard work until many months after the book has been written and reviewed. Online work, however, allows for incremental and quicker publication schedule, which.helps keep me motivated. And while well-publicized technical online material is more accessible and read by more people than a book, there's still something alluring about books... about being able to see a physical manifestation of your work in a bookstore. To see someone thumbing through your book. To hold it in your hands, to skim the table of contents, to turn to a random page and cast your mind back to the days you spent writing that chapter. These sensory delights are nice, but come at a cost, as writing computer trade books very often has a terrible ROI - see The Economics of Writing a Computer Trade Book for a more detailed breakdown of why writing computer trade books is not the way to riches.
Many thanks to those who helped review the tutorials or who have provided feedback or pointed out typos or other issues since their publication. One of the nice things about having an “online book” is that it is much easier to fix typos and update code, if necessary, so keep sending in corrections.
|
-
IIS 7.0 is one of the products that my team is shipping later this year that I'm most excited about. It is the most significant release of our web-server that we've done since IIS 1.0, and introduces a huge number of improvements for both administrators and developers. Mike Volodarsky from the IIS team wrote a great article for the March 2007 MSDN Magazine that summarizes some of the key IIS 7.0 improvements. I highly recommend reading his excellent article here for a quick summary of some of them. IIS 7.0 is included within the Windows Vista client release, and is now available with the home editions of the operating system (unlike IIS 5.1 which was only available with XP Professional). IIS 7.0 for server will ship later this year with Windows Longhorn Server, and will add a bunch of additional deployment features - including much richer hosting support, secure FTP support, and built-in web farm deployment support. The web farm support in particular is really cool, and will allow you to deploy your web applications on a file-share that contains all of the code, configuration, content, and encryption keys needed to run a server. You can then add any number of stateless and configuration-less web-servers into a web farm and just point them at the file-server to dynamically load their configuration settings (including bindings, virtual directories, app pool settings, etc) and application content. This makes it trivial to scale out applications across machines, and avoid having to use replication schemes for configuration and application deployment (just copy over the files on the file-share and all of the machines in the web farm will immediately pick up the changes). The upcoming Beta3 release of Windows Longhorn Server will support a go-live license, so you'll be able to take advantage of this soon (note: we are already running www.Microsoft.com on IIS 7.0 clusters). ASP.NET and IIS 7.0 Integration In previous versions of IIS, developers had to write ISAPI extensions/filters to extend the server. In addition to being a royal pain to write, ISAPIs were also limited in how they plugged into the server and in what they allowed developers to customize. For example, you can't implement URL Rewriting code within an ISAPI Extension (note: ASP.NET is implemented as an ISAPI extension). And you end up tying up the I/O threads of the web-server if you write long-running code as an ISAPI Filter (which is why we didn't enable managed code to run in the filter execution phase of a request). One of the major architectural changes we made to the core IIS processing engine with IIS7 was to enable much, much richer extensibility via a new modular request pipeline architecture. You can now write code anywhere within the lifetime of any HTTP request by registering an HTTP Extensibility Module with the web-server. These extensibility modules can be written using either native C++ code or .NET managed code (you can use the existing ASP.NET System.Web.IHttpModule interface to implement this). All "built-in" IIS7 functionality (authentication, authorization, static file serving, directory listing support, classic ASP, logging, etc) is now implemented using this public modular pipeline API. This means you can optionally remove any of these IIS7 "built-in" features and replace/extend them with your own implementation. ASP.NET on IIS 7.0 has itself been changed from being implemented as an ISAPI to instead plug in directly as modules within the IIS7 pipeline: Among the many benefits this brings: 1) You can now use ASP.NET Forms Authentication, Membership/Roles, and any other feature for all requests to the server (for example: .htm, .php, and .jsp files) 2) You can now easily re-write the URL of any web request and/or modify the request in interesting ways 3) You can replace or extend any existing IIS feature using VB or C# (for example: you could remove the built-in directory listing module and plug-in your own). This really brings a tremendous number of extensibility opportunities to .NET developers. IIS 7.0 Download Center To help enable developers share the extensibility modules and other add-ins they write, the IIS team recently launched the "Download Center" on www.iis.net. This enables developers to browse/download as well as upload and share module extensions for IIS. You can check it out here. Note that in addition to having a managed extensibility story for Http Modules, IIS7 also now allows you to write managed admin tool UI extensions (the admin tool itself was built using Windows Forms), as well as use the .NET System.Configuration namespace to manage the IIS7 configuration system. Cool Scenarios for ASP.NET Developers In addition to the cool new extensibility options that IIS 7.0 provides, there are a ton of improvements (both big and small) that ASP.NET developers will really appreciate. I'll be blogging a series of them over the next few weeks/months and point out some really cool things that you'll be able to take advantage of. Hope this helps, Scott 
|
|
|
|