The blog of dlaa.me

Toolkit talk, take two [Spoke at the TechReady4 conference]

Earlier today I presented the DEV304: ASP.NET AJAX Control Toolkit Unleashed: Creating Rich Client-Side Controls and Components session at Microsoft's TechReady4 conference here in Seattle. TechReady is a Microsoft-only conference that non-Redmond-based employees attend to get an opportunity to meet with product team members (typically Redmond-based) and catch up on all the new technology each year. Most of the session content is Microsoft-only, but because the presentation I gave today had no private information, I'm posting the (sanitized) slide deck and demos here for everyone to use (note: the attachment is at the bottom of this post).

If you saw the content for my ASP.NET Connections talk a few months ago, the slide content for today's TechReady4 talk was very similar. The first demo was identical and the second (new) demo was just a quick overview of the sample web site that comes with the Toolkit. However, the third demo was completely new and demonstrated how to encapsulate existing script into a new Toolkit control. For demonstration purposes, I took a simple web page with a WPF/E (February CTP) control (the use of which requires two <script>/src tags and a <script>/code block) and showed how to wrap that all into a single "one-liner" Toolkit component which can be more easily used/maintained/added to a page. Those of you who are paying close attention will realize that I took my inspiration from a similar effort by my manager, Shawn Burke - though I wrote all my demo code from scratch so I'd be more familiar with it. :) The final result is a pretty handy way of handling WPF/E controls and folks are welcome to use it however they want!

I hope those of you who attended today enjoyed the talk and learned more about the Toolkit - it was great to have an opportunity to meet with you!

PS - We're always looking for more contributors and additional control ideas, so please let me know if you want to contribute!

[TechReady4-DEV304-AjaxControlToolkit.zip]

Safely avoiding the "access denied" dialog [How to: Work around the access denied cross-domain IFRAME issue in the AJAX Control Toolkit]

Bertrand recently blogged "How to work around the access denied cross-domain frame issue in ASP.NET Ajax 1.0". Unfortunately, a similar issue exists in the AJAX Control Toolkit - with a similar workaround that's detailed in this post.

Background: The AJAX Control Toolkit attempts to use as much of the ASP.NET AJAX infrastructure as possible in order to keep things simple and benefit from the established architecture of ASP.NET AJAX. However, the ASP.NET AJAX 1.0 implementation of Sys.UI.getLocation was not accurate for IFRAME content with certain page layouts in IE6 - one of which was used by the Toolkit test harness. We couldn't have our automated tests failing - and the ASP.NET AJAX team wasn't able to include a fix in their 1.0 release - so we needed to address this somehow. Since we had developed our own getLocation implementation that was accurate in IE6, we decided to route all Toolkit calls to getLocation through our own wrapper function - which used our improved implementation for IE6 and called through to the ASP.NET AJAX implementation for everything else. This works pretty well - except that our version suffers from the same cross-domain permissions issue that the ASP.NET AJAX version suffers from (please refer to Bertrand's post for more details).

Fix: We've just checked in a fix to the Toolkit's Development branch to add the same try/catch wrapper that Bertrand suggests; this fix will be included with the next Toolkit release (in about a month). In the meantime, people who want the fix sooner are encouraged to apply the changes themselves. To do so, open AjaxControlToolkit.sln in Visual Studio, open the file AjaxControlToolkit\Common\Common.js, find the getLocation function, add the yellow, italic block below, and build the project to get a new AjaxControlToolkit.dll with the fix. The complete function definition with the fix applied is included here to make this as easy as possible:

getLocation : function(element) {
    
/// <summary>Gets the coordinates of a DOM element.</summary>
    /// <param name="element" domElement="true"/>
    /// <returns type="Sys.UI.Point">
    ///   A Point object with two fields, x and y, which contain the pixel coordinates of the element.
    /// </returns>

    // workaround for an issue in getLocation where it will compute the location of the document element.
    // this will return an offset if scrolled.
    //
    if (element === document.documentElement) {
        
return new Sys.UI.Point(0,0);
    }

    
// Workaround for IE6 bug in getLocation (also required patching getBounds - remove that fix when this is removed)
    if (Sys.Browser.agent == Sys.Browser.InternetExplorer && Sys.Browser.version < 7) {
        
if (element.window === element || element.nodeType === 9 || !element.getClientRects || !element.getBoundingClientRect) return new Sys.UI.Point(0,0);

        
// Get the first bounding rectangle in screen coordinates
        var screenRects = element.getClientRects();
        
if (!screenRects || !screenRects.length) {
            
return new Sys.UI.Point(0,0);
        }
        
var first = screenRects[0];

        
// Delta between client coords and screen coords
        var dLeft = 0;
        
var dTop = 0;

        var inFrame = false;
        
try {
            inFrame = element.ownerDocument.parentWindow.frameElement;
        }
catch(ex) {
            
// If accessing the frameElement fails, a frame is probably in a different
            // domain than its parent - and we still want to do the calculation below
            inFrame = true;
        }

        
// If we're in a frame, get client coordinates too so we can compute the delta
        if (inFrame) {
            // Get the bounding rectangle in client coords
            var clientRect = element.getBoundingClientRect();
            
if (!clientRect) {
                
return new Sys.UI.Point(0,0);
            }

            
// Find the minima in screen coords
            var minLeft = first.left;
            
var minTop = first.top;
            
for (var i = 1; i < screenRects.length; i++) {
                
var r = screenRects[i];
                
if (r.left < minLeft) {
                    minLeft = r.left;
                }
                
if (r.top < minTop) {
                    minTop = r.top;
                }
            }

            
// Compute the delta between screen and client coords
            dLeft = minLeft - clientRect.left;
            dTop = minTop - clientRect.top;
        }

        
// Subtract 2px, the border of the viewport (It can be changed in IE6 by applying a border style to the HTML element,
        // but this is not supported by ASP.NET AJAX, and it cannot be changed in IE7.), and also subtract the delta between
        // screen coords and client coords
        var ownerDocument = element.document.documentElement;
        
return new Sys.UI.Point(first.left - 2 - dLeft + ownerDocument.scrollLeft, first.top - 2 - dTop + ownerDocument.scrollTop);
    }

    
return Sys.UI.DomElement.getLocation(element);
},

Sorry for the trouble - we hope this patch helps any people who might be running into this issue!

Updated at 6pm: Modified the getLocation implementation to return the correct value in all cases.

A quick update to address some top customer issues [AJAX Control Toolkit update!]

Just a few moments ago we made available the 10201 release of the AJAX Control Toolkit to address some of the most significant issues reported since the 10123 release last week. We chose these issues based on feedback from our users in our support forum and online issue tracker and tried to prioritize issues with widespread benefits while minimizing the risks of breaking anything.

In particular, we:

  • Fixed problems that occurred when using the new AutoComplete or Tabs controls inside an UpdatePanel
  • Improved the localization behavior of the Calendar so that it works better in other countries/time zones
  • Simplified and improved the implementation of the new "draggable popup" feature of ModalPopup
  • Addressed a TextBoxWatermark focus issue that was inconveniencing users

Recall that you can sample any of the controls right now (no install required). You can also browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum (or email me)!

ASP.NET AJAX 1.0 is on the loose! [AJAX Control Toolkit update!]

Earlier today we made available the 10123 release of the AJAX Control Toolkit. We did this in parallel with the official release of ASP.NET AJAX v1.0 and added a bunch of good stuff along the way.

As I note in the release teaser, "This release of the AJAX Control Toolkit includes four new controls (AutoComplete (formerly in the Futures CTP), Calendar, MaskedEdit, and Tabs), fixes for over 75 issues reported by the community, and new functionality for ModalPopup, RoundedCorners, and the ExtenderBase framework." Additionally, we spent time making sure that all 32 Toolkit controls work well on the latest version of the Opera browser. Accepting that every browser has its little quirks, we now offer the same level of "pretty much everything works" support for Internet Explorer 6, Internet Explorer 7, Firefox 1.5, Firefox 2.0, Safari 2.0.4, and Opera 9.10. Those are the top six browsers on the Internet, so there's an very good chance that visitors to a Toolkit-enabled site will be running a supported browser.

Of note, three of the four new controls for this release were submitted by contributors! Ron Buckton wrote both Calendar and Tabs while Fernando Cerqueira wrote MaskedEdit. These are some very cool new controls and we're fortunate to have such great contributors helping out with the Toolkit! As a teaser, I created two little "movies" to show off Calendar and MaskedEdit in action - as well as our Opera support. :)

Calendar Demonstration

MaskedEdit Demonstration

Recall that you can sample any of the controls right now (no install required). You can also browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum (or email me)!

Runnin' on the RC [AJAX Control Toolkit update!]

A few minutes ago we made available the 61214 release of the AJAX Control Toolkit. We did this in parallel with the release of the ASP.NET AJAX v1.0 RC in order to accommodate some breaking changes introduced in that release. Though we did not make any functional changes to the Toolkit in this release, we did take the opportunity to fix a handful of bugs that we'd found.

Recall that you can sample any of the controls right now (no install required). Then you can browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum (or email me)!

Dynamic content made easy *remix* [How to: Use the new dynamic population support for Toolkit controls]

I previously blogged an update to my sample demonstrating how to use the AJAX Control Toolkit's dynamic population functionality with a data-bound ModalPopup. Someone asked privately what the C# page method would look like in VB, so I figured I'd post a small follow-up to show the straightforward translation to VB.

Here's the original C# code for reference:

<script runat="server">
[System.Web.Services.WebMethod]
[Microsoft.Web.Script.Services.
ScriptMethod]
public static string GetContent(string contextKey)
{
    
// Create a random color
    string color = (new Random()).Next(0xffffff).ToString("x6");
    
// Use the style specified by the page author
    string style = contextKey;
    
// Display the current time
    string time = DateTime.Now.ToLongTimeString();
    
// Compose the content to return
    return "<span style='color:#" + color + "; " + style + "'>" + time + "</span> ";
}
</script>

Translating that to VB is largely a matter of changing the syntactic elements from their C# versions to their VB versions. So "[" becomes "<", "}" becomes "End Function", and so on... Two things that tripped me up because I don't regularly use VB were the translation of the hexadecimal prefix "0x" to "&H" and the translation of "static" to "Shared" - but a quick look at the online documentation for VB sorted me out on both counts. After a short while, I ended up with this:

<script runat="server">
    <System.Web.Services.WebMethod()> _
    <Microsoft.Web.Script.Services.ScriptMethod()> _
    
Public Shared Function GetContent(ByVal contextKey As String) As String
        ' Create a random color
        Dim color As String = (New Random()).Next(&HFFFFFF).ToString("x6")
        
' Use the style specified by the page author
        Dim style As String = contextKey
        
' Display the current time
        Dim time As String = DateTime.Now.ToLongTimeString()
        
' Compose the content to return
        Return "<span style='color:#" + color + "; " + style + "'>" + time + "</span> "
    End Function
</
script>

I completed the translation by changing the sample page's Page/Language property from "C#" to "VB", ran the sample page, and verified that it worked just like it did before. Of course! :)

Another quick, small-scale release [AJAX Control Toolkit update!]

Just a short while ago we made available the 61121 release of the AJAX Control Toolkit. I'd barely finished posting the release bits to CodePlex and was still in the process of verifying them when I saw that we'd already had our first eight customer downloads. Wow, those people must really want the latest stuff! :)

The 61121 release was all about addressing some of the biggest pain points for our customers. Of particular note were two workarounds for ASP.NET AJAX Beta 2 issues:

  • The first addresses an issue where the Toolkit had a hard dependency on Microsoft.Web.Extensions.Design.dll, a file that isn't installed by ASP.NET AJAX Beta 2 on machines that don't have some flavor of Visual Studio already installed. This dependency can cause obvious issues for web servers since they usually do not have development tools like Visual Studio installed.
  • The second addresses an issue where ASP.NET AJAX Beta 2 doesn't render the ScriptManager/extenders out to the page during an async postback if EnableEventValidation=false - meaning that the relevant extenders simply don't get recreated after an UpdatePanel postback. We reported this issue to the ASP.NET AJAX team prior to Beta 2, but there wasn't time for them to fix it in that release (don't worry, they'll be fixing it in their next release!). We'd implemented a workaround for this issue in our earlier 61106 release, but it applied only to CascadingDropDown (which is the only control that requires EnableEventValidation=false). Subsequent customer feedback prompted us to move that workaround up a level for this release so that it now applies to the entire Toolkit.

In addition to those two "big ticket" items, we also fixed a handful of other issues, most of which we chose based on customer feedback and work item voting on CodePlex. (Voting is a fairly recent addition - have a look at how it focuses attention on issues that are important to the community!). The other fixes in the 61121 release address the most popular issues in our CodePlex queue and include fixes for ModalPopup server-side show/hide, ClientState within an UpdatePanel, Accordion pane size updates, multiple DragDrop panels, CommonToolkitScripts, and web.config updates to get things working seamlessly with IIS7.

This being small-scale release, we didn't have time to include any new controls this time around. :( However, that's an explicit goal for an upcoming release which we hope to make available before the end of the year. We've got some neat stuff in the prototype stage and it'll be great to get some of it polished and released to the world!

Recall that you can sample any of the controls right now (no install required). Then you can browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum (or email me)!

Dynamic content made easy *redux* [How to: Use the new dynamic population support for Toolkit controls]

I previously blogged a sample demonstrating how to use the AJAX Control Toolkit's dynamic population functionality with a data-bound ModalPopup. That sample was well received, but some of the changes that happened as part of the ASP.NET AJAX Beta 1 and Beta 2 releases have rendered the sample code I originally posted un-runnable on current builds.

No worries - it's a simple matter to update the sample and the exercise should serve as a good example of some of the things that need to be done as part of an upgrade. (For a far more in depth guide to upgrading, please refer to Shawn's AJAX Control Toolkit Migration Guide and follow-up about upgrading Web Services/Methods.)

Referring to the sample code I posted earlier as a starting point, the 5 things we need to do to update it are:

  1. Change the tag prefix for ScriptManager from "atlas" to "asp" to point to the new location for ScriptManager
  2. Change the @Register tag to refer to the AjaxControlToolkit by its new name ("AtlasControlToolkit"->"AjaxControlToolkit" twice and "atlasToolkit"->"ajaxToolkit" once)
  3. Change the corresponding tag prefix for ModalPopupExtender from "atlasToolkit" to "ajaxToolkit"
  4. Copy the properties of the ModalPopupProperties element to the ModalPopupExtender element and remove the empty ModalPopupProperties element now that the XxxProperties elements are no longer used
  5. Update the web method definition by making the GetContent method static and adding the [Microsoft.Web.Script.Services.ScriptMethod] attribute

That's it! As you can see, it's mostly simple "find-and-replace" naming changes that can easily be applied to an entire site at once. The XxxProperties change is slightly more involved, but requires very little effort since it's basically just a "cut-and-paste" operation. The web method changes are also a little bit of effort, but the changes themselves are simple and it's easy to find where to make them by searching for the pre-existing "WebMethod" attribute. Nothing here is risky or error-prone and - with the exception of the web method changes - the compiler will report all of them as errors until they're fixed correctly.

For completeness, here's a reminder of what dynamic population looks like in action:

Animated demonstration

And here's the complete sample code after the changes discussed above have been applied. This sample runs fine on the ASP.NET AJAX Beta 2 and the AJAX Control Toolkit 61106 release:

<%@ Page Language="C#" %>
<%
@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
  TagPrefix="ajaxToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<
script runat="server">
  [System.Web.Services.WebMethod]
  [Microsoft.Web.Script.Services.
ScriptMethod]
  
public static string GetContent(string contextKey)
  {
    
// Create a random color
    string color = (new Random()).Next(0xffffff).ToString("x6");
    
// Use the style specified by the page author
    string style = contextKey;
    
// Display the current time
    string time = DateTime.Now.ToLongTimeString();
    
// Compose the content to return
    return "<span style='color:#" + color + "; " + style + "'>" + time + "</span> ";
  }
</script>

<
html xmlns="http://www.w3.org/1999/xhtml">
<
head id="Head1" runat="server">
  <title>Dynamic ModalPopup Demonstration</title>

  <%-- Style the page so it looks pretty --%>
  
<style type="text/css">
    body { font-family:Verdana;     font-size:10pt; }
    
.background { background-color:Gray; }
    
.popup { width:200px;             padding:10px;        background-color:White;
            
border-style:solid;      border-color:Black;  border-width:2px;
            
vertical-align: middle;  text-align:center; }
  
</style>
</
head>
<
body>
  <form id="form1" runat="server">

    <%-- Atlas pages need a ScriptManager --%>
    
<asp:ScriptManager ID="ScriptManager1" runat="server" />

    <%-- A very simple data source to drive the demonstration --%>
    
<asp:XmlDataSource ID="XmlDataSource1" runat="server">
      <Data>
        <items>
          <item style="font-weight:bold" />
          <item style="font-style:italic" />
          <item style="text-decoration:underline" />
        </items>
      </Data>
    </asp:XmlDataSource>

    <%-- A simple list of all the data items available --%>
    
<asp:DataList ID="DataList1" runat="server" DataSourceID="XmlDataSource1">

      <HeaderTemplate>
        How would you like your dynamic content styled?
      
</HeaderTemplate>

      <ItemTemplate>
        &bull; <asp:LinkButton ID="LinkButton" runat="server" Text='<%# Eval("style") %>' />

        <%-- The ModalPopupExtender, popping up Panel1 and dynamically populating Panel2 --%>
        
<ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender" runat="server"
            TargetControlID="LinkButton" PopupControlID="Panel1" OkControlID="Button1"
            BackgroundCssClass="background" DynamicControlID="Panel2"
            DynamicContextKey='<%# Eval("style") %>' DynamicServiceMethod="GetContent" />
      </ItemTemplate>

    </asp:DataList>

    <%-- All ModalPopups share the same popup --%>
    
<asp:Panel ID="Panel1" runat="server" CssClass="popup" style="display:none;">
      <p>This popup popped at <asp:Label ID="Panel2" runat="server" /> and all was well.</p>
      <p><asp:Button ID="Button1" runat="server" Text="OK" /></p>
    </asp:Panel>

  </form>
</
body>
</
html>

Enjoy!

Just what it takes for Beta 2 [AJAX Control Toolkit update!]

On Monday we made available the 61106 release of the AJAX Control Toolkit. We did this in parallel with the release of ASP.NET AJAX v1.0 Beta 2 in order to accommodate some breaking changes introduced in that release. As such, we did not make any functional changes to the Toolkit in the 61106 release, though we did take the opportunity to fix one or two small bugs that we'd found.

Recall that you can sample any of the controls right now (no install required). Then you can browse the project web site, download the latest Toolkit, and start creating your own controls and/or contributing to the project!

If you have any feedback, please share it with us on the support forum (or email me)!

Talked Toolkit [Spoke at the ASP.NET Connections conference]

As I blogged earlier, I presented the AMS302: "Atlas" AJAX Control Toolkit Unleashed: Creating Rich Client-Side Controls and Components session at the Microsoft ASP.NET Connections conference a few hours ago. This was my first ever presentation at a conference and it was a lot of fun! I hope those of you who attended enjoyed the talk and learned more about the Toolkit - it was great to have an opportunity to talk to you in person!

I've attached my slide deck and the demo content to this post so that anyone who's interested can download it and play around on their own machines.

We're always looking for more contributors and additional control ideas, so please let me know if you want to contribute!

[AMS302-AjaxControlToolkit.zip]