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.

November 2006 - Posts

  • Win a Visual Studio 2005 Team Suite with MSDN Premium Subscription

    In celebration of my solitary post this month, I'm giving away two Visual Studio 2005 Team Suite with MSDN Premium subscriptions. Microsoft gave me these subscriptions to give to the community, and I'd like to find some deserving candidates.

    To win a subscription, send me an interesting application or some cool code you've written that uses a .NET 3.0 technology (WF, WPF, or WCF), or uses ASP.NET AJAX 1.0 Beta 2. I'll pick one winner from the .NET 3.0 category and one winner from the AJAX category. I'll be posting the code from 6 or more of the entries here on the site. You have to own the code and be willing to have it featured here in a post. We can all learn something from the contest.

    Send submissions to contest @ odetocode.com before midnight on December 15th (GMT -5). I'll announce the winners on December 20th. Winners must activate their subscriptions before December 29.

  • Tip/Trick: Use the ASP.NET 2.0 CSS Control Adapters for CSS friendly HTML output

    Tired of having html <table> elements rendered by the built-in ASP.NET server controls and wishing you could use a pure CSS solution instead?  If so, read on...

    Last week we released Version 1.0 of the ASP.NET 2.0 CSS Control Adapters.  These adapters take advantage of a new extensibility feature in ASP.NET 2.0 that we call the "Control Adapter Architecture", and which enables developers to override, modify and/or tweak the rendering output logic of an existing server control (without changing any of its properties, supported events, or programming model).

    The ASP.NET 2.0 CSS Control Adapters that we released last week provide pre-built control adapters for 11 of the most common ASP.NET controls (GridView, DetailsView, FormsView, DataList, Menu, TreeView, Login, LoginStatus, CreateUserWizard, ChangePassword and PasswordRecovery).  The CSS Control Adapters cause these ASP.NET controls to emit CSS friendly html output (eliminating things like inline styles and <table> elements), and can significantly help when using CSS on your web-site.

    Click any of the links below to see a before/after example of how they change the markup generated by these built-in ASP.NET controls:

    The CSS Control Adapter toolkit includes both VB and C# source code for all of the above control adapters. You can use the source-code as-is (without having to modify anything) to get pure CSS output.  Or if you want to tweak the output even further you can go in and modify the adapters to emit any custom markup you want:

    I posted a nice tutorial two months ago that walksthrough how you can use the CSS Control Adapters that I highly recommend reading to learn how to get started. 

    Scott Mitchell earlier today also posted a nice CSS Control Adapters article on www.4guysfromrolla.com that covers how to use them as well. 

    You can ask questions and get help on how to use them on the CSS Control Adapters Forum on http://www.asp.net.

    Hope this helps,

    Scott

    P.S. I'd like to pass along a special big thanks to Russ and Heidi for all of their awesome work in building these CSS Control Adapters and samples!

    P.P.S. For additional ASP.NET Tips/Tricks blog posts of mine, please review my ASP.NET Tips, Tricks and Resources page.

  • Extending the ASP.NET 2.0 Localization Model with a Database Resource Provider

    Earlier this spring, Michèle Leroux Bustamante wrote a great article for MSDN: ASP.NET 2.0 Localization Features: A Fresh Approach to Localizing Web Applications.  It covers the basics of how to use the new localization features available within ASP.NET 2.0 to build localized, culture-aware, web applications.

    To watch how to quickly apply these localization techniques, I'd also highly recommend checking out this free 13 minute video: How do I: Create a Multi-Lingual Site with Localization?  It is part of the excellent ASP.NET 2.0 How Do I video series and demonstrates step-by-step how to build and localize an ASP.NET application from scratch (as well as how to dynamically select the language to use both via a client's incoming user-agent string as well as by giving a user an explicit choice via a drop-down list). 

    One of the common questions that people have asked for over the last few months is better documentation on how to store localized resource strings in resource providers other than the default XML-based RESX solution that ships built-in with ASP.NET 2.0 and VS 2005.  Last month Michelle published another great article on MSDN: Extending the ASP.NET 2.0 Resource-Provider Model.  This article focuses on features that enable developers to retrieve resources from alternate storage locations and integrate with page parsing, compilation, and run-time execution. Included within this article are details and sample code that demonstrate how to use a database to store localized resource content.

    Michelle is going to be publishing two more articles in the localization series in the future that will include how to integrate resource providers further with VS 2005, as well as how to handle complex resource hierarchies. 

    Hope this helps,

    Scott

  • ASP.NET 2.0 Web Parts in Action by Darren Neimke

    I highly recommend the book ASP.NET 2.0 Web Parts in Action by Darren Neimke (Manning Publications).  This book assumes you are already experienced with ASP.NET, so it doesn't waste your time with yet another introduction.  Instead, everything in this book is just good content about Web Parts and the Portal Framework, a lot of which is hard to find anywhere else.  This book does not just show you how to build a Web Part based Portal, it will also teach you how to customize most every aspect of the process.  You'll learn about the Manager control, Connections, and Personalization, but also about changing the look of the Chrome that all Web Parts automatically get.  So if you are an experienced ASP.NET developer that is needing to learn about Web Parts, then this is a must-have book -- there's nothing else like it.
  • Books: The Long Tail by Chris Anderson

    I am getting really behind on posting book posts (I have about five more books to post about), but then again I am getting behind on posting in general.

    I picked up this book based on the stellar reviews I kept reading on blogs and based on the initial article by Chris Anderson that coined the term “The Long Tail”. I was not disappointed. I half expected the book to cover the initial idea and then expound on how your business can take advantage of it for the next 200 pages. Instead this book is more of an economics book, examining the business models of Amazon, Rhapsody, Netflix, and others and how they have exploited the long tail evolution.

    One thing I find interesting is that all of these companies who share the focus of the book really only take advantage of the first part of the long tail, there is a much longer tail that continues past the most obscure book or song available from Amazon, Rhapsody, or Netflix. I think the next revolution will be in these areas. Netflix may stock 65,000 DVDs, but that neglects all the user-created (youtube, etc) content, or the content in the public domain, or the 50 years of archived TV footage. For every song on Rhapsody there are probably 100 more around from un-signed artists or live performances. I think this is where the future of The Long Tail is going, and while these original companies will thrive for the next 5 years they better wake up to the rest of the tail if they want to survive. Mr. Anderson calls the first type of company (Amazon, Netflix, etc) a Hybrid retailer because it can stock much more than a Target or Sam Goody but it can’t compete with what he calls the Pure Digital Retailers who have no limit to what they can offer.

    If you haven’t already be sure and subscribe to Anderson’s blog.

    -James

  • Cincinnati-Dayton Code Camp 2007

    Last year’s code camp was a blast, so we decided to do it again! This time around it will be on Saturday, March 24th. The location is the same as last year, the Wingate Inn in West Chester.

    Interested in speaking? Fill out a form and send it our way! Talks on .NET, Java, Ruby, Python, etc will all be considered.

    Register quickly! Last year we booked up early.

    -James

  • CodeMash is going to rock

    If you are anywhere near Ohio (and I mean like within 8 hours drive) you should seriously consider getting to this conference. There are going to be some incredible speakers like Scott Guthrie, Neal Ford, and Bruce Eckel. I am still trying to decide what talk to submit, I am debating between the Ajax applied talk I recently did at Cinnug or perhaps a new talk on agile practices.

    And I guarantee if you mention you read my blog I will buy you at least one beer (if not more) or a shot of tequila, depending on how late it is.

    -James

  • Tip/Trick: Implement "Donut Caching" with the ASP.NET 2.0 Output Cache Substitution Feature

    Some Background:

    One of the most powerful, yet too often under-used, feature areas of ASP.NET is its rich caching infrastructure.  ASP.NET's caching features enable you to avoid repeating work on the server for each new request received from clients.  Instead, you can generate either html content or data structures once, and then cache/store the results within ASP.NET on the server and re-use them for later web requests.  This can dramatically improve performance for your applications, and lower the load on critical backend resources like databases.

    Steve Smith wrote a good ASP.NET 1.1 caching article on MSDN a few years ago that covers some of the basics of the ASP.NET 1.1 caching features and provides a good summary of how to use them.  If you haven't used ASP.NET caching before, I'd recommend checking it out and giving each feature a try.

    ASP.NET 2.0 has added two very important improvements to the caching feature set:

    1) SQL Cache Invalidation Support - This enables you to automatically invalidate/re-generate a cached page or data structure when a database table or row it depends on is updated.  For example, you can now output cache all of your product listing pages within an e-commerce site - and make sure that anytime that their prices change in the database the pages are immediately re-generated on the next request (and do not show stale pricing data to users). 

    2) Output Cache Substitution - This nifty feature enables you to implement what I sometimes call "donut caching" -- where you output cache everything on a page except for a few dynamic regions that are contained within cached regions.  This enables you to implement full page output caching more aggressively, and not have to split your pages into multiple .ascx user control files to order to implement partial page caching.  The below tip/trick tutorial explains the motivation and implementation of this feature better.

    Real-World Scenario:

    You want to implement a product listing page within your site that lists all products within a given product category.  You want to output cache this page so that you don't have to hit the database on each request.  You can easily accomplish this by declaratively adding an <%@ OutputCache %> directive to the top of a Products.aspx page that contains an <asp:datalist> control which is databound to product data returned from your middle-tier.

    Note below how the page is configured to output cache its contents for 100,000 seconds or until the northwind's products table is updated with new pricing data (in which case it will immediately regenerate the page on the next request).  The OutputCache directive also has a "VaryByParam" attribute that tells ASP.NET to store a separate cached version of the page for each unique categoryID (for example: a separate page for Products.aspx?categoryId=1, Products.aspx?categoryId=2, etc). 

    Products.aspx:

    <%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="Products.aspx.vb" Inherits="Products" %>
    <%@ OutputCache Duration="100000" VaryByParam="CategoryID" SqlDependency="northwind:products" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

    <div class="catalogue">

        
    <asp:DataList ID="DataList1" RepeatColumns="2" runat="server">
            
    <ItemTemplate>
            
                
    <div class="productimage">
                    
    <img src="images/productimage.gif" />
                </
    div>
            
                
    <div class="productdetails">
                
                    
    <div class="ProductListHead">
                        
    <%#Eval("ProductName")%>
                    
    </div>
                    
                    
    <span class="ProductListItem">
                        
    <strong>Price:</strong>
                        
    <%# Eval("UnitPrice", "{0:c}") %>
                    
    </span>
                    
                
    </div>
            
            
    </ItemTemplate>
        
    </asp:DataList>
        
        
    <h3>Generated @ <%=Now.ToLongTimeString()%></h3>

    </div>

    </asp:Content>

    Products.aspx.vb:

    Partial Class Products
        
    Inherits System.Web.UI.Page

        
    Sub Page_Load(ByVal sender As ObjectByVal As System.EventArgs) Handles Me.Load

            
    Dim products As New NorthwindTableAdapters.ProductsTableAdapter

            DataList1.DataSource 
    products.GetProductsByCategoryID(Request.QueryString("categoryId"))
            DataList1.DataBind()

        
    End Sub

    End Class

    When accessed by a browser, the below page is returned from the server:

    Note that the timestamp at the bottom of the page will only be updated every 100,000 seconds or if the pricing data in the products table has been updated.  It will be cached for all the other HTTP requests - allowing us to process 1000s of requests per second on a production server and avoid ever having to hit the database (making things super fast).

    Problem:

    The one problem we are going to encounter in the above example is with the welcome message and username we output at the top-right of the page (circled in red above).  This is currently being generated within our Site.Master master-page file using the new ASP.NET 2.0 <asp:loginname> control like so:

    <div class="header">
        
    <h1>Caching Samples</h1>
                
        
    <div class="loginstatus">
            
    <asp:LoginName FormatString="Welcome {0}!" runat="server" />
        </
    div>        
    </div>

    The problem we are going to run into is that because we've added full-page output caching to our page, the username of the first user to hit the site is going to be saved in the cached output from the page - which means that by default the users who hit the site in the 100,000 seconds after that initial request are going to receive back an incorrect welcome message (and worse - an incorrect name!).

    Solution:

    There are two ways to solve this problem. 

    The first solution would be to have the overall page be dynamic (so remove the top-level <%@ OutputCache %> directive), and refactor the page contents so that all of the "cacheable" content is encapsulated within ASP.NET User Controls (which are implemented in .ascx files).  You'd then add <%@ OutputCache %> directives at the top of each of these .ascx user control files to make them separately cacheable.  This avoids you having to hit the database on each request, and ensures that the username is always correctly output (since it is not within a cached user control region).  This approach works today with ASP.NET 1.1 and of course can still be done with ASP.NET 2.0.

    The downside with this first solution, though, is that it requires us to refactor our code and layout within the page in order to make caching work.  If we have only a few places within the page that we want to keep dynamic, this refactoring can be really inconvenient.  The good news is that ASP.NET 2.0 has added support for Output Cache Substitution block support that provide a much cleaner way to handle this scenario.

    Output Cache Substitution Blocks using the <asp:substitution> control:

    Output Cache Substitution blocks enable you to OutputCache an entire page's output -- while leaving a few dynamic region markers to indicate places in the HTML output where you want to dynamically "fill-in" content on later requests (for example: the username message in our sample above).  I sometimes call this the "donut caching feature" - since the outer content of a page is all cached, with only a few holes in the middle of the content stream that are dynamic.  This is the exact opposite of using user controls with partial page caching - since in the partial page caching case the overall page is dynamic, with cached regions in the middle. 

    You implement output cache substitution by output caching a page using full page output caching (exactly the same syntax as the Products.aspx code sample above).  You can then indicate regions of the page that you want to dynamically fill-in using substitution blocks by adding <asp:substitution> controls to the page like so:

    <div class="header">
        
    <h1>Caching Samples</h1>
        
        
    <div class="loginstatus">
            
    <asp:Substitution ID="Substitution1" runat="server" MethodName="LoginText" />
        </
    div>
    </div>

    The <asp:Substitution> control is unlike any other control in ASP.NET.  It registers a callback event with the ASP.NET output-cache that will cause a static method on your page or masterpage to be invoked when the page content is served out on subsequent requests from the ASP.NET Output Cache.  This static method will be passed an HttpContext object at runtime that contains the standard ASP.NET Request, Response, User, Server, Session, Application intrinsics, and which you can then use to return a string that ASP.NET will automatically inject into that region of the page before the content is sent back to the client. 

    For example, to handle the scenario above where we want to dynamically output a welcome message into the output-cached products.aspx page we'd simply add this method to our Site.Master code-behind file and have it be invoked by the <asp:substitution> control above:

    Partial Class Site
        
    Inherits System.Web.UI.MasterPage

        
    Shared Function LoginText(ByVal Context As HttpContext) As String
            Return 
    "Hello " & Context.User.Identity.Name
        
    End Function

    End Class

    Now the entire page will be output cached, except for the contents of the <asp:substitution> control representing the welcome message on the top-right of our page. 

    We could obviously extend this further if we wanted to include additional personalized information like how many items the user had within their shopping cart, etc.  The cool thing is that all other content on the page remains fully cached - and we never have to hit the products database in order to generate it on cached requests (meaning we can process thousands of product pages a second on a single server).  In fact, no controls on the page are created during the request, and no code other than the static method above ever runs on later requests - making everything super fast. 

    Output Cache Substitution Blocks using the Response.WriteSubstitution method:

    In addition to using <asp:substitution> controls to indicate replaceable substitution blocks on a page, you can alternatively use the Response.WriteSubstitution method instead.  This method takes as a parameter a delegate object to a HttpResponseSubstitutionCallback method that you can implement on any class within your application (it is not limited to only going against static methods on your code-behind class). 

    The <asp:substitution> control internally uses this method to wire-up delegates in the code-behind classes of pages.  You can likewise use it within your own controls or pages for maximum control and flexibility.

    Conclusion:

    I have yet to find a single ASP.NET application that could not benefit from using the ASP.NET caching features.  Because ASP.NET supports full page output caching, partial page output caching, and now donut-level caching - and allows you to vary the cached content based on any parameter or custom logic you want, and now allows you to automatically invalidate/re-generate the cached contents when a database changes, you shouldn't find yourself ever building an application that can't use caching to at least some degree. 

    I definitely recommend spending time checking all of the ASP.NET caching features out.  To find some more caching samples I've done, please download my Tips/Tricks talk from the recent ASP.NET Connections event.  Within that presentation I include slides+samples that show how to use full-page caching, partial page caching, substitution block caching, and SQL Cache Invalidation.

    Hope this helps,

    Scott

  • Tip/Trick: How to Register User Controls and Custom Controls in Web.config

    I've been including this technique in my ASP.NET Tips/Tricks talks the last year, but given how many people are always surprised by its existence I thought it was worth a dedicated tip/trick post to raise the visibility of it (click here to read other posts in my ASP.NET Tips/Tricks series).

    Problem:

    In previous versions of ASP.NET developers imported and used both custom server controls and user controls on a page by adding <%@ Register %> directives to the top of pages like so:

    <%@ Register TagPrefix="scott" TagName="header" Src="Controls/Header.ascx" %>
    <%@ Register TagPrefix="scott" TagName="footer" Src="Controls/Footer.ascx" %>
    <%@ Register TagPrefix="ControlVendor" Assembly="ControlVendor" %>

    <html>
    <body>
        
    <form id="form1" runat="server">
            
    <scott:header ID="MyHeader" runat="server" />
        </
    form>
    </body>
    </html>

    Note that the first two register directives above are for user-controls (implemented in .ascx files), while the last is for a custom control compiled into an assembly .dll file.  Once registered developers could then declare these controls anywhere on the page using the tagprefix and tagnames configured.

    This works fine, but can be a pain to manage when you want to have controls used across lots of pages within your site (especially if you ever move your .ascx files and need to update all of the registration declarations.

    Solution:

    ASP.NET 2.0 makes control declarations much cleaner and easier to manage. Instead of duplicating them on all your pages, just declare them once within the new pages->controls section with the web.config file of your application:

    <?xml version="1.0"?>

    <configuration>

      
    <system.web>
        
        
    <pages>
          
    <controls>
            
    <add tagPrefix="scottgu" src="~/Controls/Header.ascx" tagName="header"/>
            <
    add tagPrefix="scottgu" src="~/Controls/Footer.ascx" tagName="footer"/>
            <
    add tagPrefix="ControlVendor" assembly="ControlVendorAssembly"/>
          </
    controls>
        
    </pages>

      
    </system.web>

    </configuration>

    You can declare both user controls and compiled custom controls this way.  Both are fully supported by Visual Studio when you use this technique -- and both VS 2005 Web Site Projects and VS 2005 Web Application Projects support them (and show the controls in WYSIWYG mode in the designer as well as for field declarations in code-behind files).

    One thing to note above is the use of the "~" syntax with the user-controls.  For those of you not familiar with this notation, the "~" keyword in ASP.NET means "resolve from the application root path", and provides a good way to avoid adding "..\" syntax all over your code.  You will always want/need to use it when declaring user controls within web.config files since pages might be using the controls in different sub-directories - and so you always need to resolve paths from the application root to find the controls consistently.

    Once you register the controls within the web.config file, you can then just use the controls on any page, master-page or user control on your site like so (no registration directives required):

    <html>
    <body>
        
    <form id="form1" runat="server">
            
    <scott:header ID="MyHeader" runat="server" />
        </
    form>
    </body>
    </html>

    Hope this helps,

    Scott

    P.S. Special thanks to Phil Haack who blogged about this technique as well earlier this month (for those of you who don't know Phil, he helps build the very popular SubText blog engine and has a great blog).

  • ASP.NET 2.0 CSS Control Adapters Released

    Its official -- the ASP.NET 2.0 CSS Friendly Control Adapters have finally been released !

    What are CSS Friendly Control Adapters?  Here's what Microsoft says about them:

    ASP.NET is a great technology for building web sites but it would be even better if it provided more flexibility for customizing the rendered HTML. For example, the Menu control makes it simple to add a menu to a web site, but it would be better if it didn't create <table> tags and was easier to style using CSS. Happily, it's easy to customize and adapt the Menu control to generate better HTML. Indeed, you can modify any ASP.NET control so it produces exactly the HTML you want.

    The key is to use something that may be new to you: control adapters. These are little chunks of logic that you add to your web site to effectively "adapt" an ASP.NET control to render the HTML you prefer. The ASP.NET 2.0 CSS Friendly Control Adapters kit provides pre-built control adapters that you can easily use to generate CSS friendly markup from some of the more commonly used ASP.NET controls.

    So go download and install them today -- and start building more CSS Friendly sites with ASP.NET. 

     

  • Common Gotcha: Don't forget to <clear/> when adding providers

    Recently I've helped a few people out who were having an issue with how they had added new Membership, Role, and Profile providers within their web.config file.  If you are ever going to add a provider declaration within your web.config file, please read-on to learn how to avoid a common gotcha.

    Symptom:

    You want to configure ASP.NET 2.0 to store your Membership/Role Management/Profile data within a remote SQL database.  To accomplish this you first use the aspnet_regsql.exe utility to provision the appropriate schema within the database.  Rather than override the "LocalSqlServer" connection string within your web.config file, you decide to register a new provider within your web.config file like below (note: the following registration has a bug - so don't copy/paste it):

          <membership>

                
    <providers>
                    
    <add name="AspNetSqlMembershipProvider"
                        type
    ="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                        connectionStringName
    ="MyDatabase"
                        enablePasswordRetrieval
    ="false"
                        enablePasswordReset
    ="true"
                        requiresQuestionAndAnswer
    ="true"
                        requiresUniqueEmail
    ="false"
                        passwordFormat
    ="Hashed"
                        maxInvalidPasswordAttempts
    ="5"
                        minRequiredPasswordLength
    ="7"
                        minRequiredNonalphanumericCharacters
    ="1"
                        passwordAttemptWindow
    ="10"
                        passwordStrengthRegularExpression
    ="" 
                        applicationName
    ="/" 
                    
    />
                </
    providers>

          
    </membership>

    When registering the above provider you are careful to explictly set the applicationName property, and so avoid another really common gotcha.

    When you run your application on a machine without SQL Express, though, you see some weird behavior.  You might get a SQL error like so:

    An error has occurred while establishing a connection to the server.  When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

    You might also find that the web administration tool has problems connecting with your database and/or the roles/users you create within it aren't correctly saved in the database you configured above.

    Cause of the Problem:

    The root cause of the above problem rests in how the new provider was registered within the web.config file. 

    The <providers> section within the web.config file is implemented as a collection, and so it is possible to register multiple providers at the same time (this is useful when you want to have some users authenticated using one Membership store, and others authenticated using a separate Membership store).

    By default ASP.NET 2.0 registers a set of default SQL Express providers within the root web.config file on your machine that create a SQL Express database within your /app_data directory to store/manage membership/role/profile data when you first access it.  Because this is registered at the machine-wide level, all provider collections by default inherit this registration.  Unless you explictly <clear/> or override the inherited value, your application will have this default membership/role/profile provider registered.

    Because the above web.config file simply added a new provider -- and didn't clear or replace the default provider registration -- the above application now has two Membership providers configured.  When you do a Membership.CreateUser() call in your code, ASP.NET will attempt to create the user in both membership databases.  If you don't have SQL Express installed on your system, the create-user attempt will fail for this database - which leads to the errors and/or weird behavior above.

    How to Fix It:

    Unless you wish to register multiple membership, role or profile databases (which is rare), you should always add an explicit <clear/> directive before your <add/> statements within your web.config file:

          <membership>

                
    <providers>
                    
    <clear/>
                    
    <add name="AspNetSqlMembershipProvider"
                        type
    ="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
                        connectionStringName
    ="MyDatabase"
                        enablePasswordRetrieval
    ="false"
                        enablePasswordReset
    ="true"
                        requiresQuestionAndAnswer
    ="true"
                        requiresUniqueEmail
    ="false"
                        passwordFormat
    ="Hashed"
                        maxInvalidPasswordAttempts
    ="5"
                        minRequiredPasswordLength
    ="7"
                        minRequiredNonalphanumericCharacters
    ="1"
                        passwordAttemptWindow
    ="10"
                        passwordStrengthRegularExpression
    ="" 
                        applicationName
    ="/" 
                    
    />
                </
    providers>

          
    </membership>

    This will ensure that your application doesn't inherit any default provider registrations. 

    Note that you must do this for each provider declaration that you register.  So if you are adding providers for <roles> and <profile>, make sure you add the <clear/> directive in their providers section as well.

    Hope this helps,

    Scott

    P.S. Click here to review other past ASP.NET Tips/Tricks, Gotchas, and Recipes.

  • Podcasts and Prototyping

    Ron Jacobs recently published a podcast with me for his ARCast.net show (which is a free Podcast series aimed at architects).  In the podcast we covered a couple of topics people might find interesting:

    • Some of the history behind .NET and specifically ASP.NET
    • The importance of prototyping (and how not to screw it up)
    • The importance of developing "soft skills" to be a successful architect

    The prototyping discussion is one that I think has a lot of relevance to many projects out there.  It is a best practice that I really encourage all developers to dedicate more time towards -- since done right it really allows you to experiment and quickly try out a lot of ideas and concepts that can help you dramatically move the innovation dial on your projects. 

    The critical thing with prototyping is to ensure that you never, never, never allow prototype code to morph into becoming production code.  Don't try and "clean it up" or "refine" it to make the prototype code production grade.  This type of "clean up" rarely goes as far as it should, and usually ends up starting a project off on a very poor footing.  And checking in "quick and dirty" prototype code to an existing code-base is kind of like tossing in a bad apple into a barrel of good ones - you can easily end up with "code rot" spreading across a code-base this way.

    It is always much better to simply start a blank new project and import the prototype concepts -- and not the code -- to the project.  Spend extra time up front ensuring that the new production code starts off at 100% production quality, and don't try and save a few days by re-using the lines of code in the prototype.  What you'll find after a prototyping exercise is that writing the "real" production code from scratch ends up going much faster than you might have expected, since the feature ideas are much more fleshed out in your head and consequently you'll have a much deeper understanding of how the implementation should be structured.  The code quality bar will also be dramatically higher.

    I recently ran into this with one of the ideas I've been playing around with prototyping in my spare time the last few weekends.  I had some pretty complex dispatcher logic that I'd been working on and morphing overtime as I experimented with features and approaches.  I knew that once I'd finished playing around with some of the programming model ideas I'd be able to clean it up considerably - but it wasn't until last night when I set aside a few hours to write a new implementation from scratch that I was able to see just how dramatic an improvement I was able to get over the iteratively developed prototype one.  I suspect most people will see similar code improvement/quality results by being disciplined and making sure that they consciously throw-out prototype code once they've finished iterating/learning from it.

    To listen to the podcast in full visit Ron's podcast link here.

    Hope this helps,

    Scott

    P.S. I just saw that Paul Glavich also just posted another podcast with me here.  Show contents on this second podcast include: ASP.NET AJAX (aka Atlas), WPF/e, Windows Workflow/Cardspace, BLINQ and Script#, and Visual Studio 2005 SP1.  Definitely check it out too!

  • December's Toolbox Column Now Online

    My 12th Toolbox column in the December 2006 issue of MSDN Magazine is now avaiable online, marking my one year anniversary writing this column! The December issue examines three products:

    • AxoSoft OnTime 2006 - issue and defect tracking software.
    • Automation Anywhere - a straightforward program for defining and implementing automated tasks (which can include GUI-based actions as well as system- and programmatic-based ones).
    • SpreadsheetGear for .NET - a .NET component for generating and working with Excel spreadsheets.

    This month's issue reviewed Laurence Moroney's book Foundations of Atlas. Atlas (now renamed to the Microsoft AJAX Library, the ASP.NET 2.0 AJAX Extensions, and the ASP.NET AJAX Control Toolkit) provides a set of controls and libraries for easily creating AJAX-enabled ASP.NET web applications. From the review:

    For those itching to use Atlas to create responsive ASP.NET applications, check out Foundations of Atlas by Laurence Moroney (Apress, 2006). The book begins with a good overview of AJAX, followed by a look at how Atlas simplifies AJAX development by providing a set of client and server controls that work together to emit the needed client-side script and server-side functionality to participate in asynchronous postbacks.

    The next several chapters focus on examples and walkthroughs that show how to use the Atlas controls, including an entire chapter on data binding. The last chapter looks at building an AJAX-enabled financial research Web application from the ground up. The chapter does a great job at tying together the lessons learned throughout the book and illustrating a real-world benefit from using AJAX techniques with Atlas.

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

  • IronPython for ASP.NET CTP

    A few months back I blogged about the release of IronPython v1.0.  IronPython is an implementation of the Python dynamic language for .NET.  It supports an interactive console with full dynamic compilation support and makes all .NET libraries easily available to Python programmers -- while still maintaining full compatibility with the Python language.

    IronPython provides a great example of how .NET languages can leverage the new dynamic language features that we added into the CLR with last year's .NET 2.0 release.  For example, CLR features like "lightweight code-generation" now make it possible for a dynamic language to quickly compile and JIT source in-memory (giving you really fast code execution without ever having to generate or persist a .dll file).  CLR 2.0 also now has the ability to garbage collect out JIT'd code (meaning you can quickly adapt types on the fly and not have to leak code). 

    Last week we released a really cool CTP that provides IronPython integration support within ASP.NET and Visual Web Developer Express (which is of course free).  Once installed you can create new projects and pages using Python as your language and easily take advantage of dynamic language scripting support:

    Once the IronPython for ASP.NET CTP download is installed, Visual Studio/Visual Web Developer will provide both inline code and code-behind page support for Python with ASP.NET -- with syntax highlighting, WYSIWYG designer, and full debugging support.  You can also use it to create standalone python module files that live under the App_Script directory, and which can be used across a site.

    The easiest way to explore Python usage with it is to choose the File->New Web Site menu item and create the Python edition of the "Personal Starter Kit" sample site (note the .py code-behind files in the screen-shot below):

    The Personal Starter Kit Python example above provides a cool way to start to learn Python, as well as take advantage of some of the dynamic language capabilities that Python provides (as well as the really nice integration within ASP.NET that the IronPython team has added). 

    For example, the Photos.aspx page contains support for allowing an administrator to upload a new photo into an album.  This is implemented using a FormView control with a templated insert mode UI like so: 

    <asp:FormView ID="FormView1" DefaultMode="insert" OnItemInserting="FormView1_ItemInserting" runat="server">
        
    <InsertItemTemplate>

            Enter Photo: 
    <asp:FileUpload ID="PhotoFile" … />
            Enter Caption: <
    asp:TextBox ID="PhotoCaption" … />

            ....

        </
    InsertItemTemplate>
    </asp:FormView>

    In a strongly-typed language you would typically need to use the "FindControl()" method of FormView1 in order to reach into its template to retrieve a reference to the FileUpload or TextBox control, and then cast it the returned object type in order to use it. With a dynamic language like Python you can instead just write the below code in your Photos.aspx.py code-behind file:

    import PhotoManager

    def FormView1_ItemInserting(sender, e):

        caption 
    FormView1.PhotoCaption.Text
        bytes 
    FormView1.PhotoFile.FileBytes
        
        
    if len(bytes) == 0:
            e.Cancel 
    True
        
    else:
            PhotoManager.AddPhoto(Request.AlbumID, caption, bytes)

    Note how you can just write "FormView1.PhotoCaption" to access the sub-control within the template, and then reference subproperties off of it directly.  This technique can also be used with templated controls like DataLists, Repeaters, Wizards, etc.  Pretty neat.

    How to Learn More About IronPython

    Check out the IronPython for ASP.NET home-page to learn more about the IronPython for ASP.NET CTP download.  You can also read a great whitepaper that David Ebbo wrote that describes the changes made to the ASP.NET parser to better support dynamic languages and compilation here (these can be used by both IronPython and any other dynamic language). 

    Lastly, to learn more about IronPython itself I'd recommend watching this great videocast (with demos) that Jod Udell did with Jim Hugunin back in September.  Jim codes up some cool demos on the fly, including building a calculator within WPF using IronPython that integrates with the Speech APIs.  He also then shows how you can optionally refactor performance critical code from Python into strongly typed languages like C# and seamlessly work across the two.  You can now use all of the same techniques with IronPython and ASP.NET.

    Hope this helps,

    Scott

  • Gotcha: Lost HTML Intellisense within ASP.NET AJAX Controls

    Symptom:

    You are using ASP.NET AJAX Beta1 or Beta2, and create a .aspx page that is based on a .master file.  You add the <asp:scriptmanger>, <asp:updatepanel>, <asp:updateprogress> or <asp:timer> control into the content page, and find that markup intellisense no longer works for these controls, or for any controls nested within them:

    In the screen-shot above notice how the ScriptManager, UpdatePanel and ContentTemplate tags have the little red-squiggly lines underneath them.  You also won't get tag completion when you type these elements in the document.  You can still compile and run just fine, and the WYSIWYG designer works just fine.  But you do lose source editor intellisense.

    Some Background on the Issue:

    ASP.NET 2.0 added support for registering controls (both compiled and .ascx user controls) within your web.config file - removing the need to always add <%@ Register %> directives at the top of your page.  For more details on this and to see a sample in action, please check out my Tips and Tricks talk from the recent ASP.NET Connections conference.

    One of the cool aspects of this feature is that it also now allows you to map the same tag prefix against multiple assemblies.  We use this with ASP.NET AJAX to have these controls use the <asp:> tag prefix, even though they live in a separate assembly from the system.web.dll file that contains the rest of ASP.NET.

    Unfortunately we discovered a bug with the VS markup intellisense engine when doing the ASP.NET AJAX Beta1 release - which is that you lose intellisense when you map multiple assemblies against the <asp:> tag prefix and use the controls within a <asp:content> control in a .aspx page based on a master page. 

    How to Fix This

    The fix for the intellisense issue will be in VS 2005 SP1.

    In the meantime there are two workarounds that you can use to fix it immediately:

    1) Keep the .master file open within the Visual Studio IDE when working on the .aspx content page.  It turns out the intellisense engine only runs into issues if the .master file is closed.  As long as it is open within the same IDE, it resolves the assemblies just fine and will give you full intellisense:

    The screen-shot above is with the exact same sample as the previous screen-shot.  The only difference is that I also have the Site.Master file open in the editor in the background.  When that file is open, I get full intellisense for the ASP.NET AJAX control elements and no intellisense errors.

    Alternatively you could instead use the below technique if you don't want to keep the .master file open:

    2) Go into your web.config file and change the tag-prefix naming for the ASP.NET AJAX controls to something other than <asp:>.  For example, instead of:

          <controls>
            
    <add tagPrefix="asp" namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Extensions" />
            <
    add tagPrefix="asp" namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Extensions" />
          </
    controls>

     

    change them to something like this:

     

          <controls>
            
    <add tagPrefix="ajax" namespace="Microsoft.Web.UI" assembly="Microsoft.Web.Extensions" />
            <
    add tagPrefix="ajax" namespace="Microsoft.Web.UI.Controls" assembly="Microsoft.Web.Extensions" />
          </
    controls>

    You'd then want to update your tag prefixes in your .aspx page to use this new tag prefix.

    Either of these approaches will solve the problem and deliver full intellisense.  The issue should then be resolved completely with VS 2005 SP1.

    Hope this helps (and sorry for the inconvenience),

    Scott

  • Free Lunch-n-Learn on .NET v3.0 (WinFx) in Atlanta

    Doug Turnure and Todd Fine will be hosting a few free lunch-n-learns on .NET v3.0 (formerly called WinFx) in Atlanta at the Microsoft offices in Alpharetta on Nov. 20 and Dec. 18 -- BYOL (bring your own lunch).
    Share this post: Email it! | bookmark it! | digg it! | reddit!