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.

February 2007 - Posts

  • ASP.NET Black Belt Training :: April 21st, 2007 :: San Diego, CA

    On Saturday, April 21st I will be putting on a one-day event covering many real-world tips, tricks, and techniques for building data-driven ASP.NET 2.0 web applications. Starting from scratch, we'll build a feature-rich blog engine application that showcases a number of best practices and common challenges, including: building a layered application architecture; implementing a system to log unhandled exceptions; using caching to boost performance; efficiently paging through large amounts of data; implementing dynamic URL rewriting via an HTTP Module; making a site's appearance customizable through the use of dynamic themes and skins; and many more topics (see the outline for a more detailed look at the day's syllabus).

    This event is taking place in San Diego, California and runs from 9:00 AM to 5:00 PM with lunch provided. Specifically, the event will be held at the UCSD Extension building in Sorrento Mesa [Directions].

    The cost for this event is normally $299, but if you sign up by March 21st the rate is discounted to $199.

    For more information about this event, see the ASP.NET Black Belt Training homepage. Sign up at http://fuzzylogicinc.net/BlackBelt/SignUp.aspx.

    There is only room for 48 attendees. The last time this event was offerred, it sold out in two weeks...

    Hope to see you there!

  • Pet-Sitter Recommendation: Wholistic Setting

    This is a non-technical post, but I don't do this often, so please indulge me.  We recently went on a vacation and had to find a new pet-sitter for our dogs, cat, and fish/turtles.  We ended up choosing Wholistic Sitting and were very pleased with Tanya's service.  She sent us emails during our trip, including pictures, and it was obvious she was spending quality time with our pets given her descriptions.  The house was also well taken care of, accidents cleaned up, and the mail brought in.  So I'm very happy to recommend Wholistic Sitting if you need a pet-sitter in the Woodstock, Canton, or Roswell area of Georgia.  And if you've always done kennels then think again, as pet-sitting doesn't cost anymore, especially if you have more than one pet, and your pets are much better off in your own home.
  • Mimsware Position Announcement: Senior Network Consultant

    Mimsware is looking for a Senior Network Consultant.  Check out the job posting if you or someone you know in the Atlanta area is interested and qualified.
  • Tip/Trick: Url Rewriting with ASP.NET

    People often ask me for guidance on how they can dynamically "re-write" URLs and/or have the ability to publish cleaner URL end-points within their ASP.NET web applications.  This blog post summarizes a few approaches you can take to cleanly map or rewrite URLs with ASP.NET, and have the option to structure the URLs of your application however you want.

    Why does URL mapping and rewriting matter?

    The most common scenarios where developers want greater flexibility with URLs are:

    1) Handling cases where you want to restructure the pages within your web application, and you want to ensure that people who have bookmarked old URLs don't break when you move pages around.  Url-rewriting enables you to transparently forward requests to the new page location without breaking browsers.

    2) Improving the search relevancy of pages on your site with search engines like Google, Yahoo and Live.  Specifically, URL Rewriting can often make it easier to embed common keywords into the URLs of the pages on your sites, which can often increase the chance of someone clicking your link.  Moving from using querystring arguments to instead use fully qualified URL's can also in some cases increase your priority in search engine results.  Using techniques that force referring links to use the same case and URL entrypoint (for example: weblogs.asp.net/scottgu instead of weblogs.asp.net/scottgu/default.aspx) can also avoid diluting your pagerank across multiple URLs, and increase your search results.

    In a world where search engines increasingly drive traffic to sites, extracting any little improvement in your page ranking can yield very good ROI to your business.  Increasingly this is driving developers to use URL-Rewriting and other SEO (search engine optimization) techniques to optimize sites (note that SEO is a fast moving space, and the recommendations for increasing your search relevancy evolve monthly).  For a list of some good search engine optimization suggestions, I'd recommend reading the SSW Rules to Better Google Rankings, as well as MarketPosition's article on how URLs can affect top search engine ranking.

    Sample URL Rewriting Scenario

    For the purpose of this blog post, I'm going to assume we are building a set of e-commerce catalog pages within an application, and that the products are organized by categories (for example: books, videos, CDs, DVDs, etc).

    Let's assume that we initially have a page called "Products.aspx" that takes a category name as a querystring argument, and filters the products accordingly.  The corresponding URLs to this Products.aspx page look like this:

    http://www.store.com/products.aspx?category=books
    http://www.store.com/products.aspx?category=DVDs
    http://www.store.com/products.aspx?category=CDs

    Rather than use a querystring to expose each category, we want to modify the application so that each product category looks like a unique URL to a search engine, and has the category keyword embedded in the actual URL (and not as a querystring argument).  We'll spend the rest of this blog post going over 4 different approaches that we could take to achieve this.

    Approach 1: Use Request.PathInfo Parameters Instead of QueryStrings

    The first approach I'm going to demonstrate doesn't use Url-Rewriting at all, and instead uses a little-known feature of ASP.NET - the Request.PathInfo property.  To help explain the usefulness of this property, consider the below URL scenario for our e-commerce store:

    http://www.store.com/products.aspx/Books
    http://www.store.com/products.aspx/DVDs
    http://www.store.com/products.aspx/CDs

    One thing you'll notice with the above URLs is that they no longer have Querystring values - instead the category parameter value is appended on to the URL as a trailing /param value after the Products.aspx page handler name.  An automated search engine crawler will then interpret these URLs as three different URLs, and not as one URL with three different input values (search engines ignore the filename extension and just treat it as another character within the URL). 

    You might wonder how you handle this appended parameter scenario within ASP.NET.  The good news is that it is pretty simple.  Simply use the Request.PathInfo property, which will return the content immediately following the products.aspx portion of the URL.  So for the above URLs, Request.PathInfo would return "/Books", "/DVDs", and "/CDs" (in case you are wondering, the Request.Path property would return "/products.aspx").

    You could then easily write a function to retrieve the category like so (the below function strips out the leading slash and returning just "Books", "DVDs" or "CDs"):

        Function GetCategory() As String

            If 
    (Request.PathInfo.Length 0Then
                Return 
    ""
            
    Else
                Return 
    Request.PathInfo.Substring(1)
            
    End If

        End Function

    Sample Download: A sample application that I've built that shows using this technique can be downloaded here.  What is nice about this sample and technique is that no server configuration changes are required in order to deploy an ASP.NET application using this approach.  It will also work fine in a shared hosting environment.

    Approach 2: Using an HttpModule to Perform URL Rewriting

    An alternative approach to the above Request.PathInfo technique would be to take advantage of the HttpContext.RewritePath() method that ASP.NET provides.  This method allows a developer to dynamically rewrite the processing path of an incoming URL, and for ASP.NET to then continue executing the request using the newly re-written path.

    For example, we could choose to expose the following URLs to the public:

    http://www.store.com/products/Books.aspx
    http://www.store.com/products/DVDs.aspx
    http://www.store.com/products/CDs.aspx

    This looks to the outside world like there are three separate pages on the site (and will look great to a search crawler).  By using the HttpContext.RewritePath() method we can dynamically re-write the incoming URLs when they first reach the server to instead call a single Products.aspx page that takes the category name as a Querystring or PathInfo parameter instead.  For example, we could use an an Application_BeginRequest event in Global.asax like so to do this:

        void Application_BeginRequest(object sender, EventArgs e) {

            
    string fullOrigionalpath Request.Url.ToString();
            
            if 
    (fullOrigionalpath.Contains("/Products/Books.aspx")) {
                Context.RewritePath(
    "/Products.aspx?Category=Books");
            
    }
            
    else if (fullOrigionalpath.Contains("/Products/DVDs.aspx")) {
                Context.RewritePath(
    "/Products.aspx?Category=DVDs");
            
    }
        } 

    The downside of manually writing code like above is that it can be tedious and error prone.  Rather than do it yourself, I'd recommend using one of the already built HttpModules available on the web for free to perform this work for you.  Here a few free ones that you can download and use today:

    These modules allow you to declaratively express matching rules within your application's web.config file.  For example, to use the UrlRewriter.Net module within your application's web.config file to map the above URLs to a single Products.aspx page, we could simply add this web.config file to our application (no code is required):

    <?xml version="1.0"?>

    <configuration>

      
    <configSections>
        
    <section name="rewriter"  
                 requirePermission
    ="false" 
                 type
    ="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter" />
      </
    configSections>
      
      
    <system.web>
          
        
    <httpModules>
          
    <add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter"/>
        </
    httpModules>
        
      
    </system.web>

      
    <rewriter>
        
    <rewrite url="~/products/books.aspx" to="~/products.aspx?category=books" />
        <
    rewrite url="~/products/CDs.aspx" to="~/products.aspx?category=CDs" />
        <
    rewrite url="~/products/DVDs.aspx" to="~/products.aspx?category=DVDs" />
      </
    rewriter>  
      
    </configuration> 

    The HttpModule URL rewriters above also add support for regular expression and URL pattern matching (to avoid you having to hard-code every URL in your web.config file).  So instead of hard-coding the category list, you could re-write the rules like below to dynamically pull the category from the URL for any "/products/[category].aspx" combination:

      <rewriter>
        
    <rewrite url="~/products/(.+).aspx" to="~/products.aspx?category=$1" />
      </rewriter>  

    This makes your code much cleaner and super extensible.

    Sample Download: A sample application that I've built that shows using this technique with the UrlRewriter.Net module can be downloaded here

    What is nice about this sample and technique is that no server configuration changes are required in order to deploy an ASP.NET application using this approach.  It will also work fine in a medium trust shared hosting environment (just ftp/xcopy to the remote server and you are good to go - no installation required).

    Approach 3: Using an HttpModule to Perform Extension-Less URL Rewriting with IIS7

    The above HttpModule approach works great for scenarios where the URL you are re-writing has a .aspx extension, or another file extension that is configured to be processed by ASP.NET.  When you do this no custom server configuration is required - you can just copy your web application up to a remote server and it will work fine.

    There are times, though, when you want the URL to re-write to either have a non-ASP.NET file extension (for example: .jpg, .gif, or .htm) or no file-extension at all.  For example, we might want to expose these URLs as our public catalog pages (note they have no .aspx extension):

    http://www.store.com/products/Books
    http://www.store.com/products/DVDs
    http://www.store.com/products/CDs

    With IIS5 and IIS6, processing the above URLs using ASP.NET is not super easy.  IIS 5/6 makes it hard to perform URL rewriting on these types of URLs within ISAPI Extensions (which is how ASP.NET is implemented). Instead you need to perform the rewriting earlier in the IIS request pipeline using an ISAPI Filter.  I'll show how to-do this on IIS5/6 in the Approach 4 section below.

    The good news, though, is that IIS 7.0 makes handling these types of scenarios super easy.  You can now have an HttpModule execute anywhere within the IIS request pipeline - which means you can use the URLRewriter module above to process and rewrite extension-less URLs (or even URLs with a .asp, .php, or .jsp extension).  Below is how you would configure this with IIS7:

    <?xml version="1.0" encoding="UTF-8"?>

    <configuration>

      
    <configSections>
        
    <section name="rewriter" 
                 requirePermission
    ="false" 
                 type
    ="Intelligencia.UrlRewriter.Configuration.RewriterConfigurationSectionHandler, Intelligencia.UrlRewriter" />
      </
    configSections>
      
      
    <system.web>
          
        
    <httpModules>
          
    <add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule, Intelligencia.UrlRewriter" />
        </
    httpModules>
        
      
    </system.web>

      
    <system.webServer>

        
    <modules runAllManagedModulesForAllRequests="true">
          
    <add name="UrlRewriter" type="Intelligencia.UrlRewriter.RewriterHttpModule" />
        </
    modules>

        
    <validation validateIntegratedModeConfiguration="false" />

      </
    system.webServer>

      
    <rewriter>
        
    <rewrite url="~/products/(.+)" to="~/products.aspx?category=$1" />
      </
    rewriter>
      
    </configuration>

    Note the "runAllManagedModulesForAllRequests" attribute that is set to true on the <modules> section within <system.webServer>.  This will ensure that the UrlRewriter.Net module from Intelligencia, which was written before IIS7 shipped, will be called and have a chance to re-write all URL requests to the server (including for folders).  What is really cool about the above web.config file is that:

    1) It will work on any IIS 7.0 machine.  You don't need an administrator to enable anything on the remote host.  It will also work in medium trust shared hosting scenarios.

    2) Because I've configured the UrlRewriter in both the <httpModules> and IIS7 <modules> section, I can use the same URL Rewriting rules for both the built-in VS web-server (aka Cassini) as well as on IIS7.  Both fully support extension-less URLRewriting.  This makes testing and development really easy.

    IIS 7.0 server will ship later this year as part of Windows Longhorn Server, and will support a go-live license with the Beta3 release in a few weeks.  Because of all the new hosting features that have been added to IIS7, we expect hosters to start aggressively offering IIS7 accounts relatively quickly - which means you should be able to start to take advantage of the above extension-less rewriting support soon.  We'll also be shipping a Microsoft supported URL-Rewriting module in the IIS7 RTM timeframe that will be available for free as well that you'll be able to use on IIS7, and which will provide nice support for advanced re-writing scenarios for all content on your web-server.

    Sample Download: A sample application that I've built that shows using this extension-less URL technique with IIS7 and the UrlRewriter.Net module can be downloaded here

    Approach 4: ISAPIRewrite to enable Extension-less URL Rewriting for IIS5 and IIS6

    If you don't want to wait for IIS 7.0 in order to take advantage of extension-less URL Rewriting, then your best best is to use an ISAPI Filter in order to re-write URLs.  There are two ISAPI Filter solutions that I'm aware of that you might want to check-out:

    • Helicon Tech's ISAPI Rewrite: They provide an ISAPI Rewrite full product version for $99 (with 30 day free trial), as well as a ISAPI Rewrite lite edition that is free.
    • Ionic's ISAPI Rewrite: This is a free download (both source and binary available)

    I actually don't have any first-hand experience using either of the above solutions - although I've heard good things about them.  Scott Hanselman and Jeff Atwood recently both wrote up great blog posts about their experiences using them, and also provided some samples of how to configure the rules for them.  The rules for Helicon Tech's ISAPI Rewrite use the same syntax as Apache's mod_rewrite.  For example (taken from Jeff's blog post):

    [ISAPI_Rewrite]
    # fix missing slash on folders
    # note, this assumes we have no folders with periods!
    RewriteCond Host: (.*)
    RewriteRule ([^.?]+[^.?/]) http\://$1$2/ [RP]

    # remove index pages from URLs
    RewriteRule (.*)/default.htm$ $1/ [I,RP]
    RewriteRule (.*)/default.aspx$ $1/ [I,RP]
    RewriteRule (.*)/index.htm$ $1/ [I,RP]
    RewriteRule (.*)/index.html$ $1/ [I,RP]

    # force proper www. prefix on all requests
    RewriteCond %HTTP_HOST ^test\.com Idea
    RewriteRule ^/(.*) http://www.test.com/$1 [RP]

    # only allow whitelisted referers to hotlink images
    RewriteCond Referer: (?!http://(?:www\.good\.com|www\.better\.com)).+
    RewriteRule .*\.(?:gif|jpg|jpeg|png) /images/block.jpg [I,O]

    Definitely check out Scott's post and Jeff's post to learn more about these ISAPI modules, and what you can do with them.

    Note: One downside to using an ISAPI filter is that shared hosting environments typically won't allow you to install this component, and so you'll need either a virtual dedicated hosting server or a dedicated hosting server to use them.  But, if you do have a hosting plan that allows you to install the ISAPI, it will provide maximum flexibility on IIS5/6 - and tide you over until IIS7 ships.

    Handling ASP.NET PostBacks with URL Rewriting

    One gotcha that people often run into when using ASP.NET and Url-Rewriting has to-do with handling postback scenarios.  Specifically, when you place a <form runat="server"> control on a page, ASP.NET will automatically by default output the "action" attribute of the markup to point back to the page it is on.  The problem when using URL-Rewriting is that the URL that the <form> control renders is not the original URL of the request (for example: /products/books), but rather the re-written one (for example: /products.aspx?category=books).  This means that when you do a postback to the server, the URL will not be your nice clean one.

    With ASP.NET 1.0 and 1.1, people often resorted to sub-classing the <form> control and created their own control that correctly output the action to use.  While this works, it ends up being a little messy - since it means you have to update all of your pages to use this alternate form control, and it can sometimes have problems with the Visual Studio WYSIWYG designer.

    The good news is that with ASP.NET 2.0, there is a cleaner trick that you can use to rewrite the "action" attribute on the <form> control.  Specifically, you can take advantage of the new ASP.NET 2.0 Control Adapter extensibility architecture to customize the rendering of the <form> control, and override its "action" attribute value with a value you provide.  This doesn't require you to change any code in your .aspx pages.  Instead, just add a .browser file to your /app_browsers folder that registers a Control Adapter class to use to output the new "action" attribute:

    You can see a sample implementation I created that shows how to implement a Form Control Adapter that works with URLRewriting in my sample here.  It works for both the Request.PathInfo and UrlRewriter.Net module approaches I used in Approach 1 and 2 above, and uses the Request.RawUrl property to retrieve the original, un-rewritten, URL to render.  With the ISAPIRewrite filter in Approach 4 you can retrieve the Request.ServerVariables["HTTP_X_REWRITE_URL"] value that the ISAPI filter uses to save the original URL instead.

    My FormRewriter class implementation above should work for both standard ASP.NET and ASP.NET AJAX 1.0 pages (let me know if you run into any issues).

    Handling CSS and Image Reference Correctly

    One gotcha that people sometime run into when using Url Rewriting for the very first time is that they find that their image and CSS stylesheet references sometimes seem to stop working.  This is because they have relative references to these files within their HTML pages - and when you start to re-write URLs within an application you need to be aware that the browser will often be requesting files in different logical hierarchy levels than what is really stored on the server.

    For example, if our /products.aspx page above had a relative reference to "logo.jpg" in the .aspx page, but was requested via the /products/books.aspx url, then the browser will send a request for /products/logo.jpg instead of /logo.jpg when it renders the page.  To reference this file correctly, make sure you root qualify CSS and Image references ("/style.css" instead of "style.css").  For ASP.NET controls, you can also use the ~ syntax to reference files from the root of the application (for example: <asp:image imageurl="~/images/logo.jpg" runat="server"/>

    Hope this helps,

    Scott

    P.S. For more ASP.NET 2.0 Tips and Tricks, please check out my ASP.NET 2.0 Tips, Tricks and Tutorials Page.

    P.P.S. Special thanks to Scott Hanselman and Michael K. Campbell for testing my Form Control Adapter with their sites.

  • ASP.NET ViewState Helper

    Double D sent me this in an email earlier, looks pretty awesome. I ususally use Fiddler to look at page size, but this tool handily breaks out Viewstate vs. Markup.

    ASP.NET ViewState Helper

     

    -James

  • ClickOnce, I think I love you

    A couple months ago I wrote a post about how I didnt really like ClickOnce and that I was going to use ClickThrough. Well, I was wrong. ClickOnce is pretty awesome once you get into it. I also couldn't find much information about ClickThrough and it looks like there isn't much active development going on there. 

    I thought I needed to use a .msi file to get the install functionality I needed, but it turns out it was all built into ClickOnce... the only issue is that the ClickOnce documentation sucks pretty bad. Because the documentationm sucks I picked up Smart Client Deployment with ClickOnce by Brian Noyes and this book kicks ass, it answered all my questions and helped me figure out the best way to install and update my application.

    I kept running into issues I thought would break ClickOnce, but it turns out they did think through alot of stuff. One part that really impressed me is the data migration scenario. Let's say my user is off-line for a week, then they log back in and there is an update. If the update includes updates to the local database then it would overwrite all of their data from the last week... but what ClickOnce does is make a copy of the old data file and put it in a .pre folder in your deployment. This way I can write code that will check to see if the .pre folder is there and if so migrate any of their offline changes.

    -James

  • Awesome Modal

    I am always looking out for a new web modal (via Signal vs. Noise), and I ran across this one today:

    http://okonet.ru/projects/modalbox/

    The animation is awesome, and the dynamic re-sizing is very useful. (if you have used other modals then you this can be a real issue with validation results)

    -James

  • WPF Text Reading and Flow Document Support, and the new NYTimes, Daily Mail, and Seattle Post-Intelligencer Reader Applications

    Windows Presentation Foundation (WPF aka "Avalon") is a massive step forward for Windows client development, and delivers a super-rich .NET UI framework that integrates vector graphics, rich flow text support, and 3D visualization with a powerful control model framework.  You get WPF support with .NET 3.0 (which is built-in with Windows Vista and available as a separate download for other Windows OS versions).

    Visual Studio "Orcas" will ship with a rich WYSIWYG designer and project support for developers to easily build WPF applications.  The Microsoft Expression suite of designer products will also then provide killer support for designers to work on WPF visuals and interactivity (Expression Blend in particular is optimized for this).

    Both Visual Studio and Expression share the same project file format - which means that developers and designers can seamlessly work on a single project together, without stepping on each other's toes during the process (XML based XAML files define the UI and style of an app, separate .cs/.vb files contain the code-behind for a programmer to develop against them).  You can download the Beta 2 version of Microsoft Expression today.  In the next few weeks we'll be shipping the "February CTP" of Visual Studio "Orcas" on the web, which will have the WPF designer built-in and provide great coding support for WPF.

    WPF Text Reading and Flow Document Features

    WPF includes a tremendous amount of rich typographical support that dramatically improves how text is rendered to the screen, and significantly improves the digital text reading experience.  Advanced typographical features like ClearType support for sub-pixel positioning and y-direction smoothing, and OpenType features like ligatures, traditional numerals, swashes, and contextual alternatives make the quality of text much, much higher compared with standard HTML or other Windows client graphics technologies, and can significantly increase the speed with which a user can read content.

    WPF also provides built-in Flow Document support as part of the UI layout and control model experience.  Flow Document capability provides automatic support to reflow content within an application depending on the window size, content semantics, and device resolution of the application.  For example, you could load text, images, videos and any other WPF control within the FlowDocumentPageViewer control in WPF, and then have it automatically size and paginate the text across multiple columns and/or pages of content for you automatically.

    Below is an example of this in action with the New York Times Reader application (more on this app later in this blog post).  Notice how the article is automatically wrapped across two columns, and note the "Page 1 of 2" navigation and Zoom UI at the bottom of the screen:

    To help illustrate how you can achieve the same content flow behavior yourself in your own applications, I built a simple sample below using WPF's built-in FlowDocumentPageViewer control.  Below is the entire contents of the application (it is all XAML - no code-behind code necessary):

    <Window x:Class="WPFApplication1.Window1"
        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        Title
    ="Window1" Height="300" Width="300">
        
    <Grid>
        
    <FlowDocumentPageViewer>
            
           
    <FlowDocument>
                
            
    <Paragraph>
               This is a paragraph of text.
            
    </Paragraph>
                    
            
    <Paragraph>
               This is another paragraph of text.
            
    </Paragraph>
                    
            
    <Paragraph>
               My movers are carrying my TV out right now.
            
    </Paragraph>
                    
            
    <Paragraph>
               I hope that loud bang wasn't the TV being dropped.
            
    </Paragraph>

            
    <BlockUIContainer>
               
    <Button Content="Button" />
            </
    BlockUIContainer>
                    
            
    <Paragraph>
               This is another paragraph.
            
    </Paragraph>

            
    </FlowDocument>
            
           
    </FlowDocumentPageViewer>

        
    </Grid>
    </Window>

    Now when I run the application I get a window that is 300x300 pixels wide by default with this content:

    As you'd expect, I get several paragraphs of text.  Note how I was also able to embed a WPF Button control directly within the content (I could put any WPF control within it).  Note also the automatic content paging control and content sizing slider that is also provided above by the FlowDocumentPageViewer.

    Now when I resize the Window to make it shorter and wider, you'll note how the content is automatically paged for me by the FlowDocumentPageViewer into two columns.  I did not have to write any code to get this behavior:

    I could also then narrow the Window slightly, and zoom in the content (using the slider at the bottom).  Note how the content (both the text and the button) get bigger on the screen, and how the FlowDocumentPageViewer control is now automatically paging the content for me (I've circled the appropriate UI in red below to indicate it):

    As you can see - this is really easy to achieve, and the result is a simple but powerful application.  Rather than hard-code the content within the application, I could obviously instead call out to a web-service or RSS feed and populate the content dynamically.  I'd get the same paging and flow semantics.

    New York Times Reader, Daily Mail Reader, and Seattle Post-Intelligencer Reader WPF Applications Now Available

    The WPF text support really opens up a tremendous number of opportunities to create deeper, more personalized reading experiences (among other things it is screaming out to be used by a blog reader client).  

    My team has been working with a number of Newspaper and Magazine publishers to help them develop and launch personalized reader applications for their content.  In addition to providing rich text support, each of these reader applications supports offline content support (meaning you sync the content when you are online, and can then read everything offline while not on a network - which is ideal for when you are on a plane, train or bus, etc).  The reader applications also provide rich search visualization and content annotation support:

    This past September the New York Times launched this customized New York Times Reader application (click here to download and use it for free):

    Today the Seattle Post-Intelligencer launched as well (click here to download and use it for free):

    As did the Daily Mail in the UK (click here to download and use it for free):

    Many more well-known publishers will be launching similar applications in the months ahead. 

    We are also going to be releasing a Reader SDK for publishers that will enable anyone to build similarly customized reading applications.  Sites will be able to expose RSS feeds with custom extensions (to embed optional pagination rules, advertising placement details, etc), and then developers will be able to easily build custom WPF reader client applications to further enhance the experience.

    Tim Sneath talks about this a little more about this work on his great blog here.

    How to Learn More about WPF

    To learn more about Flow Document support in WPF, I recommend reading this great MSDN article here.

    There are a number of good WPF books that have recently been published that can also help you come up to speed with WPF.  Adam Nathan has published a very good Windows Presentation Foundation Unleashed book that is out today and has received great reviews on Amazon (5 out of 5 starts with 10 reviews):

    Chris Sells and Chris Anderson each have WPF books coming out in the next few months that I've seen early drafts of and really like.  Here is a pointer to Chris Anderson's Essential WPF book on Amazon (it will be published in April).  I've just started reading Chris Sell's updated WPF book and really like his book as well - I'll update this blog post with a link to it on Amazon once it is available.

    Hope this helps,

    Scott

  • Four 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 four newest tutorials, which illustrate working with database data directly from an ASP.NET web page. The previous 46 tutorials (as well as all tutorials following these four) looked at working with data through a layered architecture. But for one-off projects or prototyping, it may be preferable to use a SqlDataSource and avoid building the architecture. These four new tutorials illustrate various facets of working with the SqlDataSource control:

    • Querying Data with the SqlDataSource Control [VB | C#]
    • Using Parameterized Queries with the SqlDataSource [VB | C#]
    • Inserting, Updating, and Deleting Data with the SqlDataSource [VB | C#]
    • Implementing Optimistic Concurrency with the SqlDataSource [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. Also, the layout of the tutorial homepage has been revamped and a new style has been applied for the individual tutorials.

    There are more tutorials to be released in the upcoming weeks, including tutorials on working with binary data (images, PDFs, etc.), caching, and much more!

  • ASP.NET AJAX and SharePoint

    One of the questions I was recently asked at a user group meeting in Europe was whether it was possible to use ASP.NET AJAX within SharePoint 2007 solutions.  This was a common enough question that the SharePoint team recently blogged about their plans with ASP.NET AJAX to help answer it.  You can read their post here.

    At a highlevel, official support for ASP.NET AJAX within SharePoint will be coming with the first service pack of SharePoint 2007.  This is because SharePoint 2007 shipped before ASP.NET AJAX 1.0 did, and so there is some work the SharePoint team needs to-do to make it integrate nicely.

    In the meantime, though, you can read the SharePoint team's blog post here on how to install ASP.NET AJAX 1.0 on a SharePoint 2007 site and start using its functionality today.  There are some caveats to using it until the first service pack ships - but the steps in their blog post will help you start using it immediately.  Also make sure to check out Eric Schoonover's blog post on a custom AjaxBasePart web part that his team has created to help with using ASP.NET AJAX within custom web parts you build.

    SharePoint and ASP.NET Developer Information

    For more information on SharePoint and Web Parts, please check out these past posts of mine:

    Also check out the SmartPart control plug-in for SharePoint 2007 that allows you to deploy any ASP.NET 2.0 user control as a web part within SharePoint 2007.

    SharePoint and ASP.NET Web Part Development Books

    While on the subject of SharePoint Developer and ASP.NET Web Parts, there are two great books on SharePoint development that I've been hearing very good things about lately.  The first book is Todd Bleeker's "Developer's Guide to the Windows SharePoint Services v3 Platform" which has a 5 star rating (out of 5) on Amazon after 11 reviews, and which has been burning up the Amazon most popular lists the last few months:

    The second book is Darren Neimke's "ASP.NET 2.0 Web Parts in Action: Building Dynamic Web Portals" which provides a great way to learn how to build sites that use ASP.NET 2.0 Web Parts, as well as how to build custom Web Parts of your own:

    The beauty of web parts is that with ASP.NET 2.0 you can now build ones that can work and be customized by end-users within any ASP.NET web site/application (no SharePoint required), as well as have these same web parts work and run within SharePoint 2007 (both the free Windows SharePoint Services edition as well as the Microsoft Office SharePoint Server version).  This provides a tremendous amount of developer power, and opens up a lot of options.

    Free Application Templates for Windows SharePoint Services 3.0

    One of the things the SharePoint team has been very focused on the last few months has been with putting together free application templates that you can download and use with Windows SharePoint Services 3.0 (which is the free version of SharePoint that you can download and install on any Windows Server box). 

    You can learn more about these application templates here.  Below is a list of some of the templates with custom web parts provided for free download today:

    • Board of Directors
    • Business Performance Reporting
    • Case Management for Government Agencies
    • Classroom Management
    • Clinical Trial Initiation and Management
    • Competitive Analysis Site
    • Discussion Database
    • Disputed Invoice Management
    • Employee Activities Site
    • Employee Self-Service Benefits
    • Employee Training Scheduling and Materials
    • Equity Research
    • Integrated Marketing Campaign Tracking
    • Manufacturing Process Management
    • New Store Opening
    • Product and Marketing Requirements Planning
    • Request for Proposal
    • Sports League
    • Team Work Site
    • Timecard Management

    What is great about these templates is that once you download and install them, you can optionally add custom ASP.NET web parts to it, and use standard ASP.NET 2.0 techniques to customize it further.  This makes it dramatically easier to build and deploy common solution applications.

    Some Final Information for Hosters Wanting to Offer SharePoint Offerings

    For hosters reading this who want to offer SharePoint based hosting solutions to customers, please make sure to check out the excellent "Creating Shared Hosting Solutions on Windows SharePoint Services 3.0" solution guide that Microsoft shipped this past Monday.  It provides really detailed instructions and prescriptive guidance on how to best deploy and manage SharePoint in a shared hosting environment, and enable thousands of customers to run on a single shared hosting server.

    Hope this helps,

    Scott

  • I've Noticed My CAPTCHAs Effectiveness is Decreasing

    About six months ago I implemented CAPTCHAs here on ScottOnWriting.NET and immediately saw comment spams drop from dozens a day to virtually zero. Sure, I occassionally found a comment spam or two every week, but the tide of spams had been abated. That's not the case anymore. I know get about 5-10 comment spams per day now.

    I take it this uptike in comment spams despite the CAPTCHA means one of two things:

    • There's some security hole in my blog comment system where spammers can post comments without needing to use the CAPTCHA, or
    • Brute force is in effect here. There are folks out there who are taking the time to type in the CAPTCHA to propagate their spam.

    I'm inclined to believe the latter explanation is what's happening because if there were a hole I'd expect to comment spam to ratchet back up to its previous, pre-CAPTCHA level. Assuming that spammers are taking the time to enter the CAPTCHA, it makes an interesting (albeit somewhat depressing) economic commentary: either that spam pays well enough to justify this behavior or it doesn't pay that well, but the people recruited to continue this spamming are “selling” their time for so little that the actions are still profitable. It's a bit of both, I'm sure, but it's sad because I would wager these people taking the time to surf to sites, paste in their spam, and enter the CAPTCHA, could be benefiting humanity moreso by producing a good or service.

    The only real guard against comment spam is moderation or simply turning off comments. I've actually taken the latter approach with some of my other blogs because the hassle of periodically removing the comment spam or proactively moderating outweighed the value the contributors' comments.

  • ASP.NET AJAX Tutorials, Disk Output Cache and RSS Toolkit CodePlex Projects, and Podcasts of Me

    I am moving to a new house this week, so I unfortunately didn't get a chance to create any new original content this weekend.  But thankfully a few people did forward me some good links that I haven't seen pointed to elsewhere that I highly recommend checking out:


    Free ASP.NET AJAX Hands-On Tutorials

    Sascha Corti from Microsoft Switzerland helped produce some really nice ASP.NET AJAX  hands-on tutorials in German and French, and Ken Cox (a great ASP.NET MVP from Canada) did an awesome job translating them to English.  You can download these labs and walkthrough them yourselves for free here

    Note that the documentation .zip file is 8MB (it contains lots of step by step pictures) - so I recommend using the "Save As" option in your browser and store them locally to disk as opposed to trying to open them directly. 

    Also - in case you missed it, also make sure to check out the great free ASP.NET AJAX 1.0 Videos here


    Cool ASP.NET Disk Output Cache and RSS Toolkit CodePlex Projects

    Dmitry, who used to be the ASP.NET Dev Manager and who now runs the Dynamic Language group within my team, created a number of really cool ASP.NET projects early last year.  Over the last few months Dmitry has worked with members of the .NET community to create CodePlex projects for some of these free components, which will anyone to join in enhancing them and adding new features.  Below are pointers to two recent CodePlex groups:

    • Disk Output Cache for ASP.NET: This module implements HTTP response caching on disk, that allows ASP.NET output cache responses to survive application restarts, and to optionally be shared across multiple servers.  Dmitry announced that Scott Cate is now running this project in his blog post tonight.
    • ASP.NET RSS Toolkit: This toolkit provides a ton of great support for efficiently consuming RSS feeds from a remote server (including automatic caching of them, as well as a RssDataSource control to enable easy databinding to feeds), and also support easily generating RSS feeds of your own.  My past RSS Toolkit Tip./Trick tutorial shows just some of the cool things you can do with it.  This CodePlex project is now being run by Marc Brooks

    Free Podcasts with Me

    Two podcasts that were recorded two weeks ago while I was in the UK at the excellent WebDD conference have recently been published.  You can listen to both for free:

    • NxtGenUG podcast -- NxtGenUG is a free .NET usergroup that meets regularly in Birmingham, Coventry, and Oxford.  You can learn more about them, as well as their upcoming free conference on May 23rd in Reading here.

    Hope this helps,

    Scott

    P.S. And now I have to go back to carrying boxes....<g>

  • Pluralsight News

    Fritz broke the news on Friday. I've joined the esteemed staff of Pluralsight!

    pluralsight logo

  • Free ASP.NET MVP Live Online Chat Tonight

    Ryan Olshan and StrongCoders have helped put together a great ASP.NET live web chat for later tonight.  It includes an all-star cast of MVP experts to field questions (I'll be there too to help answer questions).

    You can join us from 8-9pm EST (5-6 PM US West Coast Time) tonight to participate.  Details can be found on Ryan's post here, and on the MSDN Chat Center.

    Hope to see you there,

    Scott

    P.S. Apologies for the 150+ unanswered comments on my blog this week.  I was taken out by the flu the last few days and haven't been online.  I will post the comments and respond this weekend.

  • March's Toolbox Column Now Available Online

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

    • GoToMeeting - a desktop-sharing meeting tool that supports meetings of up to 10 participants. Very useful for telecommuniting or consulting on remote projects.
    • SlickEdit - a lightweight code editor that offers many of the essential features, but without the bloat that's present in Visual Studio.
    • FlowChart.NET - a component for displaying and modifying flowcharts, diagrams, hierarchies, and a myriad of other types of classification graphs.

    This month's issue reviewed Accelerated C#, by Trey Nash.

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

  • Free ASP.NET AJAX 1.0 "How Do I?" Videos (Updated for Final Release)

    Joe Stagner on the ASP.NET team has been busy the last few weeks, and has just finished updating all 23 of his ASP.NET AJAX "How Do I?" videos to go against the final ASP.NET AJAX 1.0 release

    If you haven't watched Joe's videos before, I highly recommend checking them out.  They are short, focused, videos that drill in on a specific topic and are designed to help master common scenarios when using the product.  Both VB and C# sample code versions can be downloaded for each video topic.

    You can watch all of the videos online for free at: http://www.asp.net/learn/videos/ (also make sure to check out the more than 50+ other videos on that page as well).

    Now that Joe has finished covering a lot of the ASP.NET AJAX and ASP.NET AJAX Control Toolkit basics, he is starting on a new "ASP.NET AJAX Patterns" series that will go deeper and discuss broader patterns to think about with AJAX (for example: predictive fetching, content chunking, page rearrangement, etc).  Make sure to subscribe to the ASP.NET Videos RSS Feed to keep an eye on this series as future videos are released.

    ASP.NET AJAX in Action Book

    Alessandro "Garbin" Gallo, David Barkol, and Rama Krishna Vavilala have also been working on what is shaping up to be a great ASP.NET AJAX 1.0 book for Manning called "ASP.NET AJAX in Action":

    Early chapters are now available online via their early access program.  Click here to learn more and start reading it today.

    Hope this helps,

    Scott

  • What's Wrong With This Code (#12)

    Joe Developer has been fired. Sacked. Terminated. Dismissed. Booted. "Dis-employed", if you will.

    Before Joe left, he started to write one last piece of code. He was asked to write an HTTP Module in ASP.NET that will log some information, and will include the date and time when the application last started running. He learned his lesson in last week's misadventure (too little, too late), and made his DateTime field static, like so:

    using System;
    using System.Web;

    public class LoggingModule : IHttpModule
    {
        
    public void Init(HttpApplication context)
        {
            startTime =
    DateTime.Now;
        }

        
    public void Dispose()
        {
        }

        
    static DateTime startTime;
    }

    Joe's replacement, Estelle Hertz, has to finish the module Joe started. Estelle thinks Joe was off to a pretty good start and adds some event handlers, some logging code, and checks in her changes.

    The testers are finding that the "start time" recorded by her module is drifting, but the event logs show the application is definitely not restarting.

    Did Joe leave a bug behind?

  • Windows Workflow Foundation and ASP.NET

    My latest article shows how to drive an ASP.NET web form using a state machine workflow. The sample is based loosely on the Ordering State Machine smart client sample in the SDK, but adds a few real world requirements.

  • WinDevPowerTools on The MicroISV Show

    Jim Holmes and myself were recently interviewed by Bob Walsh and Michael Lehman for the MicroISV Show over on Channel 9. I was proud to see that we are actually the longest podcast so far.

    There are some audio problems, Bob’s voice seems to be a little bit ahead of the rest of the audio… but other than that I think it turned out pretty good.

    -James