BusinessRx Community

Dedicated to the advancement of software, technology and the people who devote their lives to it.

Welcome to BusinessRx Community Sign in | Join | Help
in Search

BusinessRx Reading List

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.

March 2007 - Posts

  • Slides from my ASP.NET Connections talks: WPF/E, LINQ and ASP.NET Tips/Tricks

    Earlier this week I presented three breakout sessions at the ASP.NET Connections conference in Orlando.  Below are the slides / demos for each of the talks I gave:

    Introduction to "WPF/E"

    This talk provides a good introduction to "WPF/E" - which is the code-name for a new small, cross platform browser runtime that enables developers and designers to deliver richer, more interactive web experiences.  I first blogged about "WPF/E" here.

    You can download the slides+demos from my WPF/E talk here (it includes a video sample - which makes the overall download ~10MB).  The talk provides an overview of the core capabilities within the WPF/E CTPs today, and also demonstrates the core XAML and JavaScript programming model concepts you use.

    For more "WPF/E" samples please visit the online "WPF/E" sample gallery on Channel9 here.  You can also download documentation and samples on the official "WPF/E" MSDN site here.  Mike Harsh on my team also maintains a fantastic blog that covers WPF/E here that I highly recommend subscribing to.

    Building Data Driven Web Applications using LINQ

    This talk provided a drill down of LINQ (which will ship as part of our "Orcas" release), and demonstrated some of the dramatic productivity improvements it will bring for ASP.NET.  Click here to download the slides for this talk.

    If you haven't seen it yet, I highly recommend watching my 20 minute video that demonstrates using LINQ with Visual Studio "Orcas" here.  You can learn even more about LINQ and how to use it with ASP.NET by reviewing some of my past LINQ blog posts.  Here are a few in particular worth reviewing:

    Lastly, to learn more about some of the new C# and VB language features coming out with "Orcas" (and which LINQ heavily uses), please check out the first two posts in my language series here:

    I'm going to try and post the next installment in my language series (which will cover Lambdas) in the next few days - so stay tuned for that.

    ASP.NET 2.0 Tips and Tricks:

    This talk covered ASP.NET UI, AJAX, Caching and Deployment Tips and Tricks, and Visual Studio 2005 tips/tricks.  The samples include updated versions of ASP.NET AJAX that all work with ASP.NET AJAX 1.0.  You can download the slides+samples here.

    You can learn more about the Visual Studio build performance optimization suggestions by reading this past post of mine on improving build performance

    Hope this helps,

    Scott

  • Jeff Atwood on Putting Down the Mouse

    Jeff Atwood has another great blog post, this one about going commando and putting down the mouse. Knowing keyboard shortcuts is a great productivity booster, as the keyboard-to-mouse context switch has high latency. I prefer keeping my hands on the keyboard as much as possible, delegating to the mouse only when necessary. As such, I've setup a variety of keyboard shortcuts in Microsoft Word to perform common actions and am fairly well-versed in the keyboard shortcuts for Visual Studio.

    There is one place where I overuse keyboard shortcuts, and that is when I am teaching or training. By habit, when I want to perform some action I use the keyboard shortcut I know, but this doesn't translate well when you are showing a class how to accomplish some task because they only can see your screen on the projector and cannot see the keys you just pressed.

    In any event, Jeff's blog entry reminded me of a past experience. There have been many developers I've met over the years who have impressed me in various ways. Here is a story about one of them that is related to Jeff's blog entry...

    At the university where I did my undergraduate work, computer science seniors had to take this special class their last two semesters that attempted to mimic real-world software development projects. We'd get assigned to groups and would have to pick a problem from a long list that would involve meeting with real clients (small businesses in the community), crafting requirements, building the app, testing, deploying, and so forth. A pretty neat program.

    Anywho, each group would have to give a 15-30 minute presentation at the end of the semester to the faculty and other groups, discussing their progress, challenges encountered, blah blah blah. Many would demo their application. In my junior year I was in the computer lab working on an assignment and in came a group of seniors getting ready to present their senior project. One group member had lugged his desktop computer from home to demo their application. 15 minutes before class was about to start and they were to present, the desktop is plugged in and powered up in order to do a final test run. To his group members horror, the mouse was not working! I don't know if they had it plugged into the wrong port, if it had dropped on the way over, or if it was just an old and unreliable computer or peripheral. Regardless, the group member who brought the desktop machine showed his mettle by shrugging off his group members' panic, going commando and launching the app and running through their presentation entirely from the keyboard!

    I didn't know this guy outside of seeing him in the lab a few times over the course of the school year. Never knew his name or saw him again after that day. But I remember his calm in the face of four worried group members and his mastery of the keyboard, and for those reasons I was thoroughly impressed and knew that this would be a developer I'd want on my team.

  • Too Much Encapsulation

    A couple times this year I've wanted to plug some electronics into a hotel TV. For instance, when I'm on the road and want to watch a movie from my Creative Vision M. I also unexpectedly came into possession of an XBOX 360 during a recent trip to Seattle (thank you, Party with Palermo and PreEmptive).

    Side note: My XBOX Live Gamertag thingy is:

    XBOX Gamertag

    The last couple hotel TVs I've looked at offer no media inputs on the front. No problem, I'll think to myself. If there are no inputs on the front, there must be inputs on the back. Getting to the back of a hotel TV, however, is a problem.

    You see, here in the United States a television is a prized commodity. Watch carefully next time you see news footage of looting in the U.S. After a natural disaster, you won't see looters plundering grocery stores for canned food and bottled water, but you will see them carrying 32 inch televisions through streets of rubble. As soon as electricity is restored, American Idol can alleviate the dehydration and malnourishment.

    To protect their assets from rouge bands of Idol depraved looters, hotels lock their TVs into place using the strongest, heat-tempered metals known to mankind. Depending on how the TV is mounted, it's often physically impossible to look at the back of a television. No problem, I think, I'll reach around and take a picture of the back, and find some inputs.

    TV Black Box

    The proverbial "black box" is here, bolted onto the TV. All inputs are hard wired. I think the plastic twisty thing is some sort of tamper detection "seal". Turns out hotels don't want you to watch movies unless you watch their pay-for-view movies.

    If this TV was a Visual Basic class, it would have the MustNeverInheritOrOverideAnything keyword attached.

  • Office Layout and Space

    Joel Spolsky has an interesting blog entry up about searching for new office space. What's particularly interesting about this post is the contrast between Joel's requirements a the average office space requirements. He is a strong proponent of making the workplace attractive[1] and for his new office space he desires private offices for all employees with ample daylight. The best floorplans to meet such requirements allow for at most 30 feet between the building's outer wall and the core of the building to allow for two rows of offices. However, most office builings in New York have much larger areas between the outer wall and the core to maximize cube farm square footage.

    It's interesting to see the tangential challenges that face business owners. And I concur with Joel's opinions on the relationship between attractive and distraction-free workspaces and productivity. I've been working from home for the vast majority of my career, but I did have two office jobs. The first was in a building that had offices and cubicals. When I arrived, the cube farm was full, yet there were open offices, so as luck would have it I ended up with a rather large office with floor to ceiling windows looking out from the 11th story (IIRC). The office could have doubled as a meeting room, as it was huge, and for several months it was all mine!! But as the company grew, they eventually moved three additional developers into the same office.

    My only other experience that involved not working from home had be bounce around a few two-person offices. I think I had three different offices in a three month span (moving offices - another productivity drain). Also, constantly moving offices means you don't get to really know your office mate. Joel also espouses the benefits of natural light, and I hearily concur. Working in an office that's cut off from sunlight feels like working in a cave. This is kind of nice if you're a night owl and saunder into work around 4:00 PM, but if you get your most productive work done in the morning or early afternoon hours (like yours truly), then cave-like offices can definitely be a drain on productivity.

    So what is Joel to do? How can he balance the real-world topography of office buildings in New York with his lofty requirements? I wonder if he could 'cohabitate' with another company? Joel's crew can have the sunlight offices and the other company can have the dank inner offices or cubes. Or maybe they can pipe in sunlight somehow... solatubes or whatnot.

  • What's Wrong With This Code? (#13)

     

    For lucky #13, I want to know what can go terribly wrong with the following code, and why.

    class HardWorker
    {        
        
    public void DoMultiThreadedWork(object someParameter)
        {
            
    lock (lockObject)
            {
                
    // ... lots of work ...
            }
        }

        
    private string lockObject = "lockit";
    }

     

    Hint: Think about memory optimizations in the CLR.

  • Me Presenting at the Space Coast .NET User Group in Florida this Tuesday

    I'm in Orlando the next few days presenting at the spring ASP.NET Connections / DevConnections conference.  There are about ~1500 people attending this week's conference, which is a great turnout for the spring show (the fall show is in Las Vegas each year in November, and had almost 5,000 people last year).

    On Tuesday, I'll also be presenting on ASP.NET and Visual Studio "Orcas" at the Space Coast .NET User Group.  The presentation starts at 6:30pm and is free for everyone who wants to attend.  You can register online to attend the talk here (you can also find the address of the event and driving instructions).

    Hope to see some of you there!

    Scott

  • The Head Tag in ASP.NET 2.0

    The Themes feature in ASP.NET 2.0 requires a server-side <head> tag. In other words, if you don't have runat="server" in the <head> tag, like the following:

    <head runat="server">
        <!-- head stuff -->
    </head>

     

    … then trying to use css files from a theme will create a runtime exception with a clear error message:

    Exception Details: System.InvalidOperationException: Using themed css files requires a header control on the page. (e.g. <head runat="server" />).

    Not every component yields such a direct message, however.

    I've been updating pages in a 5 year old application by adding some AJAX features and using some flair from the Control Toolkit. It's been some time since I've been in the UI layer of an application, but I've restrained myself and haven't gotten too crazy. Still, when I saw the Calendar extender I knew it was a perfect fit. After adding the control, the page threw an exception.

    System.NullReferenceException: Object reference not set to an instance of an object.
    at AjaxControlToolkit.ScriptObjectBuilder.RegisterCssReferences(Control control) ...
    at AjaxControlToolkit.ExtenderControlBase.OnPreRender(EventArgs e) ...
    at System.Web.UI.Control.PreRenderRecursiveInternal() ...
    ...

    Because I knew that the themes feature in ASP.NET 2.0 relies on an active header control to inject style sheets, I figured the ScriptObjectBuilder used the same trick to inject new script tags. Just adding runat="server" in the head tag of the page was enough to fix the problem.

  • MbUnit: Unit Testing for People who Love Unit Testing

    Mike has posted my slides and samples from the MbUnit talk, it's nothing ground-breaking that you can't find elsewhere but if you are interested in MbUnit it's a good introduction to some of the different tests, fixtures, and assertions that MbUnit has to offer.

    Get it here.

    -James

  • ASP.NET and HTML - Past, Present, Future

    Yesterday, I was giving an AJAX facelift to some old, old .aspx files. These files were created in the first version of Visual Studio.NET and have been running smoothly for years. Inside I found:

    <meta content="Microsoft Visual Studio 7.0" name="GENERATOR">
    <
    meta content="C#" name="CODE_LANGUAGE">
    <
    meta content="JavaScript" name="vs_defaultClientScript">
    <
    meta content="http://schemas.microsoft.com/intellisense/ie5"
           name="vs_targetSchema">

    ...

    <body MS_POSITIONING="GridLayout">

     

    ASP.NET has come a long way since the days when MS_POSITIONING appeared. GridLayout meant that every control dropped on the form used absolute positioning by default. GridLayout was a thrill for new web developers who came from a VB6 background, but the feature didn't fly so well with anyone who took HTML seriously.

    Ironically, Microsoft's web tools are now closer to the metal than they've ever been. The VS2005 editor is XHTML-compliant. The CSS Friendly Control Adapters can customize a control's HTML output. This trend continues in Orcas where the split screen view (see a screen shot in ScottGu's post) keeps the web form designer and the HTML editor on screen at the same time.

    I think it's safe to say we aren't abstracting HTML away anytime soon. While it's OK to hide XmlHttpRequests and client side event handling behind frameworks and script libraries, everyone wants to see, feel, touch, and taste the HTML.

  • ASP.NET AJAX Documentation Update, Videos and Cool Articles

    Here is a quick post on some great ASP.NET AJAX focused content that has been published recently:

    ASP.NET AJAX Documentation Update

    The ASP.NET documentation team recently posted a refresh of the ASP.NET AJAX 1.0 documentation.  Click here to browse it or download it locally.

    Here is a quick summary of some of the improvements:

    • Updated 38 overview and tutorial topics to include suggestions, additional information, and fix inaccuracies
    • Created a new conceptual topic about browser compatibility and security settings for AJAX-enabled Web sites
    • Created two new conceptual topics for ASP.NET AJAX client lifecycle events
    • Updated 243 client reference topics to address customer questions, and incorporate suggestions and feedback
    • Created 14 new client reference topic about the Generated Proxy Classes
    • Updated 165 code snippets to clarify coding patters, incorporate suggestions, and fix inaccuracies
    • Added 61 new code snippets
    New ASP.NET AJAX "How Do I?" Videos

    Joe Stagner from the ASP.NET team has continued to publish great new ASP.NET AJAX "How Do I?" Videos (all of which are free):

    Here are some of the recently published videos:

     

    Watch all of his videos for free here.

    How to Build a PageFlakes.com-like Home Page using ASP.NET AJAX

    Omar Al Zabir is the co-founder and CTO of www.PageFlakes.com - a really cool web 2.0 home-page service (that is also built using ASP.NET AJAX).

    He wrote a great article that walksthrough how to build a customized portal home-page that enables client-side drag/drop and user personalization:

    You can read his article on how to build the above site using ASP.NET AJAX 1.0 and download the sample code here.

    Eilon's ASP.NET AJAX Blog Posts

    Eilon Lipton is a key developer on the ASP.NET team, and has a great blog here.  He has a number of recent ASP.NET AJAX posts to check out:

    Bertrand's ASP.NET AJAX Posts

    Bertrand Le Roy is a key developer on the ASP.NET team, and is also representing Microsoft within the OpenAJAX alliance.  He maintains a great blog here.

    A few great ASP.NET AJAX posts he has written recently:

    Bertrand has also written a great PDF book with Matt Gibbs that you can obtain through O'Reilly's Short Cuts series.  It is called "ASP.NET AJAX UpdatePanel Control" and (surprise!) covers how to use the ASP.NET AJAX UpdatePanel control.  You can get it here.

    Jeff Prosise Drag-Drop Example

    Jeff recently posted a great blog post that covers how to implement a nice drag/drop client AJAX library using the client-side JavaScript library of ASP.NET AJAX.  You can read his post here.

    Hope this helps,

    Scott

  • Microsoft Joins OpenAJAX Alliance

    I'm really pleased to be able to announce that Microsoft today joined the OpenAjax alliance

    The OpenAjax alliance is a group of vendors, open source projects and companies using AJAX that are focused on developing common AJAX standards and ensuring interoperability across different AJAX frameworks, tools and technologies.  Joining the group will help ensure that the Microsoft AJAX Library and ASP.NET 2.0 AJAX Extensions integrate well with other AJAX frameworks and server technologies.  

    Interoperability has always been a key ASP.NET AJAX deliverable. We made the client-side Microsoft AJAX Library work seamlessly with other server frameworks from the very beginning, and during the beta we went through and renamed several JavaScript classes/functions to avoid collisions with other frameworks (for example: $() to $get() and Sys.Debug). Through the OpenAjax Alliance we will partner with other industry leaders to provide even deeper interoperability in a way that continues to benefit all developers on all platforms.

    Bertrand Leroy from the ASP.NET Team will be representing Microsoft in the organization's upcoming meetings.  Stay tuned to his blog to stay up to date.

    Hope this helps,

    Scott

  • Windows Workflow Foundation and Domain Specific Languages

    Windows Workflow Foundation is a multi-faceted technology. Some people will look at WF and see a tool to manage long-running business processes, while others see a rules engine. Yet another perspective is to look at WF as a tool for building domain specific languages.

    Last week I had numerous conversations with talented individuals who reinforced this theme of WF as a DSL tool. For example- Kathleen Dollard builds code-generation tools for developers, and Sam Gentile builds applications for financial analysts. Both of them are giving their end users the ability to create tailored software using a domain specific language. The DSLs themselves are composed from custom activities in Windows Workflow Foundation. Microsoft has built a few DSLs on top of WF too, most notably in the latest release of Sharepoint Server and in Speech Server 2007.

    Here's a few interesting resources on custom activity development in WF:

    Build Custom Activities To Extend The Reach Of Your Workflows – Matt Milner

    Speaker Verification Activity for Speech Server 2007 – Casey Chestnut

    Custom Activity Samples in the SDK

    HOW TO: Create a custom Windows Workflow Activity and make it available in SharePoint Designer – Todd Baginski

    Creating a Custom Composite Activity – Morgan Skinner

    I'm still hoping the WF team will one day publish and document the source code to the base activity library in WF. This would be a great starting point for developers who need to build robust, production ready custom activities.

  • Inserting through the GridView's Footer Row - Easy Unless There are No Records Bound to the Grid!

    As I mentioned in an earlier blog post this month, three new data tutorials were added to my Working with Data in ASP.NET 2.0 tutorial series. One of these new tutorials looked at how to use the GridView's footer row as an inserting interface (see Inserting a New Record from the GridView's Footer [VB | C#]). The “footer as inserting interface” approach works well enough if there are records bound to the GridView. However, if you are working with a GridView that has no data associated with it, the footer row doesn't appear. In ASP.NET 1.x this wasn't an issue because regardless of whether there were any records in the DataGrid's data source, the header and footer were still displayed. It was the page developer's responsibility to check if there were no data records bound to the DataGrid and, if so, to hide the grid and display an appropriate message. In the case of using the footer to insert, however, we would leave the DataGrid visible so that the footer row was still present to allow the user to add the first record to the grid.

    The GridView in ASP.NET 2.0 works a bit differently. If there are no records in the GridView's data source, it does not display its header or footer. If its EmptyDataText or EmptyDataTemplate properties are set, it will show that, otherwise the GridView emits no markup.

    So, if you have an inserting interface in the GridView's footer, but there are no records in the underlying table, the footer will not display! Eep. What to do?

    One option is to use the EmptyDataTemplate property. Drop a DetailsView in there, bind it to the same data source control as the GridView, check the “Enable Inserting” option from its smart tag and set its DefaultMode property to Insert. This will present the user with an inserting interface when there are no records in the table. Once they add a new record, the GridView will display its new, single record and future records can be added through the footer row.

    If you use the DetailsView in the EmptyDataTemplate option and bind it to the same ObjectDataSource as used by the GridView with the code presented in the tutorial, you'll need to make one minor code modification. The ObjectDataSource has an event handler for its Inserting event. There is picks out the values from the footer and uses those values to populate its parameters. When inserting from the DetailsView, however, we can use two-way databinding instead (i.e., adding <%# Bind(”ColumnName”) %> to the properties of the Web controls in the DetailsView's InsertItemTemplates). Consequently, you'll need to bypass reading in the GridView's footer row values when inserting from the DetailsView, which can be accomplished with the following conditional statement:

        1 // Only performt he following logic when inserting through the footer

        2 if (Products.Rows.Count == 0)

        3     // We are inserting through the DetailsView in the EmptyDataTemplate

        4     return;

    I've got a working example you can download to test this out. It's a stripped-down version of the download from the tutorial. I've manually deleted all of the rows from the Products table and added a DetailsView to the GridView's EmptyDataTemplate. Moreover, I've bound this DetailsView to the same ObjectDataSource as used by the GridView, added the above conditional statement to the ObjectDataSource's Inserting event handler, and added the markup to implement two-way databinding on the DetailsView. You can download this example from: http://datawebcontrols.com/demos/InsertFromFooter.zip

    Hope this helps and, as always, Happy Programming!

  • GotDotNet? Not Anymore, You Don't

    Microsoft's web property GotDotNet will be completely shut down and phased out of existence by June 19, 2007. From the GotDotNet homepage:

    Microsoft will be phasing out the GotDotNet site by July 2007.

       Microsoft will phase out all GotDotNet functionality by July 2007. We will phase out features according to the schedule below. During the phase-out we will ensure that requests for features or pages that are no longer available will render enough information for you to understand what has changed. If you have any questions please don’t hesitate to contact the GotDotNet Support team.

    We are phasing out GotDotNet for the following reasons:

  • Microsoft wants to eliminate redundant functionality between GotDotNet and other community resources provided by Microsoft
  • Traffic and usage of GotDotNet features has significantly decreased over the last six months
  • Microsoft wants to reinvest the resources currently used for GotDotNet in new and better community features for our customers

  • Phase Out Schedule
    The GotDotNet phase out will be carried out in phases according the following timetable:

    Target Date Areas to be Closed
    February 20 Partners, Resource Center, Microsoft Tools
    March 20 Private workspaces, Team pages, Message Boards
    April 24 GDN CodeGallery (projected date)
    May 22 GDN User Samples (projected date)
    June 19 GDN Workspaces (projected date)

    I understand how Microsoft doesn't want to dedicate any resources to a “dead site,” but why kill the site altogether? Couldn't they just stop new workspaces from being opened, stop new messageboard posts, stop new user samples from being submitted, and so on, but leave the existing pages up and available? There are countless messageboard posts, user samples, articles, and other valuable content that Microsoft is just throwing away. (The messageboard at the skmMenu workspace, for example, has over 1,000 messageboard posts that will evaporate come June 19.)

    Back in the COM days (and now in the Web Services sphere), developers harped on public interfaces exposed by a COM component or a Web service endpoint, and how these interfaces represented a contract that should never be broken. Doesn't a URL constitute a public interface into a web application? Once a URL is public, shouldn't that URL always work? My opinion is that it should. For example, I have DataGrid FAQs up at DataWebControls.com, but since the advent of ASP.NET 2.0 the DataGrid has been relegated to the dustbin of web technology. Sure, there are still people doing ASP.NET 1.x (including yours truly), but as time marches on, this will become less important. Yet I plan to keep these FAQs there in perpetuity because once a URL is public and has been put out there for the world to consume, it is rude (and, dare I say, wrong) to remove it.

    Hopefully Microsoft will decide to let GDN live on, if just as its existing content. Failure to do so not only removes useful content from the Internet, but also sends a rather innocuous message to users of CodePlex, Microsoft's GDN successor: “One day we might decide to nuke this site and your projects, messages, and contributions.”

  • April's Toolbox Column Now Available Online

    My Toolbox column in the April 2007 issue of MSDN Magazine is now avaiable online. The April issue examines three products:

    • WiXAware - a program for graphically creating and managing WiX installation files.
    • Apose.Slides for .NET - programmatically create and edit PowerPoint presentations.
    • Subversion - a popular, open-source source control product.

    This month's issue reviewed SQL Hacks, by Andrew Cumming and Gordon Russell. Here is an excerpt from the review:

    Most books on SQL focus on its syntax and semantics, specifying the structure of the SELECT statement, how the GROUP BY clause can be used, and so forth. While such information is helpful for beginners, seasoned database professionals are more interested in scenario-based learning. They want to read about queries and techniques that can help them tackle their difficult problems. What queries can you use to identify overlapping ranges in data? How do you create and maintain an audit table, or compare and synchronize tables? If this is the kind of information you are searching for, check out SQL Hacks, written by Andrew Cumming and Gordon Russell and published by O'Reilly.

     

    As always, if you have any suggestions for products or books to review for the Toolbox column, please send them into toolsmm@microsoft.com.

  • An RSS Feed for My "Working with Data in ASP.NET 2.0" Tutorials

    There is now an RSS feed available for my Working with Data in ASP.NET 2.0 Tutorials series. There are currently 53 tutorials online at http://www.asp.net/Learn/DataAccess/ (as well as the first 13 available on the MSDN website), but there will be 75 in total.

    What better way to be kept abreast of the latest tutorials than by subscribing to the RSS feed?   :-)
    http://www.asp.net/Learn/DataAccess/rss.ashx

  • An Introduction to JavaScript Object Notation (JSON)

    JavaScript Object Notation (JSON) is simple, lightweight data-exchange format that is used by most AJAX implementations (although it can be used by other applications and domain spaces). It is used to serialize data structures into a text format that is especially easy to parse and evaluate directly from JavaScript code. Back in 2006, Atif Aziz approached me and asked if I'd like to coauthor an introductory article on JSON. The net result is the latest article on MSDN online, An Introduction to JavaScript Object Notation (JSON) in JavaScript and .NET.

    The article focuses on JSON - its purpose, the standard, a comparison of XML and JavaScript, and so forth. The .NET examples use Atif's open-source Jayrock library, which provides classes for reading and writing JSON text as well as serializing and deserializing JSON to .NET types and vice-a-versa. It also includes support for JSON-RPC.

    Enjoy!

  • New "Orcas" Language Feature: Extension Methods

    Last week I started the first in a series of blog posts I'll be making that cover some of the new VB and C# language features that are coming as part of the Visual Studio and .NET Framework "Orcas" release later this year. 

    My last blog post covered the new Automatic Properties, Object Initializer and Collection Initializer features.  If you haven't read my previous post yet, please read it here.  Today's blog post covers a much more significant new feature that is available with both VB and C#: Extension Methods.

    What are Extension Methods?

    Extension methods allow developers to add new methods to the public contract of an existing CLR type, without having to sub-class it or recompile the original type.  Extension Methods help blend the flexibility of "duck typing" support popular within dynamic languages today with the performance and compile-time validation of strongly-typed languages.

    Extension Methods enable a variety of useful scenarios, and help make possible the really powerful LINQ query framework that is being introduced with .NET as part of the "Orcas" release.

    Simple Extension Method Example:

    Ever wanted to check to see whether a string variable is a valid email address?  Today you'd probably implement this by calling a separate class (probably with a static method) to check to see whether the string is valid.  For example, something like:

    string email Request.QueryString["email"];

    if 
    ( EmailValidator.IsValid(email) ) {
       

    }

    Using the new "extension method" language feature in C# and VB, I can instead add a useful "IsValidEmailAddress()" method onto the string class itself, which returns whether the string instance is a valid string or not.  I can then re-write my code to be cleaner and more descriptive like so:

    string email Request.QueryString["email"];

    if 
    ( email.IsValidEmailAddress() ) {
       

    }

    How did we add this new IsValidEmailAddress() method to the existing string type?  We did it by defining a static class with a static method containing our "IsValidEmailAddress" extension method like below:

    public static class ScottGuExtensions
    {
        
    public static bool IsValidEmailAddress(this string s)
        {
            Regex regex 
    = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
            return 
    regex.IsMatch(s);
        
    }
    }

    Note how the static method above has a "this" keyword before the first parameter argument of type string.  This tells the compiler that this particular Extension Method should be added to objects of type "string".  Within the IsValidEmailAddress() method implementation I can then access all of the public properties/methods/events of the actual string instance that the method is being called on, and return true/false depending on whether it is a valid email or not.

    To add this specific Extension Method implementation to string instances within my code, I simply use a standard "using" statement to import the namespace containing the extension method implementation:

    using ScottGuExtensions;

    The compiler will then correctly resolve the IsValidEmailAddress() method on any string.  C# and VB in the public "Orcas" March CTP now provide full intellisense support for extension methods within the Visual Studio code-editor.  So when I hit the "." keyword on a string variable, my extension methods will now show up in the intellisense drop-downlist:

    The VB and C# compilers also naturally give you compile-time checking of all Extension Method usage - meaning you'll get a compile-time error if you mis-type or mis-use one.

    [Credit: Thanks to David Hayden for first coming up with the IsValidEmailAddress scenario I used above in a prior blog post of his from last year.]

    Extension Methods Scenarios Continued...

    Leveraging the new extension method feature to add methods to individual types opens up a number of useful extensibility scenarios for developers.  What makes Extension Methods really powerful, though, is their ability to be applied not just to individual types - but also to any parent base class or interface within the .NET Framework.  This enables developers to build a variety of rich, composable, framework extensions that can be used across the .NET Framework.

    For example, consider a scenario where I want an easy, descriptive, way to check whether an object is already included within a collection or array of objects.  I could define a simple .In(collection) extension method that I want to add to all objects within .NET to enable this.  I could implement this "In()" extension method within C# like so:

    Note above how I've declared the first parameter to the extension method to be "this object o".  This indicates that this extension method should applied to all types that derive from the base System.Object base type - which means I can now use it on every object in .NET. 

    The "In" method implementation above allows me to check to see whether a specific object is included within an IEnumerable sequence passed as an argument to the method.  Because all .NET collections and arrays implement the IEnumerable interface, I now have a useful and descriptive method for checking whether any .NET object belongs to any .NET collection or array.

    I could use then use this "In()" extension method to see whether a particular string is within an array of strings:

    I could use it to check to see whether a particular ASP.NET control is within a container control collection:

    I could even use it with scalar datatypes like integers:

    Note above how you can even use extension methods on base datatype values (like the integer value 42).  Because the CLR supports automatic boxing/unboxing of value-classes, extensions methods can be applied on numeric and other scalar datatypes directly. 

    As you can probably begin to see from the samples above, extension methods enable some really rich and descriptive extensibility scenarios.  When applied against common base classes and interfaces across .NET, they enable some really nice domain specific framework and composition scenarios. 

    Built-in System.Linq Extension Methods

    One of the built-in extension method libraries that we are shipping within .NET in the "Orcas" timeframe are a set of very powerful query extension method implementations that enable developers to easily query data.  These extension method implementations live under the new "System.Linq" namespace, and define standard query operator extension methods that can be used by any .NET developer to easily query XML, Relational Databases, .NET Objects, and/or any other type of data structure. 

    A few of the advantages of using the extension method extensibility model for this query support include:

    1) It enables a common query programming model and syntax that can be used across all types of data (databases, XML files, in-memory objects, web-services, etc).

    2) It is composable and allows developers to easily add new methods/operators into the query syntax. For example: we could use our custom "In()" method together with the standard "Where()" method defined by LINQ as part of a single query.  Our custom In() method will look just as natural as the "standard" methods supplied under the System.Linq namespace. 

    3) It is extensible and allows any type of data provider to be used with it.  For example: an existing ORM engine like NHibernate or LLBLGen could implement the LINQ standard query operators to enable LINQ queries against their existing ORM implementation and mapping engines.  This will enable developers to learn a common way to query data, and then apply the same skills against a wide variety of rich data store implementations.

    I'll be walking through LINQ much more over the next few weeks, but wanted to leave you with a few samples that show how to use a few of the built-in LINQ query extension methods with different types of data:

    Scenario 1: Using LINQ Extension Methods Against In-Memory .NET Objects

    Assume we have defined a class to represent a "Person" like so:

    I could then use the new object Initializer and collection Initializer features to create and populate a collection of "people" like so:

    I could then use the standard "Where()" extension method provided by System.Linq to retrieve a sequence of those "Person" objects within this collection whose FirstName starts with the letter "S" like so:

    The new p => syntax above is an example of a "Lambda expression", which is a more concise evolution of C# 2.0's anonymous method support, and enables us to easily express a query filter with an argument (in this case we are indicating that we only want to return a sequence of those Person objects where the firstname property starts with the letter "S").  The above query will then return 2 objects as part of the sequence (for Scott and Susanne).

     I could also write code that takes advantage of the new "Average" and "Max" extension methods provided by System.Linq to determine the average age of the people in my collection, as well as the age of the oldest person like so:

    Scenario 2: Using LINQ Extension Methods Against an XML File

    It is probably rare that you manually create a collection of hard-coded data in-memory.  More likely you'll retrieve the data either from an XML file, a database, or a web-service.

    Let's assume we have an XML file on disk that contains the data below:

    I could obviously use the existing System.Xml APIs today to either load this XML file into a DOM and access it, or use a low-level XmlReader API to manually parse it myself.  Alternatively, with "Orcas" I can now use the System.Xml.Linq implementation that supports the standard LINQ extension methods (aka "XLINQ") to more elegantly parse and process the XML. 

    The below code-sample shows how to use LINQ to retrieve all of the <person> XML Elements that have a <person> sub-node whose inner value starts with the letter "S":

    Note that it uses the exact same Where() extension method as with the in-memory object sample.  Right now it is returning a sequence of "XElement" elements, which is an un-typed XML node element.  I could alternatively re-write the query to "shape" the data that is returned instead by using LINQ's Select() extension method and provide a Lambda expression that uses the new object initializer syntax to populate the same "Person" class that we used with our first in-memory collection example:

    The above code does all the work necessary to open, parse and filter the XML in the "test.xml" file, and return back a strongly-typed sequence of Person objects.  No mapping or persistence file is necessary to map the values - instead I am expressing the shaping from XML->objects directly within the LINQ query above.

    I could also use the same Average() and Max() LINQ extension methods as before to calculate the average age of <person> elements within the XML file, as well as the maximum age like so:

    I do not have to manually parse the XML file.  Not only will XLINQ handle that for me, but it will parse the file using a low-level XMLReader and not have to create a DOM in order to evaluate the LINQ expression.  This means that it is lightening fast and doesn't allocate much memory.

    Scenario 3: Using LINQ Extension Methods Against a Database

    Let's assume we have a SQL database that contains a table called "People" that has the following database schema:

    I could use the new LINQ to SQL WYSIWYG ORM designer within Visual Studio to quickly create a "Person" class that maps to the database:

    I can then use the same LINQ Where() extension method I used previously with objects and XML to retrieve a sequence of strongly-typed "Person" objects from the database whose first name starts with the letter "S":

    Note how the query syntax is the same as with objects and XML. 

    I could then use the same LINQ Average() and Max() extension methods as before to retrieve the average and maximum age values from the database like so:

    You don't need to write any SQL code yourself to have the above code snippets work.  The LINQ to SQL object relational mapper provided with "Orcas" will handle retrieving, tracking and updating objects that map to your database schema and/or SPROCs.  You can simply use any LINQ extension method to filter and shape the results, and LINQ to SQL will execute the SQL code necessary to retrieve the data (note: the Average and Max extension methods above obviously don't return all the rows from the table - they instead use TSQL aggregate functions to compute the values in the database and just return a scalar result).

    Please watch this video I did in January to see how LINQ to SQL dramatically improves data productivity in "Orcas".  In the video you can also see the new LINQ to SQL WYSIWYG ORM designer in action, as well as see full intellisense provided in the code-editor when writing LINQ code against the data model.

    Summary

    Hopefully the above post gives you a basic understanding of how extension methods work, and some of the cool extensibility approaches you will be able to take with them.  As with any extensibility mechanism, I'd really caution about not going overboard creating new extension methods to begin with.  Just because you have a shiny new hammer doesn't mean that everything in the world has suddenly become a nail!  

    To get started trying out extension methods, I'd recommend first exploring the standard query operators provided within the System.Linq namespace in "Orcas".  These enable rich query support against any array, collection, XML stream, or relational database, and can dramatically improve your productivity when working with data.  I think you'll find they'll significantly reduce the amount of code you write within your applications, and allow you to write really clean and descriptive syntax.  They'll also enable you to get automatic intellisense and compile-time checking of query logic within your code.

    In the next few weeks I'll continue this series on new language features in "Orcas" and explore Anonymous Types and Type Inference, as well as talk more about Lambdas and other cool features.  I'll also obviously be talking a lot more about LINQ.

    Hope this helps,

    Scott

  • New C# "Orcas" Language Features: Automatic Properties, Object Initializers, and Collection Initializers

    Last week we shipped the March CTP of our Visual Studio and .NET Framework "Orcas" release.   It is available as a free download by anyone, and can be downloaded as as both a VPC (allowing you to run it in a virtual machine) as well as a standalone setup install (note: if you are running Vista you want to make sure you only use the VPC version).  You can download it here.

    A few weeks ago I blogged about some of the major improvements coming for ASP.NET developers with the "Orcas" release.  If you haven't already read this blog post, I highly recommend reading it here.  I think you'll really like the new features it covers.

    In addition to all the great new framework and tool features, one of the things that I think developers (of all .NET application types) will really love about Orcas are some of the new language features and improvements that are coming to both VB and C#.  These language changes are going to improve our development experience in both subtle and dramatic ways, and will really improve productivity and reduce the amount of code we need to type.

    Over the next few weeks I'm going to try and blog about several of these language improvements, and show how they can be used together to produce some really powerful results.

    New C# Language Feature: Automatic Properties

    If you are a C# developer today, you are probably quite used to writing classes with basic properties like the code-snippet below:

        public class Person {

            
    private string _firstName;
            private string 
    _lastName;
            private int 
    _age;
            
            public string 
    FirstName {

                
    get {
                    
    return _firstName;
                
    }
                
    set {
                    _firstName 
    = value;
                
    }
            }

            
    public string LastName {

                
    get {
                    
    return _lastName;
                
    }
                
    set {
                    _lastName 
    = value;
                
    }
            }        
            
            
    public int Age {

                
    get {
                    
    return _age;
                
    }
                
    set {
                    _age 
    = value;
                
    }
            }
        }

    Note about that we aren't actually adding any logic in the getters/setters of our properties - instead we just get/set the value directly to a field.  This begs the question - then why not just use fields instead of properties?  Well - there are a lot of downsides to exposing public fields. Two of the big problems are: 1) you can't easily databind against fields, and 2) if you expose public fields from your classes you can't later change them to properties (for example: to add validation logic to the setters) without recompiling any assemblies compiled against the old class. 

    The new C# compiler that ships in "Orcas" provides an elegant way to make your code more concise while still retaining the flexibility of properties using a new language feature called "automatic properties".  Automatic properties allow you to avoid having to manually declare a private field and write the get/set logic -- instead the compiler can automate creating the private field and the default get/set operations for you. 

    For example, using automatic properties I can now re-write the code above to just be:

        public class Person {
        
            
    public string FirstName {
                
    get; set;
            
    }

            
    public string LastName {
                
    get; set;
            
    }        
            
            
    public int Age {
                
    get; set;
            
    }
        }

    Or If I want to be really terse, I can collapse the whitespace even further like so:

        public class Person {
            
    public string FirstName { get; set; }
            
    public string LastName  { get; set; }        
            
    public int    Age       { get; set; }
        }

    When the C# "Orcas" compiler encounters an empty get/set property implementation like above, it will now automatically generate a private field for you within your class, and implement a public getter and setter property implementation to it.  The benefit of this is that from a type-contract perspective, the class looks exactly like it did with our first (more verbose) implementation above.  This means that -- unlike public fields -- I can in the future add validation logic within my property setter implementation without having to change any external component that references my class. 

    Bart De Smet has a great write-up on what happens under the covers when using automatic properties with the March CTP release of "Orcas".  You can read his excellent blog post on it here.

    New C# and VB Language Feature: Object Initializers

    Types within the .NET Framework rely heavily on the use of properties.  When instantiating and using new classes, it is very common to write code like below:

       Person person = new Person();
       
    person.FirstName "Scott";
       
    person.LastName "Guthrie";
       
    person.Age 32;

    Have you ever wanted to make this more concise (and maybe fit on one line)?  With the C# and VB "Orcas" compilers you can now take advantage of a great "syntactic sugar" language feature called "object Initializers" that allows you to-do this and re-write the above code like so:

      Person person = new Person { FirstName="Scott", LastName="Guthrie", Age=32 };

    The compiler will then automatically generate the appropriate property setter code that preserves the same semantic meaning as the previous (more verbose) code sample above.

    In addition to setting simple property values when initializing a type, the object initializer feature allows us to optionally set more complex nested property types.  For example, assume each Person type we defined above also has a property called "Address" of type "Address".  We could then write the below code to create a new "Person" object and set its properties like so:

       Person person = new Person {
          FirstName 
    "Scott",
          LastName 
    "Guthrie"
          
    Age 32,
          Address 
    = new Address {
             Street 
    "One Microsoft Way",
             City 
    "Redmond",
             State 
    "WA",
             Zip 
    98052
          
    }
       }
    ;

    Bart De Smet again has a great write-up on what happens under the covers when using object initializers with the March CTP release of "Orcas". You can read his excellent post on it here.

    New C# and VB Language Feature: Collection Initializers

    Object Initializers are great, and make it much easier to concisely add objects to collections.  For example, if I wanted to add three people to a generics-based List collection of type "Person", I could write the below code:

      List<Person> people = new List<Person>();
                
      
    people.Add( new Person { FirstName "Scott", LastName "Guthrie", Age 32 } );
      
    people.Add( new Person { FirstName "Bill", LastName "Gates", Age 50 } );
      
    people.Add( new Person { FirstName "Susanne", LastName "Guthrie", Age 32 } );
     

    Using the new Object Initializer feature alone saved 12 extra lines of code with this sample versus what I'd need to type with the C# 2.0 compiler.

    The C# and VB "Orcas" compilers allow us to go even further, though, and also now support "collection initializers" that allow us to avoid having multiple Add statements, and save even further keystrokes:

       List<Person> people = new List<Person> {
          
    new Person { FirstName "Scott", LastName "Guthrie", Age 32 },
          
    new Person { FirstName "Bill", LastName "Gates", Age 50 },
          
    new Person { FirstName "Susanne", LastName "Guthrie", Age 32 }
       }
    ;

    When the compiler encounters the above syntax, it will automatically generate the collection insert code like the previous sample for us.

    Summary:

    As developers we now have a much more concise way to define objects, initialize them, and add them to collections.  At runtime, the semantics will be exactly the same as with today's longer syntax (so you don't need to worry about behavior changes).  But now you don't need to type as much, and your code can be more crisp and concise.

    In the near future I'll do additional blog posts that examine even more "Orcas" language improvements including Extension Methods, Lambdas, and Anonymous Types.  I'll then do a deep dive into LINQ, and show how it takes advantage of all of these features to provide a really elegant way to query and interact with data.

    Hope this helps,

    Scott

  • MetaBlog into a Local Directory

    Microsoft Word 2007 produces relatively clean HTML when you use the Publish feature to create a blog post. Although the XHTML purist will still be unhappy with anything they don't write themselves, the HTML far surpasses anything we've seen from Word in previous versions. Unfortunately, this feature is only available for blog posting, as far as I can tell. The "Web Page" and "Web Page, Filtered" options in the "Save As" menu still produce the same .mso littered HTML that makes Word impossible to use as a serious HTML editor. I'd like to use the HTML output by the Publish feature for purposes other than blogging.

    I wasn't sure how to get to this Publish feature, but after looking at the MetaBlog API that Word can consume, I decided it wouldn't be too hard to write something in ASP.NET that would run on localhost and give me exactly what I wanted from Word. Specifically – convert a document into clean HTML and PNG graphics and drop the files into a local directory. I decided this job was even easier when I snooped around the SubText subversion repository and discovered that Cook Computing's XML-RPC library does all the heavy lifting and XML parsing.

    It took a bit of debugging, but the IMetaWeblog interface defined in the XML-RPC library (interfaces\MetaWeblogAPI.cs) needs a few tweaks to work with Word. First, Word invokes a blogger.getUserBlogs method that isn't defined in the interface, but is easy to add:

    [XmlRpcMethod("blogger.getUsersBlogs", Description = "...")]
    BlogInfo[] getUsersBlogs(string blogid, string username, string password);

     

    Secondly, Word appear to pass an integer for the blogid parameter of the newMediaObject method. The service expects a string. I don't know enough about the history of the MetaBlog API to know who is wrong in this scenario, but it's easy to fix the method definition in the interface.

    [XmlRpcMethod("metaWeblog.newMediaObject",
    Description =
    "Makes a new file to a designated blog using the "
                  + "metaWeblog API. Returns url as a string of a struct.")]
    MediaObjectInfo newMediaObject(
          
    int blogid, // this was a string, but that doesn't work with Word...
          string username, string password, FileData file);

     

    One last change is to Refactor -> Rename the UrlInfo struct in MetaWeblogAPI.cs to MediaObjectInfo. The rename allows Word and the MetaBlog service to agree on the name of the struct.

    public struct MediaObjectInfo // this used to be called UrlInfo
    {
        
    public string url;
    }

     

    Once all this is done it's a simple matter to implement that interface in an HttpHandler (ashx file).

    public class MetaWebLogging : XmlRpcService, IMetaWeblog
    {
    // ...
    }

     

    Each method needs an implementation. For my workflow, I'm moving files around on the hard drive, but here is a sample implementation for the newPost method that will dump the incoming HTML into a file in the root directory of the application.

    public string newPost(string blogid, string username, string password,
                          
    Post post, bool publish)
    {
        
    string fileName = Path.Combine(
                            
    HttpContext.Current.Server.MapPath("~"),
                            post.title +
    ".htm");
        
        
    using (FileStream fs = File.OpenWrite(fileName))
        
    using (StreamWriter writer = new StreamWriter(fs))
        {
                writer.Write(post.description);
        }

        
    return Path.GetFileName(fileName);
    }

     

    Now I just point Word 2007's Publish feature to my local metablog.ashx file and export documents as HTML. For what I needed to do, this little hack was a huge time saver. Hopefully, future versions of Word will make this even easier.

  • Update for the Visual Studio Items Sorting Script

    Alexander Groß has a sharp looking blog, and he posted an enhanced version of my sort-vsItems PowerShell script. The update is highly recommended, particularly if you have WinFX templates installed. See his post: "Sorting Visual Studio's 'Add New Item' Dialog"

    Alexander also has an RDP/Terminal Service Port Configurator for Windows Mobile. I've been frustrated by the fact that the mobile remote desktop client doesn't understand the servername:port syntax, but this utility is a good workaround.

  • Three New "Working with Data in ASP.NET 2.0" Tutorials Now Available

    My Working with Data in ASP.NET 2.0 tutorials have been updated to include the three newest tutorials, which look at enhancing the GridView control's functionality:

    • Adding a GridView Column of Radio Buttons [VB | C#]
    • Adding a GridView Column of Checkboxes [VB | C#]
    • Inserting a New Record from the GridView's Footer [VB | C#]

    Like the previous tutorials in the series, all tutorials are available in C# and VB, include the complete code download as a self-extracting ZIP, and are available in PDF format.

    There are more tutorials to be released in the upcoming weeks. Next on the docket are four tutorials on working with binary data.

  • Video of Scott Guthrie Shooting Private Donut (and some good ASP.NET AJAX links)

    Occasionally I get to do cool non-traditional things as part of my job.  Two weeks ago, I was the guest star in a fun "Red vs. Blue" Halo video produced by Rooster Teeth.  You can watch it online here (it is 3 minutes in length).

    Below is a screen-shot of me in the movie, right after I shoot "Private Donut" the first time (you will have to watch the video to understand).

     

    I also spend some time in the video trying to explain to the "reds" what ASP.NET AJAX can offer them. <g>

    ASP.NET AJAX Toolkit Update Released

    In other ASP.NET AJAX news, the ASP.NET AJAX Control Toolkit team last week shipped an update to the ASP.NET AJAX Control Toolkit (which is a free, shared source library, containing 34+ ASP.NET AJAX Controls that are built by both Microsoft and non-Microsoft developers).  This ASP.NET AJAX Control Toolkit update contains a bunch of great new updates:

    • JavaScript comment/whitespace stripping - When compiled in "Release" mode, all of the JavaScript files in the Toolkit now automatically have all comments and unnecessary whitespace removed.  This can reduce the download size of the scripts by over 50%. This is implemented as an automated MSBuild task that you can take and use within your own ASP.NET AJAX projects to streamline your custom JavaScript sizes as well (I'll blog about how to use the MSBuild task in the next few days).
    • Localization support - The Toolkit now has an infrastructure for localizing the text in JavaScript files using the standard ASP.NET AJAX support for resource files. There are placeholder files for the following 14 languages: Arabic, German, English, Spanish, French, Hebrew, Hindi, Italian, Japanese, Korean, Portuguese, Russian, Chinese (Simplified), and Chinese (Traditional).
    • ASP.NET Theme/Skin support - You can now use ASP.NET's theme/skin support to specify properties for Toolkit controls across an entire web site in one central location.

    You can try out and download the ASP.NET AJAX Control Toolkit online here.

    Free Microsoft Learning Course: Developing Enhanced Web Experiences with Microsoft ASP.NET AJAX Extensions

    Microsoft Learning has published a free premium online clinic that provides a great way to learn how to use ASP.NET AJAX.  It can be watched for free and covers AJAX concepts and how to use ASP.NET AJAX end-to-end (it is 2 hours long).  You can watch the course online here.

    More ASP.NET AJAX "How Do I?" Videos

    Joe Stagner has been busy creating more ASP.NET AJAX "How Do I?" videos (I first blogged about this series in this blog post from last month).  He published three new videos last week:

    For more of Joe's ASP.NET AJAX videos, please check out the ASP.NET AJAX videos section on www.asp.net.

    Damian Mehers (who implemented the ListSearch ASP.NET AJAX Control Toolkit control above) has also published a cool video on ASP.NET AJAX and the ASP.NET AJAX Control Toolkit that you can watch here.

    ASP.NET AJAX Downloads and Deployments

    In the first 6 weeks since ASP.NET AJAX 1.0 was released, we've already had several hundred thousand downloads of the final V1.0 release.  Last week we got back the results from a recent web crawler study on the Internet that found over 60,000 unique Internet sites that had already deployed sites using the final ASP.NET AJAX V1.0 bits within the first month.  Click here to see screen-shots of some of these sites, and read interviews with the developers who built them.

    Hope this helps,

    Scott

  • Tip/Trick: Integrating ASP.NET Security with Classic ASP and Non-ASP.NET URLs

    One of the questions I am often asked is "How can I integrate ASP.NET security with Classic ASP other non-ASP.NET URLs?".  Specifically, people want to know if they can integrate ASP.NET's Forms Authentication, Role Based Security, and URL Authorization features with Classic ASP, PHP, JSP, .HTM, .JPG and other non-ASP.NET URLs.

    The good news is that this is pretty easy with ASP.NET 2.0 and IIS 6.0 today, and will get even easier in the IIS 7.0 timeframe.  The below blog post demonstrates how to integrate ASP.NET 2.0's Forms Authentication and Login/Membership features with classic ASP and static .HTML files. 

    For a much more detailed walkthrough of how to achieve this (as well as how to integrate features like ASP.NET role based authorization with classic ASP applications), please read Chapter 6 of Stefan Schackow's excellent ASP.NET 2.0 Security, Membership, and Role Management book.

    Some Background on IIS 6.0 Wildcard Mappings

    IIS 6.0 with Windows Server 2003 added support for an ISAPI feature called "wildcard mappings".  Wildcard mappings provide a way to configure IIS to cause all requests coming into the server to first be routed to one or more ISAPI extensions for processing.  What is cool about wildcard mappings in IIS 6.0 is that after the ISAPI extension that is processing the wildcard extension is finished, it can then cause IIS to pass control of the request to the extension or internal handler within IIS that normally would process the request.

    ASP.NET 2.0 includes built-in support to take advantage of this wildcard mapping feature.  This enables you to run ASP.NET code (or your own custom code) before and after the existing ISAPI extension that processes a non-ASP.NET URL (for example: a .asp, .php or .htm request) executes.

    We can use this feature to enable a bunch of cool integration features - including using ASP.NET authentication and authorization features to secure all URLs on a web-server. 

    How to Configure an IIS 6.0 Wildcard Mapping

    For this sample I've created a new IIS application within the IIS 6.0 admin tool called "wildcardtest".  It points to a directory that will contain a few files: "default.aspx", "login.aspx", "test.asp" and "test.htm" (these last two files being resources not usually handled by ASP.NET):

    By default when a URL request for a .aspx page comes to the application, the ASP.NET ISAPI will process the request.  By default when a URL request for test.asp comes to the application, the classic ASP ISAPI will process the request - and no ASP.NET code will run.  When a URL request for test.htm comes to the application, IIS6 will process the request internally - and again no ASP.NET code will ever run.

    We'll change this by enabling wildcard mappings for this application, and configure ASP.NET to run code before and after all requests to the server.  To-do this, right-click on the application within the IIS Admin Tool and select the "properties" context menu item on it.  This will bring up the application properties dialog:

    You can then click the "configuration" button to pull up the URL mapping rules for the application:

    Note how the top of this dialog lists the default ISAPI extension mappings (each URL extension is mapped to an ISAPI responsible for processing it).  The bottom half of the dialog lists the "wildcard application map" rules.  We can add a application wildcard mapping to the ASP.NET ISAPI by clicking the "insert" button, and pointing at the ASP.NET 2.0 ISAPI extension on disk:

    Very, Very Important: Make sure that you uncheck the "Verify this file exists" checkbox.  If you don't do this ASP.NET URL resources like WebResource.axd and other URL's handled by ASP.NET that aren't backed by a physical file won't work anymore.  This will lead to errors within your pages.

    Now close out all of the dialogs by clicking "ok" to accept the changes.  You've now configured ASP.NET to be able to run code before and after each URL request into the application.

    Enabling Forms Authentication and Url Authorization for non-ASP.NET resources

    Once we've completed the above steps to register ASP.NET 2.0 as a wild-card mapping for all URLs into our IIS application, we can then use the standard ASP.NET authentication and authorization techniques to identify users in our application and grant/deny them access to it.

    For example, we could add a web.config file to our application that enables ASP.NET's forms authentication feature for this application, and sets up two URL Authorization rules that deny "anonymous" users access to both the test.asp and test.htm URLs:

    <?xml version="1.0"?>

    <configuration>

        
    <system.web>
            
    <authentication mode="Forms" />
        </
    system.web>

        
    <location path="test.asp">

            
    <system.web>
                
    <authorization>
                    
    <deny users="?"/>
                    <
    allow users="*"/>
                </
    authorization>
            
    </system.web>
            
        
    </location>

        
    <location path="test.htm">

            
    <system.web>
                
    <authorization>
                    
    <deny users="?"/>
                    <
    allow users="*"/>
                </
    authorization>
            
    </system.web>
            
        
    </location>

    </configuration>

    Now, when I attempt to access either "test.asp" or "test.htm", the ASP.NET authentication and authorization system will execute first to check whether I'm logged into the application with forms-authentication, and if not redirect me to the login.aspx page within my application for me to login:

    Note how the "ReturnUrl" used by ASP.NET's forms authentication system above has automatically set the "test.asp" url to redirect back to once I'm logged in (this works just like it would for a .aspx page).  Once I successfully enter a username/password, I'll then have access to the test.asp page:

    Since the above page is a classic ASP file, I obviously don't have a "User.Identity.Name" property that I can use to identify the logged in user like I would in an ASP.NET page.  However, I can retrieve the "AUTH_USER" ServerVariable value within classic ASP to obtain the username (ASP.NET automatically populates this before delegating the processing back to the classic ASP ISAPI). 

    The code to use this from within classic ASP would look like below:

    <html>
        
    <body>
            
    <h1>Classic ASP Page</h1>

            
    <h3>
                You are logged in as: 
                
    <u>
                    
    <%=Request.ServerVariables("AUTH_USER") %>
                
    </u>        
            
    </h3>
        
    </body>
    </html>

    Click here to download a complete sample application that implements the above solution.  By default it will use a SQL Express database to store ASP.NET 2.0's Membership and Role Management data.  Alternatively, you can create and register a SQL 2000 or SQL 2005 database to store the membership and role management values.  This older ASP.NET Security tutorial I did shows how to-do this.

    How to Learn More about ASP.NET Security

    I highly recommend buying a copy of Stefan Schackow's excellent ASP.NET 2.0 Security, Membership, and Role Management book.  Stefan is a key member of the ASP.NET team, and owned and designed the security features in the ASP.NET 2.0 release.  As such, he really, really, really knows what he is writing about. 

    Chapter 6 of his book is titled "Integrating ASP.NET Security with Classic ASP" and contains much more detail about the solution I demonstrated above (as well as how to use role security with it, and pass data back and forth between ASP.NET and classic ASP). 

     

    Click here to learn more about the book and/or buy it online.

    Other Online ASP.NET Security Resources

    I've published a number of ASP.NET Tips, Tricks, Recipes and Tutorials in the past that cover ASP.NET 2.0 security.  Below is a short-list of them that you might want to review:

    For more free ASP.NET Tips, Tricks, and Tutorials I've written, please check out my ASP.NET Tips, Tricks and Tutorials listing.

    Hope this helps,

    Scott

  • Atlanta Cutting Edge .NET User Group Meeting

    The Atlanta Cutting Edge .NET User Group is meeting Monday, March 5, 2007, at 6:00pm in the Microsoft offices in Alpharetta.  Paul Lockwood will be talking about advanced production debugging and Eric Engler will be talking about the ASP.NET AJAX framework.  Eric promises it will be about much more than the UpdatePanel, which seems to be the extent of most such talks.
  • iWoz by Steve Wozniak

    I bought and read this book right around the time it came out, but I am just now getting around to blogging about it. I always read an auto-biography expecting a biography... and I am always disappointed. When looking at your own life I think it is hard to remember it in a linear fashion, most of the auto-biographies I have read jump around way too much. iWoz isn't really even an auto-biography, it's like one really long rambling interview. Steve doesn't always come across well, a comment said after a couple beers with a big smile can come across completely different when set in type. I think this makes him seem more conceited than he actually is (of course I have never met the guy so I am just hoping this is the case).

    There are plenty of interesting things in the book. I found the pre-apple and early-apple stories the most interesting, the parts after apple was successfully are much less interesting. (the love festival thing, etc) I think the real failure of this book is the format. Apparently the book was written through multiple interviews and thrown together as a book. It doesn't flow very well, the writing style is very conversational, and it doesn't probe into the most interesting areas. Someday a real biographer will tackle some of the tech pioneers and we will get the real story.

    -James

  • Books: Casino Royale by Ian Fleming

    Awhile back I was wandering around Barnes and Noble after eating a great dinner at Mitchell's Fish Market and I noticed that Penguin had released a new edition of all of the Ian Fleming bond novels.

    I have always wanted to read some of the original bond books so I grabbed Casino Royale since I always like to start at the beginning. I also haven't seen the movie yet, and whenever possible I like to read the book before the movie. I enjoyed the book, the Ian Fleming Bond is very different from the Bond you normally see in the movies. He is a little more chauvanistic and rude, and I don't think you would ever see a Bond movie where Bond gets tortured the way he is tortured in the book. I can see some similarities between Fleming and Raymon Chandler, especially in the disposition of the protagonist. I enjoy Chandler's writing style a little better than Fleming, but they are both great authors who have great characters.

    I have about a 4 foot stack of books to read next, but after some of those I am going to pick up Live and Let Die, the next Bond book in the series.

    -James

  • Free SQL Server Training Videos (and other good data tutorial pointers)

    Today on the www.asp.net site we posted a great new "How Do I?" video series focused on SQL Server 2005 Express (which you can download and use completely for free). 

    The series features 13 professional videos that start at the very beginning and then explore designing tables/schemas, using data types, creating SPROCs, using reporting services and the business intelligence engine, enabling full text search across your data, and more (I'm guessing even most devs with a lot of data experience might learn some new things from the reporting services and full text search videos):

    You can download or watch the the SQL Training videos online for free here.

    In case you missed my posts on uploading a SQL Express or SQL Server Database into a remote hosting environment, I also highly recommend going back and reading these two posts:

    Earlier this summer I also posted a popular blog post topic that provides 100s of sample database schemas you can download and use within your applications:

    And finally (and perhaps most importantly), make sure to check out Scott Mitchell's awesome ASP.NET Data Tutorials here (there are more than 50 fantastic tutorials all in VB and C# for common data scenarios in ASP.NET):

    Hope this helps,

    Scott

This Blog

Syndication

Powered by Community Server, by Telligent Systems
'