Archives

Archives / 2007 / August
  • Online JavaScript Compression Tool

    Compressing JavaScript code is useful when you want to minimize the size of files that get downloaded to the client.  This is especially true with AJAX applications that may rely on several scripts to function properly.

    I was playing around with Douglas Crockford's JsMin code last night and decided to put together an online version that people could use on my XML for ASP.NET Website.  It's not throughly tested at this point, but feel free to try it out and let me know of any issues.  The tool can be found at the following URL:

    http://www.xmlforasp.net/JSCompressor.aspx

    Read more...

  • Integrate Windows Live ID Authentication Into Your Website

    Microsoft recently released an SDK that allows you to integrate Windows Live ID authentication into your Website (ASP.NET or any other).  To get started you'll need to register your application and get an application ID.  From there it's quite straightforward especially since a sample application that uses Windows Live ID is available to download.  Sample code is available for ASP.NET, Java, Perl, PHP, Python, and Ruby.

    Read more...

  • Video How To: Getting Started with Subversion and Source Control

    In this video "how to" I walk through the steps required to install and configure Subversion to control your .NET source code revisions.  Several commercial options exist for source control of course such as Vault and Microsoft's Visual SourceSafe to name just two.  Subversion is an open source project (it's freely available) and has excellent documentation and support available.  It's also easy to use through the command-line or through TortoiseSVN.

    In the video you'll see how to install Subversion, configure it, install the TCP/IP service, and add new or existing projects into the source control repository.  You'll also see how to use TortoiseSVN to create repositories and manipulate files in a Subversion repository. Although the video discusses installing the TCP/IP service for accessing a repository remotely, it doesn't cover how to access the repository through HTTP.  You can find more information about that task and how to configure it with Apache here.

    Links mentioned in the video are included below:

    Subversion Project Site:  http://subversion.tigris.org

    Rick Strahl's Step-By-Step Subversion Article:  http://www.west-wind.com/presentations/subversion/

    Subversion Online Book: http://svnbook.red-bean.com/nightly/en/index.html

    Getting Started with Subversion and Source Control

    Click here to view in Windows Media Player (right-click and you can save the file)

     

    Read more...

  • Upcoming Controls in Silverlight 1.1

    I hadn't heard much lately about what controls will ship when Silverlight 1.1 is finally released.  Microsoft's Tim Heuer and I were chatting and he pointed me to Mike Ormond's blog which answers the question.  Good information to know for those of you interested in Silverlight.  Tim also blogged about 3rd party controls that will be released for Silverlight as well.  Exciting times!

     http://blogs.msdn.com/mikeormond/archive/2007/08/08/silverlight-controls.aspx

    Read more...

  • How To: Create an ASP.NET AJAX Toolkit Extender Control to Extend a GridView

    In a previous post I showed examples of how CSS and JavaScript code could be used to freeze the header row of a GridView control and add scrolling capabilities for Internet Explorer and Firefox. Here’s an example of a GridView with a frozen header:

    In this post I’m going to discuss how to package up CSS and JavaScript files into a custom control that can be used on the server-side to extend the GridView. Doing this allows you to continue using the standard GridView that ships with ASP.NET 2.0 in applications while extending it’s functionality through a custom extender control.

    There are multiple ways to go about creating an AJAX control extender. You can use native classes available in the ASP.NET AJAX Extensions to build a control that would get the job done. However, doing so requires that you write custom code to map server-side properties to client-side properties which isn’t hard. Additional details on how to do this can be found in the ASP.NET 2.0 Professional AJAX book Matt Gibbs and I co-authored. You can download the code from the book here if you’d like to see the sample code (see the chapter 11 code).

    To simplify things as much as possible, I’m going to discuss how to build a custom control that is based upon the ASP.NET AJAX Control Toolkit available from http://www.codeplex/com/AtlasControlToolkit (that’s not a typo, they never changed the Atlas name to AJAX in the URL for some reason). The ASP.NET AJAX Control Toolkit provides a base class named ExtenderControlBase along with several attribute classes that minimize the amount of code that has to be written create a control extender.  Here's the steps I went through to make the control.

    1. Create a new Class Library Project in VS.NET

    Create a class library project in VS.NET.  Add the AjaxControlToolkit.dll file to the bin folder and add a reference to the assembly using the "Add Reference" dialog.  I also added references to the System.Web and System.Web.Extensions assemblies.

    2. Create the Behavior Script that the Extender Control will Output.

    Add a new JavaScript file into the project (I named mine GridViewHeaderBehavior.js).  Here's the entire script I used for the frozen header extender control.  I started out by writing JavaScript in a page to get the code working properly first and then converted the code to the "prototype design pattern" as shown next.  This leverages functionality in the ASP.NET AJAX and ASP.NET AJAX Toolkit script libraries.

    Type.registerNamespace('WahlinControlToolkit');
    
    WahlinControlToolkit.GridViewHeaderBehavior = function(element) {
        /// <summary>
        /// The GridViewHeaderBehavior is used to fix a GridView control header and make the 
    /// control scrollable
    /// </summary> /// <param name="element" type="Sys.UI.DomElement"> /// The GridView element this behavior is associated with /// </param> WahlinControlToolkit.GridViewHeaderBehavior.initializeBase(this, [element]); this._WrapperDivCssClass = null; } WahlinControlToolkit.GridViewHeaderBehavior.prototype = { initialize : function() { /// <summary> /// Initialize the behavior /// </summary> WahlinControlToolkit.GridViewHeaderBehavior.callBaseMethod(this, 'initialize'); var element = this.get_element(); this._FreezeGridViewHeader(); }, dispose : function() { /// <summary> /// Dispose the behavior /// </summary> var element = this.get_element(); WahlinControlToolkit.GridViewHeaderBehavior.callBaseMethod(this, 'dispose'); }, _FreezeGridViewHeader : function () { var grid = this.get_element(); if (grid != 'undefined') { grid.style.visibility = 'hidden'; var div = null; if (grid.parentNode != 'undefined') { div = grid.parentNode; if (div.tagName == 'DIV') { div.className = this._WrapperDivCssClass; div.style.overflow = 'auto'; } } var tags = grid.getElementsByTagName('TBODY'); if (tags != 'undefined') { var tbody = tags[0]; var trs = tbody.getElementsByTagName('TR'); var headerHeight = 8; if (trs != 'undefined') { headerHeight += trs[0].offsetHeight; var headTR = tbody.removeChild(trs[0]); var head = document.createElement('THEAD'); head.appendChild(headTR); grid.insertBefore(head, grid.firstChild); } tbody.style.height = (div.offsetHeight - headerHeight) + 'px'; tbody.style.overflowX = 'hidden'; tbody.overflow = 'auto'; tbody.overflowX = 'hidden'; } grid.style.visibility = 'visible'; } }, get_WrapperDivCssClass : function() { return this._WrapperDivCssClass; }, set_WrapperDivCssClass : function(value) { this._WrapperDivCssClass = value; this.raisePropertyChanged('WrapperDivCssClass'); } } WahlinControlToolkit.GridViewHeaderBehavior.registerClass
    ('WahlinControlToolkit.GridViewHeaderBehavior', AjaxControlToolkit.BehaviorBase);

     

    3. Mark the Script as an Embedded Resource in VS.NET

    Right-click on the JavaScript file in the Solution Explorer and select Properties from the menu.  Change the Build Action property to "Embedded Resource".  This will embed the script into the extender control assembly so that you don't have to worry about deploying it as a standalone file.

    4. Add the Control Extender Class into the Project

    Add a new class into the project (I named mine GridViewHeaderExtender.cs).  The class imports the AjaxControlToolkit namespace and derives from ExtenderControlBase which is a class provided by the ASP.NET AJAX Toolkit assembly (AjaxControlToolkit.dll).  You can have the control automatically output the script mentioned in the previous steps to the client by using the WebResource attribute along with the ClientScriptResource attribute as shown next.  The control (named GridViewHeaderExtender) exposes a single property named WrapperDivCssClass that represents the CSS class that will be applied to the div that wraps the GridView control.

    The control also overrides OnPreRender() in order to dynamically output two CSS classes into the page that are needed to help freeze the GridView header row.  This is done by calling the CreateStyleRule() method which relies on two custom style classes to generate the necessary CSS data.  The complete  code for the GridViewHeaderExtender is shown next:

    using System;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    using System.Web.UI;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using AjaxControlToolkit;
    
    [assembly: WebResource("WahlinControlToolkit.GridViewHeaderBehavior.js", "text/javascript")]
    
    namespace WahlinControlToolkit
    {
    
        [TargetControlType(typeof(GridView))]
        [ClientScriptResource("WahlinControlToolkit.GridViewHeaderBehavior", 
    "WahlinControlToolkit.GridViewHeaderBehavior.js")] [ToolboxItem("System.Web.UI.Design.WebControlToolboxItem,
    System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    )] public class GridViewHeaderExtender : ExtenderControlBase { [DefaultValue("")] [Description("CSS class to apply to the GridView wrapper div element. Example of a
    wrapper div style: .WrapperDiv {width:800px;height:400px;border: 1px solid black;}"
    )] [ExtenderControlProperty] [ClientPropertyName("WrapperDivCssClass")] public string WrapperDivCssClass { get { return GetPropertyValue<string>("WrapperDivCssClass", string.Empty); } set { SetPropertyValue<string>("WrapperDivCssClass", value); } } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (String.IsNullOrEmpty(this.WrapperDivCssClass)) { throw new ApplicationException("WrapperDivCssClass property value must be defined for the GridViewHeaderExtender control. Here's an example of a wrapper div style that should be defined in the page and referenced with the WrapperDivCssClass property: .WrapperDiv {width:800px;height:400px;border: 1px solid black;}"); } if (this.Enabled && !this.Page.Items.Contains("GridViewHeaderStyles")) { this.Page.Items["GridViewHeaderStyles"] = true; this.Page.Header.StyleSheet.CreateStyleRule(new GridViewThCssClass(),
    null
    , "." + this.WrapperDivCssClass + " TH"); this.Page.Header.StyleSheet.CreateStyleRule(new GridViewTrCssClass(),
    null
    , "." + this.WrapperDivCssClass + " TR"); } } private class GridViewTrCssClass : Style { protected override void FillStyleAttributes(CssStyleCollection attributes,
    IUrlResolutionService
    urlResolver) { base.FillStyleAttributes(attributes, urlResolver); attributes[HtmlTextWriterStyle.Height] = "0px"; } } private class GridViewThCssClass : Style { protected override void FillStyleAttributes(CssStyleCollection attributes,
    IUrlResolutionService
    urlResolver) { base.FillStyleAttributes(attributes, urlResolver); attributes[HtmlTextWriterStyle.Position] = "relative"; } } } }

    5. Create a Website and Reference the Extender Control Assembly

    Once the extender control is compiled and the assembly is ready to use, you need to reference it in the page that needs to extend a GridView (or you can define it in web.config if you'd like all pages to use it).  This is done by adding the following code into the page:

    <%@ Register  Assembly="WahlinControlToolkit" Namespace="WahlinControlToolkit" 
    TagPrefix
    ="toolkit" %>

     

    6. Define the Wrapper Div CSS Class Used by the Extender Control

    Once the extender control has been referenced you'll need to define the CSS class that will be used to wrap the GridView control (add borders around it if desired, set height and width, etc.) in the page or in an external CSS stylesheet:

    <style type="text/css">
        .WrapperDiv {
            width:800px;height:400px;border: 1px solid black;
        }        
    </style>

     

    7. Use the Extender Control in the Page to Extend the GridView Control and Freeze the Header Row

    Add the extender control into to the page:

    <toolkit:GridViewHeaderExtender ID="gvExtender" runat="server" 
         TargetControlID="GridView1" WrapperDivCssClass="WrapperDiv"/>


    And there you have it!  The hardest part of building an extender control is getting the script to do what you want.  After you get the script working properly, the actual extender control class is pretty simple to write since you can leverage existing functionality in the ASP.NET AJAX Toolkit.  I'm considering making a video that covers these concepts so if I get some free time I'll post it here (no promises though :-)).

    All of the code discussed in this post can be downloaded here.  If you enhance it in some way, fix any bugs that are discovered, or add additional functionality please let me know about it and I'll get the code base updated with your changes.

    Read more...

  • Fixing a VS.NET 2008 Beta 2 ASP.NET Debugging Issue on Vista: "Strong name validation failed"

    I came across the following error while trying to debug an ASP.NET page in VS.NET 2008 tonight: "Unable to start debugging on the web server. Strong name validation failed."  I hadn't seen the error before but after spending a few seconds searching I came across the following steps that seem to have solved the problem.  I found the steps here.  Since this is documented I'm hoping it'll be resolved by the final release of VS.NET 2008. 

    Having used VS.NET 2008 for a week now I have to say I'm extremely impressed with it and have found it to be very stable.....and super productive.

    Update: If you're running a 64-bit installation of Vista you'll need to use the sn.exe located at C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\x64\sn.exe.

    2.3.5.2 Strong name validation failed error when launching IIS project on Windows Vista

    When a Web project is run on Windows Vista, it may fail to start and the following error may be shown: "Unable to start debugging on the web server. Strong name validation failed. Click Help for more information."

    To resolve this issue:

    Disable strong name validation for a Visual Studio file (iisresolver.dll) by doing the following:

    1. Click on Start, All Programs, Accessories, Command Prompt, and then select  Run as administrator
    2. You may see the screen grey and a 'User Account Control' dialog box appear. If this happens, click Continue so that the command prompt starts.

    3. Obtain a copy of sn.exe. Sn.exe installed with Visual Studio 2005, and the .NET Framework 2.0 SDK, and therefore it may already be on the computer. If it is not on the computer, then download .NET Framework 2.0 SDK to obtain it. The x86 version of the Software development kit can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyID=FE6F2099-B7B4-4F47-A244-C96D69C35DEC. The x64 version of the SDK can be downloaded from http://www.microsoft.com/downloads/details.aspx?FamilyId=1AEF6FCE-6E06-4B66-AFE4-9AAD3C835D3D.
    4. Run one of the following commands, as appropriate:

    32-bit computer:
    "<path_to_sn>\sn.exe" -Vr "%ProgramFiles%\Microsoft Visual Studio 9.0\Common7\IDE\iisresolver.dll"

    64-bit computer:
    "<path_to_sn>\sn.exe" -Vr "%ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Common7\IDE\iisresolver.dll"

    This assumes that Visual Studio was installed to the default location. If Visual Studio was installed to a custom location, then '%ProgramFiles%\Microsoft Visual Studio 9.0' should be replaced with the path where Visual Studio was installed.

    Read more...

  • Video: Using the New ASP.NET ListView Control

    ASP.NET 3.5 introduces a new control called the ListView that allows developers to have 100% control over the HTML markup that is generated while still providing paging, inserting, updating, and deleting support. To me the ListView control is a nice blend between the GridView and Repeater controls with new features added.

    In this video I walk through the fundamentals of using the ListView control and show how you can use the new CSS tools in VS.NET 2008 to create a scrollable ListView control with a frozen header. See my previous blog post if you're interested in learning how to freeze GridView control headers in IE and FireFox.

      
    View the Video

     

     

    Read more...

  • Freeze ASP.NET GridView Headers by Creating Client-Side Extenders

    Lately I've been working on a pet project where I needed to freeze a GridView header so that it didn't move while the grid records were scrolled by an end user.  After searching the Web I came across a lot of "pure" CSS ways to freeze a header.  After researching them more they tend to rely on a lot of CSS hacks to do the job and require HTML to be structured in a custom way.  I also found a lot of custom GridView classes (another one here), and more.  Some of the solutions were really good while others seemed a bit over the top and required a lot of custom C# or VB.NET code just to do something as simple as freezing a header.  Freezing a header requires CSS and potentially JavaScript depending upon what needs done.  Regardless if CSS or JavaScript are used, these are client-side technologies of course.  I started to write my own derivative of the GridView class but quickly realized that it made more sense to use the standard GridView control and simply extend it from the client-side.  An example of what I was after is shown next:



    In the past I've always made a scrollable GridView by wrapping a <div> tag around the control, adding a table with header rows inside the <div> (but above the GridView control code), and setting the CSS overflow property on the wrapper div to "auto".  Scott Mitchell has a nice article on doing this with a DataGrid and you can see a sample of doing something like that at my XML for ASP.NET Developers Website if you're interested.  This technique works well but makes it a bit hard to line up the header and child rows perfectly (although it can be done).

    I decided to build my own client-side GridView "extender" code to accomplish the task since I didn't want to worry about yet another GridView assembly being in my toolbox just to freeze a header.  It appears to work great in IE6+ and Firefox 2 (haven't tried FireFox 1 – 1.5) although I'm sure there are some ways it could be improved and I can't say I've done extensive testing.  The code basically grabs the first header row from the GridView using JavaScript and moves it inside of a THEAD tag so that CSS can easily be applied to all of the TH tags and things work well in FireFox.  It then applies a few styles to the appropriate items within the GridView HTML that is generated. 

    The JavaScript and CSS code is shown below.  On online version can be viewed here.

    <style type="text/css">
        
    .WrapperDiv {
            width
    :800px;height:400px;border: 1px solid black;
        
    }        
        
    .WrapperDiv TH {
            position
    :relative;
        
    }
        
    .WrapperDiv TR 
        
    {
            
    /* Needed for IE */
            height
    :0px;
        

    </
    style>
    <script>
        
    function onLoad()
        {
            FreezeGridViewHeader(
    'GridView1','WrapperDiv');
        
    }    
        
        
        
    function FreezeGridViewHeader(gridID,wrapperDivCssClass) 
        {
            
    /// <summary>
            ///   Used to create a fixed GridView header and allow scrolling
            /// </summary>
            /// <param name="gridID" type="String">
            ///   Client-side ID of the GridView control
            /// </param>
            /// <param name="wrapperDivCssClass" type="String">
            ///   CSS class to be applied to the GridView's wrapper div element.  
            ///   Class MUST specify the CSS height and width properties.  
            ///   Example: width:800px;height:400px;border:1px solid black;
            /// </param>
            
    var grid = document.getElementById(gridID);
            if 
    (grid !'undefined')
            {
                grid.style.visibility 
    'hidden';
                var 
    div = null;
                if 
    (grid.parentNode !'undefined'
                {
                    
    //Find wrapper div output by GridView
                    
    div grid.parentNode;
                    if 
    (div.tagName == "DIV")
                    {
                        div.className 
    wrapperDivCssClass;  
                        
    div.style.overflow "auto";                   
                    
    }
                }                
                
    //Find DOM TBODY element and remove first TR tag from 
                //it and add to a THEAD element instead so CSS styles
                //can be applied properly in both IE and FireFox
                
    var tags grid.getElementsByTagName('TBODY');
                if 
    (tags !'undefined')
                {
                    
    var tbody tags[0];
                    var 
    trs tbody.getElementsByTagName('TR');
                    var 
    headerHeight 8;
                    if 
    (trs !'undefined'
                    {
                        headerHeight +
    trs[0].offsetHeight;
                        var 
    headTR tbody.removeChild(trs[0]);
                        var 
    head = document.createElement('THEAD');
                        
    head.appendChild(headTR);
                        
    grid.insertBefore(head, grid.firstChild);
                    
    }
                    
    //Needed for Firefox
                    
    tbody.style.height 
                      
    (div.offsetHeight -  headerHeight) + 'px';
                    
    tbody.style.overflowX "hidden";
                    
    tbody.overflow 'auto';
                    
    tbody.overflowX 'hidden';
                
    }
                grid.style.visibility 
    'visible';
            
    }
        }
    </script>


    This solution works well but it means I'd have to reference a CSS file and JavaScript file for each GridView control that needs a frozen header.  I decided to build an ASP.NET AJAX Extender control based upon the ASP.NET AJAX Toolkit which turned out to be fairly straightforward.  This means that I have to reference an assembly in my project (which I complained about above), but I can still use the stock GridView control.  I'll talk more about the extender control  (called GridViewHeaderExtender) in a future post.  Those interested in seeing the code can download it here.  The extender seems to work great with IE6+ and FireFox 2 but doesn't work with Safari on Windows (very few of the frozen header solutions I found online worked with Safari). 

    Update:  Matt Berseth recently blogged about freezing GridView headers that are rendered using ControlAdapters.  Read more about his technique here.

    Read more...

comments powered by Disqus