Microsoft Most Valuable Professional

Chris Pietschmann

An MVP From Wisconsin

ASP.NET 3.5: Create AJAX Extender Controls using the ExtenderControl base class

As a followup to the "Create AJAX Server Controls using the ScriptControl base class" post I wrote a couple weeks ago, I've decided to write on how to create ASP.NET AJAX Extender Controls using the ExtenderControl base class in ASP.NET 3.5. There is already an article titled "Adding ASP.NET AJAX Client Behaviors to Web Server Controls" in MSDN, but it doesn't show all the code involved in creating Extender Controls, especially the JavaScript code.

What is an Extender Control?

First what exactly is an Extender Control? An Extender Control is basically a non-visual control that adds some sort of AJAX behavior to another control within the page. The majority of the controls within the AjaxControlToolkit are built as Extender Controls. It is a common misconception that you can only create Extender Controls by using the base classes within the AjaxControlToolkit, but in fact ASP.NET 3.5 contains the required ExtenderControl base class to create Extender Controls.

The base class I'm referring to in this article is the System.Web.UI.ExtenderControl base class located within the System.Web.Extensions.dll assembly.

According to MSDN the ExtenderControl class is:

The ExtenderControl class enables you to programmatically add AJAX functionality to an ASP.NET server control. The ExtenderControl inherits from the Control class and implements the IExtenderControl interface. The Control class defines the properties, methods, and events that are shared by all ASP.NET server controls. The IExtenderControl interface is an abstract class, which you cannot instantiate directly. Instead, you create a derived type.

Basics of created Extender Controls that Inherit from ExtenderControl

When first creating your custom extender control you need to inherit from the ExtenderControl base class. The first thing you'll see is the ExtenderControl requires you to implement to methods: GetScriptDescriptors and GetScriptReferences. The GetScriptDescriptors method is used to get an IEnumerable collection of ScriptDescriptor objects that basically define any of the controls client-side AJAX properties. The GetScriptReferences method is used to get an IEnumerable collection of ECMAScript (JavaScript) files that will be loaded on the client-side once the page loads; this is used to basically define any client-side scripts the control will require to run on the client.

[TargetControlType(typeof(Control))]
public class FocusExtender : System.Web.UI.ExtenderControl
{
    protected override System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
    {
        throw new NotImplementedException();
    }

    protected override System.Collections.Generic.IEnumerable<ScriptReference> GetScriptReferences()
    {
        throw new NotImplementedException();
    }
}

You may have noticed the TargetControlType attribute applied to the FocusExtender control; this attribute is required, and is used to define the type of control that the extender explicitly works with. In the case of this example, I'm setting it to work with any thing that inherits from the Control class, which is all server controls.

Define ScriptReferences

In the GetScriptReferences method, return an IEnumerable collection of the ScriptReference objects to include in the page on the client-side.

Here's a basic example of setting up a ScriptReference that includes a script resource that is embedded within the assembly that FocusExtender is contained in:

protected override System.Collections.Generic.IEnumerable<ScriptReference> GetScriptReferences()
{
    yield return new ScriptReference("CustomExtenderControl.FocusExtender.js", "CustomExtenderControl");;
}

When inheriting from ExtenderControl you'll always have at least one ScriptReference, because you need to reference the script that creates the client-side JavaScript representation of your extender control.

Define ScriptDescriptors

In the GetScriptDescriptors method, return an IEnumerable collection of ScriptDescriptor objects that define what properties will be passed down to the client-side JavaScript representation of your control.

The only ScriptDescriptor you need to return in the IEnumerable collection is a  ScriptBehaviorDescriptor instance that contains all the descriptors for your extender control.

Here's a basic example of returning a ScriptBehaviorDescriptor without any properties being defined:

protected override System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
{
    ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor(this.GetType().FullName, targetControl.ClientID)

    yield return descriptor;
}

What ECMAScript (JavaScript) code is needed?

There is a basic block of JavaScript code that you'll need to include that will define the client-side JavaScript representation of your control. This basic block of code is the same base code that you'll start with when creating all extender controls.

Here's the basic JavaScript that will define the client-side JavaScript representation of the ForucExtender control we're using in this example. One thing to remember is that the namespaces and object name in the JavaScript file need to be the same as they are in the server-side .NET code. In case you're wonderin, there is a way to make the client-side and server-side namespaces different, but that's beyond the scope of this article.

Type.registerNamespace("CustomExtenderControl");

CustomExtenderControl.FocusExtender = function(element) {
    CustomExtenderControl.FocusExtender.initializeBase(this, [element]);
};

CustomExtenderControl.FocusExtender.prototype = {
    initialize:function(){
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "initialize");
    },
    dispose:function(){
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "dispose");
    }
};

CustomExtenderControl.FocusExtender.registerClass("CustomExtenderControl.FocusExtender", Sys.UI.Behavior);

Sys.Application.notifyScriptLoaded();

Also, in order for the ExtenderControl to correctly load the "CustomExtenderControl.FocusExtender.js" script reference that we're using in this example, we must not forget to define the assemblies embedded resource as a Web Resource, like so:

[assembly: System.Web.UI.WebResource("CustomExtenderControl.FocusExtender.js", "text/javascript")]

[/code]

 

Let's Add a Little "Rich" AJAX Functionality to the Extender Control

Now that we have a basic ExtenderControl created, we can start adding out "rich" AJAX functionality that we will use to extend our target server control in the page.

In this article, I'm going to keep things extemely simple, and we're going to do the following:

  1. Pass HighlightCssClass and NoHighlightCssClass properties down to the client, that will determin the CSS class's used to highlight out server control (in this article a TextBox).

Add the HighlightCssClass and NoHighlightCssClass Properties

public string HighlightCssClass { get; set; }
public string NoHighlightCssClass { get; set; }

Add the ScriptDescriptor for the HighlightCssClass and NoHighlightCssClass Properties

Just modify the GetScriptDescriptor method above to look like the following:

protected override System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
{
    ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor(this.GetType().FullName, targetControl.ClientID)

    descriptor.AddProperty("HighlightCssClass", this.HighlightCssClass);
    descriptor.AddProperty("NoHighlightCssClass", this.NoHighlightCssClass);

    yield return descriptor;
}

Add the Client-Side Name Property that will receive the value

To do this we need to add a "private" like variable for each CSS property and property accessor methods for each to our JavaScript.

Here's the above JavaScript file with the "private" variables and property accessors added for the CSS properties:

Type.registerNamespace("CustomExtenderControl");

CustomExtenderControl.FocusExtender = function(element) {
    CustomExtenderControl.FocusExtender.initializeBase(this, [element]);
    this._HighlightCssClass = null;
    this._NoHighlightCssClass = null;
};

CustomExtenderControl.FocusExtender.prototype = {
    initialize:function(){
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "initialize");
    },
    dispose:function(){
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "dispose");
    },
   
    get_HighlightCssClass:function() {
        return this._HighlightCssClass;
    },
    set_HighlightCssClass:function(v) {
        this._HighlightCssClass = v;
    },
    get_NoHighlightCssClass:function() {
        return this._NoHighlightCssClass;
    },
    set_NoHighlightCssClass:function(v) {
        this._NoHighlightCssClass = v;
    }
};

CustomExtenderControl.FocusExtender.registerClass("CustomExtenderControl.FocusExtender", Sys.UI.Behavior);

Sys.Application.notifyScriptLoaded();

Set the TargetControls CSS according to the Focus

In this example we're going to attach event handlers to the TargetControl's focus and blur events that will change the controls CSS.

Here's the above JavaScript code with the event handlers added:

Type.registerNamespace("CustomExtenderControl");
CustomExtenderControl.FocusExtender = function(element) {
    CustomExtenderControl.FocusExtender.initializeBase(this, [element]);
    this._HighlightCssClass = null;
    this._NoHighlightCssClass = null;
   
    this._focusHandler = Function.createDelegate(this, this._onFocus);
    this._blurHandler = Function.createDelegate(this, this._onBlur);
};
CustomExtenderControl.FocusExtender.prototype = {
    initialize:function(){
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "initialize");
       
        var targetElement = this.get_element();
       
        $addHandler(targetElement, "focus", this._focusHandler);
        $addHandler(targetElement, "blur", this._blurHandler);       
    },
    dispose:function(){
        var targetElement = this.get_element();
       
        $removeHandler(targetElement, "focus", this._focusHandler);   
        $removeHandler(targetElement, "blur", this._blurHandler);
   
        CustomExtenderControl.FocusExtender.callBaseMethod(this, "dispose");
    },
   
    get_HighlightCssClass:function() {
        return this._HighlightCssClass;
    },
    set_HighlightCssClass:function(v) {
        this._HighlightCssClass = v;
    },
    get_NoHighlightCssClass:function() {
        return this._NoHighlightCssClass;
    },
    set_NoHighlightCssClass:function(v) {
        this._NoHighlightCssClass = v;
    },
   
    //Event Handler Methods
    _onFocus:function(eventArgs) {
        var targetElement = this.get_element();
        if (targetElement != null)
        {
            targetElement.className = this.get_HighlightCssClass();
        }
    },
    _onBlur:function(eventArgs) {
        var targetElement = this.get_element();
        if (targetElement != null)
        {
            targetElement.className = this.get_NoHighlightCssClass();
        }
    }
};
CustomExtenderControl.FocusExtender.registerClass("CustomExtenderControl.FocusExtender", Sys.UI.Behavior);
Sys.Application.notifyScriptLoaded();

 

Tips and Tricks

Tip #1: Simplify Creating ExtenderControls using a custom ExtenderControlBase class

One trick that I've learned, that proves useful when creating custom Extender Controls, is to create your own base class that inherits from ExtenderControl and extends it to use some custom attributes to make adding ScriptReferences and ScriptDescriptors easier. This is the same trick that I learned from creating ScriptControls.

Here's what the final server-side code for the FocusExtender object would look like when using custom attributes and our very own ExtenderControl base class to add ScriptReferences and ScriptDescriptors:

[TargetControlType(typeof(Control)),
ScriptReference("CustomExtenderControl.FocusExtender.js", "CustomExtenderControl")]
public class FocusExtender : ExtenderControlBase
{
    [ExtenderControlProperty]
    public string HighlightCssClass { get; set; }

    [ExtenderControlProperty]
    public string NoHighlightCssClass { get; set; }
}

As you can see, the new code for the FocusExtender using this ExtenderControlBase class with custom attributes is much cleaner and easier to read.

Here's the complete code for the ExtenderControlBase, ScriptReferenceAttribute and ExtenderControlPropertyAttribute objects:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;

public class ExtenderControlBase : ExtenderControl
{
    protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
    {
        ScriptControlDescriptor descriptor = new ScriptControlDescriptor(this.GetType().FullName, targetControl.ClientID);

        // Add all the ExtenderControls Client-Side Object Properties
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
        foreach (PropertyDescriptor prop in props)
        {
            ExtenderControlPropertyAttribute propAttr = prop.Attributes[typeof(ExtenderControlPropertyAttribute)] as ExtenderControlPropertyAttribute;
            if (propAttr != null)
            {
                object value = prop.GetValue(this);
                string name = (propAttr.Name != null) ? propAttr.Name : prop.Name;
                if (value != null)
                {
                    descriptor.AddProperty(name, value);
                }
            }
        }

        yield return descriptor;
    }

    protected override IEnumerable<ScriptReference> GetScriptReferences()
    {
        // Add all the ExtenderControls Client-Side JavaScript References
        object[] scriptReferences = Attribute.GetCustomAttributes(this.GetType(), typeof(ScriptReferenceAttribute), false);
        foreach (ScriptReferenceAttribute r in scriptReferences)
        {
            yield return r.GetScriptReference();
        }
    }
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ExtenderControlPropertyAttribute : Attribute
{
    public ExtenderControlPropertyAttribute() { }

    public ExtenderControlPropertyAttribute(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; }
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ScriptReferenceAttribute : Attribute
{
    public ScriptReferenceAttribute(string path)
    {
        this.Path = path;
    }

    public ScriptReferenceAttribute(string name, string assembly)
    {
        this.Name = name;
        this.Assembly = assembly;
    }

    private string _path = null;
    public string Path
    {
        get { return _path; }
        set { _path = value; }
    }

    private string _name = null;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    private string _assembly = null;
    public string Assembly
    {
        get { return _assembly; }
        set { _assembly = value; }
    }

    public ScriptReference GetScriptReference()
    {
        ScriptReference r = null;

        if (this.Path == null)
        {
            r = new ScriptReference(this.Name, this.Assembly);
        }
        else
        {
            r = new ScriptReference(this.Path);
        }

        return r;
    }
}

Tip #2: Access ExtenderControl via JavaScript

Another trick that I figured out allows you to be able to reference the custom extender control from within JavaScript. The issue this solves is the fact that the ExtenderControl base class doesn't send the control ID down to the client, so there is no way to get a reference to it for manipulation via JavaScript.

To do this all we need to do is add a property named "id" to the ScriptBehaviorDescriptor within the GetScriptDescriptor method. Here's an example of doing this:

protected override System.Collections.Generic.IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
{
    ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor(this.GetType().FullName, targetControl.ClientID);

    descriptor.AddProperty("id", this.ClientID);

    descriptor.AddProperty("HighlightCssClass", this.HighlightCssClass);
    descriptor.AddProperty("NoHighlightCssClass", this.NoHighlightCssClass);

    yield return descriptor;
}

Now with the following FocusExtender control in the page:

<cec:FocusExtender runat="server" id="FocusExtender1"
    TargetControlID="TextBox1"
    HighlightCssClass="Highlight" NoHighlightCssClass="NoHightlight">
</cec:FocusExtender>

We can access it from JavaScript like so:

<input type="button" value="Show HighlightCssClass" onclick="ShowHighlightCssClass();" />
<script type="text/javascript">
    function ShowHighlightCssClass()
    {
        var focusExtender = $find("<%=FocusExtender1.ClientID%>");
        alert(focusExtender.get_HighlightCssClass());
    }
</script>

It's kind of strange that the ExtenderControl base class doesn't automatically link it up to be able to access it from within JavaScript, but at least it's pretty simple to add.

Conclusion

As you can see it's fairly simple to get started creating your own custom extender controls that inherit from the ExtenderControl base class, especially if you use the above ExtenderControlBase class along with it's ExtenderControlPropertyAttribute and ScriptReferenceAttribute attributes. It's also very simple to enable the ability to access the ExtenderControl from within JavaScript to enable much richer AJAX functionality to be built.

Download Full Source Code: CreateAJAXExtenderControlUsingExtenderControlBaseClass.zip (21.36 kb)

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: asp.net
Posted by crpietschmann on Friday, May 30, 2008 11:22 PM
Permalink | Comments (1) | Post RSSRSS comment feed


Mount ISO Images in Vista x64

In Windows XP I used the Virtual CD-ROM Control Panel Utility from Microsoft to mount ISO images to virtual drive letters, but surely Microsoft has built this functionality into Windows Vista, right? Wrong. It would be nice, but they haven't built this into the OS yet. I hope they do in the next release. Well, this utility doesn't work under Windows Vista. I thought I was out of luck, but a quick search revealed a new option to try.

The new utility I found to mount ISO images under Windows Vista x64 is the Freeware MagicDisc from MagicISO. This utility runs as an icon in the taskbar and allows you to easily mount/unmount ISO images from virtual drive letters. This utility in fact allows you to mount up to 15 ISO images to virtual drive letters simultaneously.

This is a pretty neat utility, I encourage anyone using Vista to go check it out. They have two seperate downloads for "Windows 9x/Me/2000/XP/2003/Vista" and "Windows XP/2003/Vista x64 Edition"; so it should work if you're running either 32-bit or 64-bit editions of Windows, just pick the right download.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Thursday, May 29, 2008 10:06 AM
Permalink | Comments (1) | Post RSSRSS comment feed


My Virtual Earth Interview on The Thirsty Developer podcast

A couple weeks ago, while attending the Heros Happen Here launch event in Milwaukee, I ran into Larry Clarkin who is co-host of The Thirsty Developer, and we recorded The Virtual Earth Edition episode that he just released today. In the podcast, I talk about how I got into Virtual Earth development, and give a good overview of the Virtual Earth product, among other things VE related, including the Virtual Earth JavaScript Intellisense Helper and my Web.Maps.VE product.

Listen here: The Thirsty Developer 23: The Virtual Earth Edition

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General | Virtual Earth
Posted by crpietschmann on Wednesday, May 28, 2008 8:13 PM
Permalink | Comments (0) | Post RSSRSS comment feed


DNR: Building Communities at Dallas TechFest

I just listened to episode #344 of DotNetRocks, that was released last week. This episode is on the topic of Building Communities, and the benefits of user groups. Normally each episode is very informative and top notch, but this episode is really rather interesting. Even though this is really not so much tech related, I really encourage anyone interested in user groups and dev/tech communities to take a listen.

Building Communities at Dallas TechFest

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General | WI-INETA
Posted by crpietschmann on Wednesday, May 28, 2008 3:48 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Silverlight: Load JavaScript from Embedded Resource and Execute Within Page

I've been playing around with Silverlight 2 Beta 1 alot lately, and one of the areas I've been focusing on is interoperability with JavaScript and the DOM. Here's a technique I've found that allows you to inject JavaScript into the page from within your Silverlight application. This example also starts with the idea that the JavaScript you are going to inject is stored as an Embedded Resource within your Silverlight Application.

Step 1: Create your JavaScript (.js) file and add it as an embedded resource to your Silverlight Application.

Step 2: Place code in your app that loads the embedded JavaScript file to a string variable:

// Load JavaScript code from Embedded Resource
System.IO.Stream stream = this.GetType().Assembly.GetManifestResourceStream("[namespace].[javascriptFileName]");
System.IO.StreamReader reader = new System.IO.StreamReader(stream);
string script = reader.ReadToEnd();

Note: Replace the [namespace] text above with the full namespace of your Silverlight application project. Also, replace the [javascriptFileName] text above with the filename of your JavaScript file. An example value for this with the namespace and JavaScript filename is "MyApplication.TestScript.js".

Step 3: Inject the JavaScript into the page using Eval:

HtmlPage.Window.Eval(script);

This is a small technique that I've found to make mixing JavaScript with Silverlight a little easier since this allows you to take advantage of JavaScript Intellisense within Visual Studio 2008; where if you just placed the JavaScript code inline within your C# or VB.NET code you would not be able to have JavaScript Intellisense.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Silverlight
Posted by crpietschmann on Monday, May 19, 2008 8:32 PM
Permalink | Comments (0) | Post RSSRSS comment feed

My First Experience with ReSharper v3.1, not so good

A while back I won a free license for JetBrains ReSharper v3.1 at one of the monthly WI .NET Users Group meetings. Today, I finally got around to installing it to check it out.

I found some of the code hightlighting/outlining features to be pretty neat, but.... But, I experienced a 1/2 to 1 second lag for Visual Studio 2008 to do anything after I installed ReSharper. This lag was quite an annoyance. So, consiquentially, I uninstalled ReSharper to get my VS performance back.

I also had another issue with it; After I uninstalled ReSharper from my machine I noticed that all the Intellisense in Visual Studio wasn't there anymore. What?!!?! I did a quick search and found instructions on JetBrains Knowledge Base on how to Fix Intellisense after uninstalling ReSharper. few... At least it was easy to fix. I was afraid I would have to reinstall VS. There is also one thing I find funny about this "bug", the knowledge base article dates back to Dec. 2004. I would normally expect that JetBrains would have fixed this issue by now. Afterall, why in the world would anyone not want Intellisense after uninstalling ReSharper?

Mayber I'll try out ReSharper 4.0 after it comes out, hopefully they'll fix the performance issues in that release. However, I'm surprised that v3 has performance issues this bad.

Do any of you use ReSharper? If so, how is the Visual Studio performance for you?

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Monday, May 19, 2008 7:28 PM
Permalink | Comments (2) | Post RSSRSS comment feed

Virtual Earth + ASP.NET AJAX Now Fixed in Safari

A couple months ago I blogged about the fact that using Virtual Earth and ASP.NET AJAX together on the same page caused errors in Safari. There is good new to report back, the latest update to Virtual Earth has fixed this issue. In fact Virtual Earth v6.1 actually includes much better Safari support that previous versions; it actually works correctly in Safari. I found this to be especially helpful since I can now support Safari with my Web.Maps.VE product.

What's the catch? I can't work perfectly now can it. Well, as far as I can tell Virtual Earth works great. However, the code example in my post calling attention to the error actually still has a little bug in it. The bug is the calendar that is automatically shown on hover over by the AjaxControlToolkit CalendarExtender get hidden by the Map below the textbox. This is actually caused by a layering issue related to the z-index of the elements on the page. An easy way to fix this is to just set the z-index of the VEMap's DIV element to a lower value so all other elements on the page will be rendered over the top of it.

Here's the full example code showing example what I mean above:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ 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">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1"></script>
<script type="text/javascript">
    var map = null;
    function GetMap()
    {
        map = new VEMap('myMap');
        map.LoadMap();
    }
</script>
</head>
<body onload="GetMap();">
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>
<div>
<asp:TextBox runat="server" id="txtDate"></asp:TextBox>
<ajaxToolkit:CalendarExtender runat="server" ID="CalendarExtender1" TargetControlID="txtDate"></ajaxToolkit:CalendarExtender>
<br /><br />
<div id='myMap' style="position:relative; width:400px; height:400px; z-index: -100;"></div>
</div>
</form>
</body>
</html>

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by crpietschmann on Saturday, May 17, 2008 1:13 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Hyper-V Compatibility Check Tool for AMD Processors

I just found that AMD has a tool titled "AMD-V Technology and Microsoft Hyper-V System Compatibility Check Utility". You can run this tool on Windows Vista or Windows Server 2008 (make sure you run it with elevated privileges) to see if your hardware combination of AMD Processor and Motherboard support Hyper-V.

I guess this would have saved me from the trouble of installing Win 2008 with Hyper-V just to figure out that my AMD Athlon 64 X2 4200+ supports Hyper-V, but my motherboard doesn't.

I ran this tool on my system (AMD Athlon 64 X2 4200+ processor with a Gigabyte GA-M55SLI-S4 motherboard) to see what it says, and here's the results it displayed:

Test Results from Microsoft Hyper-V compatibility check for systems with AMD processors
This system is not compatible with Hyper-V.
This utility detected that a necessary BIOS patch is not installed.
Please contact your system vendor to determine whether a BIOS upgrade is available.
If so, upgrade your BIOS and re-run the utility.
If not, consider upgrading to a new AMD64 system to get the latest in virtualization capabilities, performace, and power efficiency.
AMD's most current processors do not require a BIOS patch to run Hyper-V.

So, basically my processor supports hardware assisted virtualization (which I knew), but my motherboard doesn't. Now I just need to check Gigabyte to see if they have a BIOS update available for this motherboard that will enable support for hardware assisted virtualization.

Update June 18, 2008: After talking with Gigabyte tech support on and off for the last couple weeks, they had me try out a couple BIOS updates that aren't posted on their website. The latest one, m55slis4.11h, finally enabled the Hardware Assisted Virtualization switch in the BIOS on my machine. I am currently running Vista x64 on this machine and I am now finally able to use virtual machines within VirtualPC now that hardware assisted virtualization is fully enabled. Maybe some day I'll get around to trying out Hyper-V again since I have a machine that'll be able to handle it. I'll write a blog post about my expereinces when I do.

Update July 3, 2008: I had a request recently asking where the 11h bios update can be found, since they don't have it available for download within the BIOS Updates on their website. You can get it from the support ticket conversation I had with them, located at the following url: http://ggts.gigabyte.com.tw/detailEmail.asp?EmailID=620026&EmailPreviousID=607096&LanguageID=1
 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Friday, May 16, 2008 10:44 AM
Permalink | Comments (1) | Post RSSRSS comment feed

.NET 3.5 SP1: A Service Pack or The Real .NET 3.5

Microsoft just RTM'd Visual Studio 2008 and .NET 3.5 last November and launched them in February. And, their already releasing a Service Pack? What could they possibly have to all fix in a Service Pack this soon? Well, actually they aren't just fixing stuff; they are adding a huge amount of functionality too. ScottGu has a long post about what's all in it here.

I'm thinking that .NET 3.5 needed to ship, so they took out everything that just wasn't quite all the way there and are including it in this Service Pack. That's the only way I can explain such a huge service pack (with so many New features) so soon. You know it's nice to have new stuff added, especially in an off cycle release, but at least do it in a way that wont cause any potential confusion.

Ok, here's a simple scenario... I have an application that I'm distributing and I post in the requirements that it supports .NET 3.5 Service Pack 1. Well, to most people (not as techie as I) they see it supports .NET 3.5, and try to run it. Well, guess what? They have .NET 3.5 without SP1 and the app throws an exception and crashes when they try to run it. Because of their undesirable experience they delete my app and never look at it again. Now, only if they would have had SP1 installed, they wouldn't have had any issues.

Well, the first thing you'll probably point out is that I claimed .NET 3.5 SP1 support and they only had .NET 3.5 installed. To the normal person who doesn't know what "Service Pack 1" means, they are the same thing.

Secondly, I could probably include the framework and service pack as part of my installer. This way if they don't have .NET 3.5 or SP1 installed, it will install it when they install the app. Now this would work fine and dandy, just as long as I wasn't just distributing the EXE without an installer, or if I didn't (and my users didn't) mind the installer being 25+ MB.

I'm not sure if you agree with me on this, but there is definitely some potential confusion here. However, I don't think this potential confusion is a big enough issue to warrant calling this release .NET 4.0. That would be much worse, since it's easier to get your sys admins to install a service pack instead of a full release.

Anyway, like I said above, maybe .NET 3.5 SP1 is the .NET 3.5 that was supposed to RTM and ship back in November, but they just didn't have enough time to meet the deadline. And, don't get me wrong, I am look forward to the improvements and new features in this service pack, I just wish we had the final release instead of a Beta. I'm leery about installing a .NET Framework Beta on my workstation.

Ok the rant is over...

Currently rated 2.0 by 1 people

  • Currently 2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by crpietschmann on Thursday, May 15, 2008 10:44 PM
Permalink | Comments (1) | Post RSSRSS comment feed

ASP.NET: Create AJAX Server Controls using the ScriptControl base class

I've been doing a lot with ASP.NET AJAX for almost 2 years now, including my Web.Maps.VE product. So, I've decided to spread some of my knowledge in this area by writing up some articles on things that I've learned and figured out.

As a note, since .NET 3.5 is the "latest and greatest" version of the framework out at the time of this writing, this article targets .NET 3.5. This article also assumes you have a basic understanding of ASP.NET AJAX and JavaScript.

What is ScriptControl?

First, what exactly is ScriptControl? Well, the base class I'm referring to is the System.Web.UI.ScriptControl base class located within the System.Web.Extensions.dll assembly.

The ScriptControl is basically the first building block you want to use to start building out a WebControl (server control) that will have some kind of rich AJAX functionality in the browser. You may have heard of ASP.NET AJAX Control Extenders, especially if you're familiar with the AJAX Control Toolkit, so why would we use ScriptControl instead of creating an ExtenderControl in order to give a control some rich AJAX functionality within the browser? Well, you want to create an ExtenderControl to extend or enhance an existing control with some rich AJAX functionality, and you want to inherit from the ScriptControl class when you are creating a full control that will have some rich AJAX functionality.

According to MSDN the ScriptControl class is:

ScriptControl inherits from the WebControl class and implements the IScriptControl interface. The WebControl class is a base class for ASP.NET Web server controls. The ScriptControl is an abstract class, which you cannot instantiate directly. Instead, you derive a class based on this abstract class.

The ScriptControl base class tests the page for a ScriptManager control during the PreRender stage of the derived control. The ScriptControl base class also makes sure that the derived control calls methods of the ScriptManager control to register script during the Render event. This includes registering ScriptDescriptor objects for the ScriptControl when the Render method is called. The Render method makes sure that ScriptDescriptor objects are not rendered unless the ScriptControl itself is rendered. This enables a ScriptControl to work inside a closed WebPart control.

You can add as many descriptors and types as necessary to any class that you derive from ScriptControl.

 

Basics of Creating Server Controls that Inherit from ScriptControl

When first creating your custom server control you inherit from ScriptControl instead of WebControl like usual. The first thing you'll see is ScriptControl requires you to implement two methods: GetScriptDescriptors and GetScriptReferences. The GetScriptDescriptors method is used to get an enumeration of ScriptDescriptor objects that basically define any of the controls client-side AJAX properties. The GetScriptReferences method is used to get an enumeration of ECMAScript (JavaScript) files that will be loaded on the client-side once the page loads; this is used to basically define any client-side scripts the control will require to run on the client.

Here's a basic stub of a control that inherits from ScriptControl:

public class CustomScriptControl : ScriptControl
{
    protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
    {
        throw new NotImplementedException();
    }

    protected override IEnumerable<ScriptReference> GetScriptReferences()
    {
        throw new NotImplementedException();
    }
}

Define ScriptReferences

In the GetScriptReferences method, return an enumeration of the ScriptReference objects to include in the page on the client-side.

Here's a basic example of setting up a ScriptReference that includes a script resource that is embedded within the assembly the CustomScriptControl is contained in:

protected override IEnumerable<ScriptReference> GetScriptReferences()
{
    List<ScriptReference> references = new List<ScriptReference>();
    references.Add(new ScriptReference("CustomScriptControl.CustomScriptControl.js", "CustomScriptControl"));
    return references;
}

When inheriting from ScriptControl you'll generally always have at least one ScriptReference because you need to reference the script that creates the client-side JavaScript representation of your control.

Define ScriptDescriptors

In the GetScriptDescriptors method, return an enumeration of ScriptDescriptor objects that define what properties will be passed down to the client-side JavaScript representation of your control.

The only ScriptDescriptor you need to return in the enumeration is a ScriptControlDescriptor instance that contains all the descriptors for your control.

Here's a basic example of returning a ScriptControlDescriptor without any properties being defined:

protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
    ScriptControlDescriptor descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);
    return new ScriptDescriptor[] { descriptor };
}

What ECMAScript (JavaScript) code is needed?

There is a basic block of JavaScript code that you'll need to include in the ScriptReference that's being defined by the GetScriptReferences method that will define the client-side JavaScript representation of your control. This basic block of code that you include in this script file is the same for all ScriptControls that you'll create.

Here's the basic JavaScript that will define the client-side JavaScript representation of the CustomScriptControl we're using in this example. One thing to remember is that the namespaces and object name in the JavaScript file need to be the same as they are in the server-side .NET code.

Type.registerNamespace("CustomScriptControl");
CustomScriptControl.CustomScriptControl = function(element) {
    CustomScriptControl.CustomScriptControl.initializeBase(this, [element]);
};
CustomScriptControl.CustomScriptControl.prototype = {
    initialize:function() {
        CustomScriptControl.CustomScriptControl.callBaseMethod(this, "initialize");
    },
    dispose:function() {
        CustomScriptControl.CustomScriptControl.callBaseMethod(this, "dispose");
    }
};
CustomScriptControl.CustomScriptControl.registerClass("CustomScriptControl.CustomScriptControl", Sys.UI.Control);
if(typeof(Sys)!=="undefined")Sys.Application.notifyScriptLoaded();

 

Also, in order for the ScriptControl to correctly load the "CustomScriptControl.CustomScriptControl.js" script reference that we're using in this example, we must not forget to define the assemblies embedded resource as a Web Resource, like so:

[assembly: System.Web.UI.WebResource("CustomScriptControl.CustomScriptControl.js", "text/javascript")]

Let's Add a Little "Rich" AJAX Functionality to the Control

Now that we have a basic ScriptControl created, we can start to add out "rich" AJAX functionality to it.

In this article, I'm going to keep things extremely simple, and we're going to do the following:

  1. Pass a Name (type string) property to the client by defining it as a ScriptDescriptor, and displaying it to the user via a JavaScript Alert dialog.

Add the Name Property to the Control

public string Name { get; set; }

Add the ScriptDescriptor for the Name Property

Just modify the GetScriptDescriptors method above to look like the following:

protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
{
    ScriptControlDescriptor descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);

    // Add our Name property to be passed down to the client
    descriptor.AddProperty("Name", this.Name);

    return new ScriptDescriptor[] { descriptor };
}

Add the Client-Side Name Property that will receive the value

To do this we need to add a "private" like variable to hold the value and property accessor methods to our JavaScript file.

Here's the above JavaScript file with the "private" variable and property accessors added for the Name property:

Type.registerNamespace("CustomScriptControl");
CustomScriptControl.CustomScriptControl = function(element) {
    CustomScriptControl.CustomScriptControl.initializeBase(this, [element]);
    // "private" variable to hold the Name properties value
    this._name = null;
};
CustomScriptControl.CustomScriptControl.prototype = {
    initialize:function() {
        CustomScriptControl.CustomScriptControl.callBaseMethod(this, "initialize");
    },
    dispose:function() {
        CustomScriptControl.CustomScriptControl.callBaseMethod(this, "dispose");
    },
    // Name Property Accessors
    get_Name:function() {
        return this._name;
    },
    set_Name:function(value) {
        this._name = value;
    }   
};
CustomScriptControl.CustomScriptControl.registerClass("CustomScriptControl.CustomScriptControl", Sys.UI.Control);
if(typeof(Sys)!=="undefined")Sys.Application.notifyScriptLoaded();

 

Display the Name to the User

In this example we're going to display the Name property to the user using a JavaScript Alert within the objects client-side initialize property.

Here's the initialize method modified to include the Alert:

initialize:function() {
    CustomScriptControl.CustomScriptControl.callBaseMethod(this, "initialize");

    // Display Name property to user
    alert(this.get_Name());

},

Tips and Tricks

One trick that I've learned that proves useful when creating custom ScriptControls, is to create your own base class that inherits from ScriptControl and extends it to use some custom attributes to make adding ScriptReferences and ScriptDescriptors easier.

Here's what the final server-side code of the CustomScriptControl object would look like when using custom attributes to add the ScriptReferences and ScriptDescriptors:

[ScriptReference("CustomScriptControl.CustomScriptControl.js", "CustomScriptControl")]
public class CustomScriptControl : ScriptControlBase
{
    [ScriptControlProperty]
    public string Name { get; set; }
}

As you can see, the new code for the CustomScriptControl using this base class with custom attributes is much cleaner and easier to read.

Here's the complete code for the ScriptControlBase, ScriptReferenceAttribute and ScriptControlPropertyAttribute objects:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;

public class ScriptControlBase : ScriptControl
{
    protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
    {
        ScriptControlDescriptor descriptor = new ScriptControlDescriptor(this.GetType().FullName, this.ClientID);

        // Add all the ScriptControls Client-Side Object Properties
        PropertyDescriptorCollection props = TypeDescriptor.GetProperties(this);
        foreach (PropertyDescriptor prop in props)
        {
            ScriptControlPropertyAttribute propAttr = prop.Attributes[typeof(ScriptControlPropertyAttribute)] as ScriptControlPropertyAttribute;
            if (propAttr != null)
            {
                object value = prop.GetValue(this);
                string name = (propAttr.Name != null) ? propAttr.Name : prop.Name;
                if (value != null)
                {
                    descriptor.AddProperty(name, value);
                }
            }
        }

        return new ScriptDescriptor[] { descriptor };
    }

    protected override IEnumerable<ScriptReference> GetScriptReferences()
    {
        List<ScriptReference> references = new List<ScriptReference>();

        // Add all the ScriptControls Client-Side JavaScript References
        object[] scriptReferences = Attribute.GetCustomAttributes(this.GetType(), typeof(ScriptReferenceAttribute), false);
        foreach (ScriptReferenceAttribute r in scriptReferences)
        {
            references.Add(r.GetScriptReference());
        }

        return references;
    }
}

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ScriptControlPropertyAttribute : Attribute
{
    public ScriptControlPropertyAttribute() { }

    public ScriptControlPropertyAttribute(string name)
    {
        this.Name = name;
    }

    public string Name { get; set; }
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ScriptReferenceAttribute : Attribute
{
    public ScriptReferenceAttribute(string path)
    {
        this.Path = path;
    }

    public ScriptReferenceAttribute(string name, string assembly)
    {
        this.Name = name;
        this.Assembly = assembly;
    }

    private string _path = null;
    public string Path
    {
        get { return _path; }
        set { _path = value; }
    }

    private string _name = null;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    private string _assembly = null;
    public string Assembly
    {
        get { return _assembly; }
        set { _assembly = value; }
    }

    public ScriptReference GetScriptReference()
    {
        ScriptReference r = null;

        if (this.Path == null)
        {
            r = new ScriptReference(this.Name, this.Assembly);
        }
        else
        {
            r = new ScriptReference(this.Path);
        }

        return r;
    }
}

Conclusion

As you can see it's fairly simple to get started creating your own custom server controls that inherit from ScriptControl, especially if you use the above ScriptControlBase class along with its ScriptControlPropertyAttribute and ScriptReferenceAttribute attributes.

Download Full Source Code: CreateAJAXServerControlUsingScriptControlBaseClass.zip (33.31 kb)

Update 5/31/2008: I recently posted an article titled "Create AJAX Extender Controls using the ExtenderControl base class" on how to create Extender Controls in ASP.NET using the System.Web.UI.ExtenderControl base class.

Currently rated 4.3 by 12 people

  • Currently 4.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: asp.net
Posted by crpietschmann on Thursday, May 15, 2008 12:52 AM
Permalink | Comments (6) | Post RSSRSS comment feed

About the author

I'm Chris Pietschmann, go to the About Me page to learn more about me.

Search

Sponsors

Web.Maps.VE - ASP.NET AJAX Virtual Earth Mapping Server Control

Recent comments

Disclaimer