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

  • Sorting the Visual Studio &quot;Add New Item&quot; Dialog with PowerShell

    The items in the "Add New Item" dialog box of Visual Studio appear in an arbitrary order. After a bit of sleuthing, I put together a brute force Powershell script to sort my items alphabetically. Now "Code File" appears near "Class", and I can always find "XML File" near the bottom of the dialog.

    sorted items in vs2005

    SortOrder, and my sanity, is restored.

    What follows is the script. Download sort-vsItems.ps1. Let me caveat this script by saying it has only been tested on two machines. If you have any problems, do let me know.

    # sort-vsItems
    # scott@OdeToCode.com
    # Use at your own risk!
    # Script will make a backup of each template ... just in case...

    #vjslib for .zip support
    [System.Reflection.Assembly]::Load(
    "vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    ) | out-null

    # Get list of VS installed templates
    $installDir = (gp HKLM:Software\Microsoft\VisualStudio\8.0).InstallDir
    $installDir += "ItemTemplates\"
    $templateFiles = gci -recurse $installDir | ? {$_.extension -eq ".zip"}

    # Append list of custom templates
    $installDir = $home
    $installDir += '\My Documents\Visual Studio 2005\Templates\ItemTemplates'
    $templateFiles += gci -recurse $installDir | ? {$_.extension -eq ".zip"}

    $templateFiles = $templateFiles | sort name

    $i = 1
    $count = 0
    $tmpDir = new-item ([System.IO.Path]::GetRandomFileName()) -type directory
    $buffer = new-object System.SByte[] (8192)

    foreach($templateFile in $templateFiles)
    {
    write-host "Processing" $templateFile.FullName

    #extract all files (no methods appear available to modify zip in place)
    $zip = new-object java.util.zip.ZipFile($templateFile.FullName)
    $entries = $zip.entries()
    while($entries.hasMoreElements())
    {
    $zipEntry = $entries.nextElement()
    $in = $zip.getInputStream($zipEntry)
    $out = new-object java.io.FileOutputStream(
    $tmpDir.FullName + "\" + $zipEntry.getName()
    )
    while(($count = $in.read($buffer, 0, $buffer.Count)) -gt 0)
    {
    $out.write($buffer, 0, $count)
    }
    $out.Close()
    $in.Close()
    }
    $zip.Close()

    #tweak the sort order element
    $vst = gci -recurse $tmpDir | ? {$_.extension -eq ".vstemplate"}

    $xmlDoc = new-object System.Xml.XmlDocument
    $xmlDoc.Load($vst.FullName)
    if($xmlDoc.VSTemplate.TemplateData.SortOrder -ne $null)
    {
    $xmlDoc.VSTemplate.TemplateData.SortOrder = ($i++).ToString()
    $xmlDoc.Save($vst.FullName)
    }

    #backup existing zip file
    $backupName = $templateFile.FullName + ".bak"
    if(test-path $backupName) { remove-item $backupName }
    move-item $templateFile.FullName $backupName

    #zip up modified version
    $files= gci -recurse $tmpDir
    $zip = new-object java.util.zip.ZipOutputStream(
    new-object java.io.FileOutputStream(
    $templateFile.FullName))
    foreach($file in $files)
    {
    $zipEntry = new-object java.util.zip.ZipEntry($file.Name)
    $zip.putNextEntry($zipEntry)
    $in = new-object java.io.FileInputStream($file.FullName)
    while(($count = $in.read($buffer, 0, $buffer.Count)) -gt 0)
    {
    $zip.write($buffer, 0, $count)
    }
    $in.close()
    $zip.closeEntry()

    }
    $zip.close()
    del $tmpDir\*
    }

    del $tmpDir -force -recurse

    write-host "Running Visual Studio to refresh templates"
    $vstudio = (gp HKLM:Software\Microsoft\VisualStudio\8.0).InstallDir
    & $vstudio\devenv /setup

    Powershell is beauty!

  • My "First Look at Orcas" Presentation

    One of the highlights of my recent trip to Europe was getting the chance to publicly show off some of the new features in our next release of Visual Studio and the .NET Framework (codename: "Orcas") for the first time publicly. 

    You can download the deck I presented here.  You can also watch a version of the Belgium talk that Tom posted on the web here (note: another version taken from my WebDD talk in the UK will also be posted shortly).

    "Orcas" is going to be a pretty exciting release, and contains a ton of great functionality that I think you will really love.  I'll be drilling down into more details of it over the next few months in many more blog posts.  Below are a few screen-shots from demos I showed over the weekend in my talks in Europe.  Note that they are just a few of the features - there are a lot more features I have yet to talk about. :-)

    Multi-Targeting

    Visual Studio "Orcas" will be the first version of Visual Studio that enables developers to target multiple versions of the .NET Framework.  This means that you can open or create a project that explicitly targets either the .NET Framework 2.0, 3.0 and 3.5 releases, and Visual Studio will automatically filter intellisense, toolbox controls, and add reference dialog items (among other things) to only show those features supported within that specific version of the framework.  You can then compile against each of these different framework releases, as well as get full debugging support for each. 

    The big benefit of Multi-Targeting is that you can now use most of the new features (for example: all the WYSWIYG designer and JavaScript editing ones) in Visual Studio "Orcas" immediately - even if you are still working on or updating an older project. 

    Below is an example that shows how to create a project that explicitly targets .NET Framework 2.0 (allowing you to create a web project in "Orcas" that will run on the current ASP.NET 2.0 release):

    You can then adjust the version target to .NET Framework 3.5 (which is the "Orcas" release of the framework libraries and includes LINQ support), and you can see that several new project types are available (including WPF projects):

    Assembly references, intellisense, and debugging within a project will automatically adjust based on the version of the framework you are targeting.

    Rich HTML/CSS WYSIWYG Designer

    As I mentioned in an earlier blog post, Visual Studio "Orcas" will ship a radically improved HTML and ASP.NET page designer.  Among other things, this WYSIWYG designer provides:

    • Split View Support (the ability to have both HTML Source and WYSIWYG design open simultaneously)
    • Extremely rich CSS support (CSS property window, CSS inheritance viewer, CSS preview, and CSS manager)
    • Dramatically improved view switching performance (moving from source->html design mode is now nearly instantaneous)
    • Support for control designers within source view (property builders, event wire-up and wizards now work in source view)
    • Richer ruler and layout support (better yet, values can be automatically stored in external CSS files)
    • Designer support for nested master pages

    Below is a screen-shot of an ASP.NET page in split-view mode editing mode (enabling you to work in both source and design mode simultaneously):

    Visual Studio "Orcas" also now has radically improved CSS support.  The new "Manage Styles" property window allows you to easily create, manage, and refactor CSS rules within style-sheets. 

    For example: you can see a list of all stylesheet rules within the c4f.css stylesheet below.  Those with circles around them mean that the rule is being used within the current page (you can then right-click to see how many places it is being used and to highlight those elements that are using it in the WYWSIYG designer).  You can drag/drop the rules to re-arrange their order within the stylesheet, refactor them across files, and to select an HTML element in the WYSIWYG designer to apply the CSS rule.

    When you select an HTML element in the WYSIWYG designer, you can also now use the CSS Properties window to see all CSS rules and their corresponding settings.  One really nice thing about this feature is that it shows you the cascading settings inherited from the various CSS rules. 

    For example: you can see below that the various rules I have set for a particular element set the color property 4 times (these are in turn overridden by lower rules in the CSS chain).  You can click on any rule in the property-pane, or on any of the overridden values to identify exactly where each setting is coming from.  This makes it much, much easier to figure out why a page or element looks a particular way when using CSS:

    When changing CSS style values like color, the color-pickers also now have nice features such as showing you other colors already in use in the stylesheet or document:

    The WYSIWYG designer now supports the ability to define and use "nested master pages" for ASP.NET.  For example, you can now define a root "Site.Master" file for the entire site:

    You can then obviously create new .aspx pages that uses this (like in VS 2005),  Or you can now also create a new master page that derives from it, and adds its own content and other contentplaceholder controls within the contentplaceholder defined in the root site.master file.  This is super useful when you want to have multiple types of layout used across a site.  For example, you might want to introduce a Two Column content layout master file like below, which inherits and extends the root Site.Master file:

    You can then create new pages that derive from this Two Column master page and fill-in content within the two contentplaceholders exposed by it:

    The beauty is that any change made to the root master will now be picked up by all pages on the site - regardless of which master page they are based on (as long as that master is based on the root master).  This enables much richer and more flexible organization of layout structure within your site.

    ASP.NET AJAX and JavaScript

    ASP.NET AJAX 1.0 shipped two weeks ago - with "Orcas" we are taking it even further (and obviously including all of the ASP.NET AJAX 1.0 functionality built-in).   Included as part of this will be significantly improved AJAX and JavaScript tool support within Visual Studio -- including JavaScript intellisense and much richer debugging support.

    Below is a screen-shot showing intellisense method summary information automatically being generated on the fly against standard inline JavaScript (any JavaScript code will work):

    The JavaScript intellisense supports rich type inferencing - for example, notice how it has automatically inferred from the method below that the return argument is a string (and so can provide intellisense for a string on it later):

    The JavaScript intellisense engine within VS will have rich support for all the standard ASP.NET AJAX library concepts (classes, properties, enums, etc).  In addition to providing intellisense support against any regular JavaScript code, VS will also allow you to now add optional comment summary information to provide additional hints for Intellisense:

    When debugging AJAX and JavaScript, you can now set client-JavaScript breakpoints within your server-code - VS can now automatically then wire these up on the client-side (these breakpoints will also optionally be persisted when you close a project/solution).  When debugging you also now have full watch window, intermediate window and more support.  The solution explorer in VS also now automatically lists running JavaScript document files - allowing you to easily set breakpoints in any script resource.

    Significantly Improved Data Support

    As I have blogged about in the past, "Orcas" will include support for LINQ - which makes data access with .NET radically better by making the concept of querying a first class programming concept.  VS Orcas includes an object relational mapper that enables you to create data models for relational data:

    You can then write rich LINQ queries in VB and C# to retrieve data, data bind it, and update it.  Full intellisense is now supported inside VS for all LINQ queries and resulting value:

    To start to see some of the power of LINQ, please watch my video here,  In addition to allowing you to write code using LINQ, we'll also obviously have full data-binding support in ASP.NET, and enable you to easily hook up any ASP.NET UI control to LINQ entities (allowing you to support paging, sorting, editing, deleting, and insertion without having to write any code).  We'll also have some new ASP.NET data controls (including a sweet new CSS based  ListView control) that will help make building data driven UI even easier. 

    Summary

    Orcas is going to be a fun release.  The screen-shots above hopefully wet your appetite about what is coming.  All of the features I showed above, and in the LINQ video, will ship within the February CTP of "Orcas" that will be available for public download in a few weeks.  We are then looking to ship a first Beta later this spring.  I'll be doing many more posts over the next few months that talk about some of the new features in much more detail. 

    Hope this helps,

    Scott

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

    Joe Developer is tasked with displaying the start date of his ASP.NET application. Joe thinks he'll just add a DateTime field to global.asax and initialize the field during the Application_Start event.

    <%@ Application Language="C#" %>

    <script runat="server">

        void Application_Start(object sender, EventArgs e)
        {
            StartDateTime =
    DateTime.Now;
        }
        
        
    public DateTime StartDateTime;
              
    </script>

    Whenever Joe needs to display the application start date, he accesses this public field.

    Joe doesn't know what is wrong, but he is sure of one thing – the date that is displaying on his pages is not the date when the application started. Can you help out Joe one more time?

  • ASP.NET AJAX Goodies: Documentation Download, Back Button Support, New Animation Control

    Just a quick post to highlight a few cool ASP.NET AJAX 1.0 related downloads that have been posted over the last few days:

    ASP.NET AJAX 1.0 Documentation Available for Download:

    The ASP.NET AJAX 1.0 Documentation can now be easily downloaded for offline usage.

    You can download and install your own copy of the docs here.  You can also browse all of the documentation and run all of the samples online at the http://ajax.asp.net web-site.

    Cool ASP.NET AJAX Control to easily enable Back / Forward Button Support with AJAX:

    Nikhil has updated his cool "UpdateHistory" control for the final ASP.NET AJAX 1.0 release (I first blogged about it in this old post).  This control enables developers to modify the browser's history stack - which enables AJAX integration with the back/forward buttons in the browser.  It also enables you to implement Unique URLs for bookmarking in AJAX applications.

    Nikhil also includes two new controls he built as part of the package - including a nice AnimatedUpdatePanel control that displays new content retrieved using the UpdatePanel with a variety of animations, as well as a CSS StyledUpdatePanel control that adds additional CSS customization semantics.  You can watch a video of how to use these controls here on Channel9.

    You can then download the source + binaries for the controls from Nikhil's web-site here.

    Hope this helps,

    Scott

  • ASP.NET 2.0 Tips and Tricks and ASP.NET, IIS7 and ASP.NET AJAX End to End Talks

    I've finished my whirlwind speaking tour of Europe (Belgium, UK and Netherlands in less than one week), and was fortunate to have had the chance to present to several hundred people along the way.  Many thanks to everyone who came out to attend my talks!

    Here are the first two slide decks + samples from the talks I gave:

    ASP.NET Tips and Tricks: 

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

    You can learn more about the Visual Studio build performance optimization suggestions by reading this past post of mine on improving build performance.  You can also find several dozen more ASP.NET and Visual Studio Tips/Tricks of mine on my Tips and Tricks summary page.

    Building an End-to-end Web Application from scratch using ASP.NET 2.0, ASP.NET AJAX, IIS7 and Visual Studio:

    This talk walked through building a rich data-driven application from scratch using ASP.NET 2.0, ASP.NET AJAX 1.0, IIS7 and Visual Studio (all of which are now officially shipping products).  You can download the deck + completed sample here.

    This talk demonstrates the following features: IIS7 distributed configuration, Master Pages, Building a DAL using DataSets, Building Data Driven Edit Pages, Building Catalogue Browsing Pages, Site Navigation, Url Rewriting, Site Navigation, CSS Control Adapters, ASP.NET AJAX, ASP.NET AJAX Control Toolkit, Membership/Roles, IIS7 Admin UI, SQL Cache Invalidation, and WebPart portal support.

    Hope this helps,

    Scott

    P.S. I'll be posting more slides+samples from my other talks in the days ahead (including my Orcas and WPF/E talks).

  • Sneak Peek: ASP.NET and Windows Workflow

    I’ve been working on an article that will show how to use a Windows Workflow state machine to drive logic behind an ASP.NET web form. Generally, my approach in articles is to use just enough code to reveal a specific concept. I don’t use heavy abstractions or include the safeguards and proven practices we need for production applications.

    There is delicate balance to strike when devising sample code, and you can never please everyone. Simple code will find itself cut and pasted into situations where it shouldn’t exist, and the person who has to fix the situation will curse you for being a fool. On the other hand, complex code is frustrating to the person who doesn’t want to tear apart three software layers just to see how to kick start a workflow in ASP.NET.

    For the article I’m working on, I could cram 15-20 lines of code into a Page_Load event. I started down this road, in fact, but I began to feel dirty. So dirty, I took a hot shower and came up with something like this:

    Workflow and ASP.NET

    Now the ASP.NET web form doesn't know anything about Windows Workflow - it only sees a service that interacts with domain objects. Between this service and the WF runtime is a mediator that uses knows how to run workflows and harvest workflow results. A second  service - a transaction service, commits units of work inside the same transaction as the WF persistence and tracking services. The end result is a unit-testable architecture, and relatively clean event handlers in ASP.NET code.  

    protected void shipOrderButton_Click(object sender, EventArgs e)
    {
        
    int orderId = GetSelectedOrderId();
        
    Check.IsNotTrue(orderId < 1, "Could not find selected order ID");

        
    Order selectedOrder = OrderService.Instance.GetOrderById(orderId);
        
    Check.IsNotNull("selectedOrder", "Could not fetch order " + orderId);

        
    OrderService.Instance.ShipOrder(selectedOrder);
        UpdateView();
    }

    The result is a more advanced article where the reader will need to understand some of the WF basics before digging through the sample application. I might be leaving out beginners, but I feel the complexity is justified. Now I just need to finish the article, as it is one week behind schedule. It's easy to push back deadlines since I set the schedule!

  • Brendon Schwartz at the Atlanta Cutting Edge .NET User Group

    The Atlanta Cutting Edge .NET User Group's monthly meeting is on Monday, February 5th, at 6:00 PM:

    This month, Brendon Schwartz will introduce the new release of Sharepoint (now known as MOSS). We will cover the high level advancements that make up MOSS 2007 and take a look a few demos of the new UI and features.

    Brendon Schwartz is an ASP.NET MVP in Atlanta. He is one of the "Atlanta .NET Regular Guys", as well as a founding member of the Atlanta Microsoft Professionals Group, and VP of Technology on the INETA Board of Directors. You can reach Brendon through his personal website at www.devcow.com, and visit his weblog at DevCow (http://devcow.com/blogs/adnrg/default.aspx).

    I won't be able to attend this meeting, but it looks like a good one, so come on out if you can, and hopefully I can make next month.
     

  • Podcast on Windows Developer Power Tools Posted

    Jim and I sat down (well, on skype) and did a podcast with Michael Kimsal at WebDevRadio. Michael was alot of fun to talk to and did a great job with the audio. I just finished listening and I think it actually turned out pretty good. We covered how and why we wrote the book, some of the tools we covered, and then some general discussion on the direction of the industry, especially around free and open source tools.

    Check it out.

    -James

  • Opening a PDF in a Popup Window In Internet Explorer

    Today I was working on a web application where we have a number of Crystal Reports. To date, we were displaying them using the CrystalReportViewer Web control, but virtually all users, we found, were using the reports in the same manner:

    1. Click on the link to view the report in the CrystalReportViewer in a popup window
    2. Click on the print icon
    3. Specify the pages to print. This refreshes the web page and shows it as a PDF
    4. Click the print button on the PDF document in the browser

    (Side note: Will there ever be a paperless office? Not in the health care industry, that's for sure!)

    To streamline this process we decided to have the CR render as a PDF automatically. The code is pretty straightforward, and we ended up using code very similar to that presented in Use ASP.NET to Launch a Report as a PDF. Once this code was implemented, clicking a link would display a popup containing the report in PDF format... in FireFox.

    In Internet Explorer 6, the popup window was empty. Using Fiddler, I could see that the PDF data was getting sent down, that the Content-Type MIME header was kosher, and so forth. A little Googling revealed that IE is a little fickle about displaying PDFs in popups. The workaround we ended up using - courtesy of Cowboy Bob's answer in the Unable to Display a PDF in IE When Within a Popup Window message post - was to “trick” IE by ending the URL with “.pdf”.

    That is, in the window.open JavaScript call we previously had something like:

    window.open('ShowCR.aspx?doc=1234', ...);

    And to get this to work in IE we had to change this to:

    window.open('ShowCR.aspx?doc=1234&iefix=fix.pdf', ...);

    Basically, IE had to see “.pdf” at the end of the URL to display the PDF in the popup window. Bleh. Is this fixed in IE 7? I sure hope so.

    (I also added a few lines of code to the Page_Load event handler in ShowCR.aspx so that if the querystring didn't end with “fix.pdf”, the page would Response.Redirect back to itself appending “&iefix=fix.pdf” to the URL. This way, if a previous or future link forgets or doesn't have the appropriate ending for this IE hack, it will automatically get tacked on and the report will properly display for our IE users, which is like 99% of the user base.)

  • A Potential Security Hole with "Remember Me Next Time"

    When a user authenticates in ASP.NET using forms authentication, the forms authentication system writes an authentication ticket to the user's cookies that allows the site to remember that the user has already been authenticated. This authentication ticket either lasts for the duration of the user's visit, for a specified duration, or can be persisted on the user's machine. If a timeout is specified, it can be a sliding or absolute duration. To specify this duration, from Web.config use the <forms> element's timeout and slidingExpiration attributes. It's a little confusing because the rules governing the cookie expiry changed between ASP.NET 1.x and 2.0.

    In ASP.NET 1.x, the timeout settings are ignored for persistent cookies. For ASP.NET 2.0, the timeout settings only apply to the persistent cookies. Moreover, in ASP.NET 1.x the expiry defaults to be sliding, while in ASP.NET 2.0 it defaults to be absolute.

    What this means, in English, is that in ASP.NET 1.x if you created a non-persistent authentication ticket cookie, it would last for the specified timeout (default is 30 minutes) with the timeout automatically being refreshed each time the user visited a new page in the site. In short, if a user visited a site, logged on (but did not choose to have their credentials remembered for subsequent visits), the cookie would be good until the user let 30 minutes (or whatever) lapse between visiting the site. If the user logged on with a persistent cookie, the cookie would have a duration of 50 years! Crazy. This, as we'll discuss shortly, carries with it some security concerns.

    ASP.NET 2.0 takes a much more conservative approach toward authentication ticket cookie expiries. For non-persistent cookies, the cookie lasts for the duration that the browser's open. There's no timeout, but once the browser closes, the user will need to re-authenticate when the next visit the site. Persistent cookies have an expiry based on the timeout value (again, a default of 30) and it defaults to an absolute timeout, meaning that after 30 minutes, regardless of how often they hit the site, the user will have to reauthenticate. This settings, of course, can be changed through the <forms> element as noted above.

    The authentication ticket is persisted on the user's machine across browser restarts (but only for the specified timeout duration) in ASP.NET 2.0 if the Login control's “Remember me next time” checkbox is checked. One potential security hole here is introduced because of the disconnect between authentication and the user's underlying information in the Membership system (or in some custom user store system). Consider the following scenario:

    • User A logs into site and checks “Remember me next time“. Imagine that the site has a timeout of three days.
    • User A then posts messages to the forum on this site and blasts a lot of spam and other garbage
    • Mr. Administrator sets User A's IsApproved value to False. If the user goes to Login.aspx, they won't be able to validate their credentials, but............
    • User A has a persistent authentication ticket cookie on his machine that is good for three days. So if User A visits tomorrow, he's still able to pass the authorization checks. If there's no additional logic on making posts that ensures the poster is approved, blam, User A is back to making his garbage posts.

    Any suggestions/recommendations on preventing this? I see two options:

    1. The application should not allow posts from unapproved users. Such a check could be done right before the post is committed to the database, for instance. This would prevent an unapproved user from making a post, but would still let them get on the site via the persistent authentication ticket cookie (until it expired after three days).
    2. Use a Session variable to indicate if a user has had their Approved status validated. If so, do nothing. If not, then check Membership.GetUser().IsApproved to make sure it has a value of True. If it does, set the Session variable to indicate that the check has been performed. In a base page class, override OnInit and perform this logic. Then have all ASP.NET pages in sections where only authenticated users are allowed derive from this base page class so that all pages make sure that the users visiting the site are approved.

    Any other suggestions or workarounds for this issue? Granted, one could simply shorten the persistent cookie timeout, but that kind of defeats the utility of “Remember me next time.” The good news is that because ASP.NET 2.0 is much more conservative than ASP.NET 1.x by default, the window with which an unapproved user has to access the site is greatly reduced.

This Blog

Syndication

Powered by Community Server, by Telligent Systems
'