Jack @ ASP.NET

As a software engineer, I focus on .NET, especially asp.net, C#, WCF and so on, and I am also very interested in Search Engine Optimization.

Entries Tagged ‘quot’

Issue with Auto-Generated Designer Files not Adding Controls: Hotfix available

A hotfix is now available for issues most commonly described as "Controls are not being recognized in the code-behind" and "Editing existing .aspx regenerates .aspx.designer.(cs), but most of the controls are now missing”.

This hotfix can be downloaded from: http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=27117

The update addresses the following Connect bugs:

    * Cannot embed standard asp.net controls in Ajax Control Toolkit TabContainer
    * Controls in CreateUserWizard WizardStep not visible as before
    * issue with auto-generated Designer files not addding components
    * Code Generation in 2010 RC doesn’t work the same as 2008 for ASP.NET Application
    * Editing existing .aspx regenerates designer.cs (good) but most of the controls are now missing (bad)
    * ASP.NET designer fails to auto-generate fields
    * Bug in generating the designer.cs file in VS2010 (Converting VS2008 project to VS2010)

C# Code Snippet: Finding a Node in an XML String

XML to be operated on:

   1: <States>

   2:   <State name="Wisconsin">

   3:     <Regions>

   4:       <Region name="Milwaukee">

   5:         <Area name="Mukwanago"/>

   6:         <Area name="Germantown"/>

   7:       </Region>

   8:       <Region name="Fox Valley">

   9:         <Area name="Oshkosh" />

  10:         <Area name="Appleton" />

  11:       </Region>    

  12:     </Regions>

  13:   </State>

  14: </States>

C# code:

   1: // using System.Xml.Linq

   2:  

   3: // make sure the xml file exists

   4: XElement states  = XElement.Load("testXML.xml");

   5:  

   6: // Using LINQ

   7: XElement foundNode;

   8: var query = from XElement r in states.Descendants("Region")

   9:                    where r.Attribute("name").Value == "Milwaukee"

  10:                    select r;

  11: foundNode = query.FirstOrDefault();

  12:  

  13: // Using Lambda expressions

  14: foundNode = states.Descendants("Region").

  15:      Where(r => r.Attribute("name").Value ==

  16:                          "Milwaukee").FirstOrDefault(); 

TODO Comments in Visual Studio

Using TODO

imageTODO comments allow you to tell Visual Studio to maintain a central list of tasks, which it reads from many different places in your code. The Task List is a panel or floating window in Visual Studio that will display all the TODO comments in your project. To open the list, go to View menu -> Task List.

Some example TODO comments

You probably have a lot of code that needs a lot of work. If you don’t, then you need to write code that needs a lot of work. Here are some examples of TODO lines that Visual Studio 2008 will notice and put into its special Task Pane.

//todo: your task 1
//TODO: your task 2
// Todo your task 3

Description of example. This will appear in your tasks pane as a separate task. Note that you have some flexibility with these tokens. The strings "todo", "TODO", and "TODO" all work equally well—Visual Studio’s parser gives you a little bit of freedom.

jQuery hoverImage plugin

   1: (function($) {

   2:     $.fn.extend({

   3:         hoverImage: function(options) {

   4:             var defaults = { src: "-hover", preload: true, replaceEnd: "" };

   5:             options = $.extend(defaults, options);

   6:  

   7:             var append = options.src.indexOf(".") == -1;

   8:  

   9:             var splitter;

  10:             if (append) {

  11:                 splitter = options.replaceEnd + ".";

  12:             }

  13:  

  14:             return this.each(function() {

  15:                 var obj = $(this);

  16:                 var img = obj.is("[src]") ? obj : obj.children("[src]:first").eq(0);

  17:  

  18:                 if (!img.is("[src]")) {

  19:                     return true;

  20:                 }

  21:  

  22:                 var oSrc = img.attr("src");

  23:                 img.data("oSrc", oSrc);

  24:  

  25:                 var hSrc = options.src;

  26:                 if (append) {

  27:                     hSrc = oSrc.split(splitter).join(hSrc + ".");

  28:                 }

  29:                 

  30:                 img.data("hSrc", hSrc);

  31:  

  32:                 if (options.preload) {

  33:                     new Image().src = hSrc;

  34:                 }

  35:  

  36:                 obj.hover(function() { img.attr("src", img.data("hSrc")); },

  37:                           function() { img.attr("src", img.data("oSrc")); });

  38:             });

  39:         }

  40:     });

  41: })(jQuery);

Here’s a sample of html in which the plug-in is used.

   1: <html xmlns="http://www.w3.org/1999/xhtml">

   2: <head runat="server">

   3:     <title>hoverImage test page</title>

   4:     <script src="/ClientScript/jquery-1.3.2.min.js" type="text/javascript"></script>
   1:  

   2:     <script src="/ClientScript/jquery.hoverImage.js" type="text/javascript">

   1: </script>

   2:  

   3:     <script type="text/javascript">

   4:         $(function() {

   5:             $(".standardImage").hoverImage({replaceEnd: "-standard"});

   6:             $(".hoverImage").hoverImage();

   7:         });

   8:     

</script>

   5: </head>

   6: <body>

   7:     <form id="form1" runat="server">

   8:     <div>

   9:         <img class="standardImage" src="Imgs/button-standard.gif" />

  10:         <img class="hoverImage" src="Imgs/button.gif" />

  11:         <a class="hoverImage" href="#" style="display:block; width:100%;border:solid 1px black;">

  12:             <img src="Imgs/button.gif" />

  13:         </a>

  14:     </div>

  15:     </form>

  16: </body>

  17: </html>

Happy 2010~~

How to Hack the ASP.NET Parser

The ASP.NET compliation system is pretty complex. There are all kinds of extensibility points, including BuildProviders, PageParserFilters, ControlBuilders, ExpressionBuilders and the list goes on. One unknown *feature* of the parser is it’s ability to generate code from something called an InstanceDescriptor.

The parser has a special way of dealing with ITemplate properties so if we try to do this:

<asp:Repeater ID="repeater" runat="server" ItemTemplate="~/MyUserControl.ascx">
</asp:Repeater>

It fails because the there is no way to convert the string “~/MyUserControl.ascx” into an ITemplate.

The parser uses the TypeConverter attribute defined on properties it parses to aid in the conversion.  Enter TypeDescriptionProvider. These complex beasts are used at the heart of all designers in Visual Studio. There are used for things like populating the property grid, and adding and removing properties dynamically, basically a general purpose metadata API (think of it as an abstraction on top of reflection).

VirtualPathTemplate

The code we are going to generate will instantiate a VirtualPathTemplate with a virtual path pointing to a user control on our site. Normally when you define a template in markup, a special type called CompiledTemplateBuilder (which points to a delegate that builds the template at runtime) is assigned to it. We want to replace a line of code that looks like this:

repeater.ItemTemplate = new CompiledTemplateBuilder(BuildTemplate);

to this

repeater.ItemTemplate = new VirtualPathTemplate("~/MyUserControl.ascx");

TypeDescriptionProvider

After overriding about 4 classes (TypeDescriptionProvider, CustomTypeDescriptor, PropertyDescriptor, and finally TypeConverter) we are able to control what happens when the parser asks, “can we convert “~/MyUserControl.ascx” to an ITemplate?”.

Here is the code for the TemplateTypeConverter:

public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) {
// Allow InstanceDescriptor so that the code gen engine can use it to generate the correct
// code for the ITemplate property
return destinationType == typeof(InstanceDescriptor) || _converter.CanConvertTo(context, destinationType);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) {
var descriptorProvider = value as IInstanceDescriptorProvider;
if (descriptorProvider != null) {
return descriptorProvider.Descriptor;
    }
return _converter.ConvertTo(context, culture, value, destinationType);
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) {
return sourceType == typeof(string) || _converter.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
string stringValue = value as string;
if (stringValue != null) {
if (stringValue.StartsWith("~/")) {                    
// Assume this is a virtual path and return the instance description provider
// for it
return new VirtualPathInstanceDescriptorProvider(stringValue);
        }                
    }
return _converter.ConvertFrom(context, culture, value);
}

First the parser asks the converter if it can convert from a string so we always say yes. In ConvertFrom we try to convert the value to a string and check if the path starts with “~/” in order to determine if it’s a virtual path. If it is a virtual path we return an object that knows how to get an InstanceDescriptor from the virtual path (VirtualPathInstanceDescriptorProvider). Now we have successfully parsed the control.

Next the code generator tries to generate code for the ITemplate property. The code generator will eventually ask if it can convert the object we returned earlier (VirtualPathInstanceDescriptorProvider) to an InstanceDescriptor. The implementation of VirtualPathInstanceDescriptorProvider returns an instance descriptor that wraps a constructor info for a custom template we are going to use:

internal class VirtualPathInstanceDescriptorProvider : IInstanceDescriptorProvider {
private string _virtualPath;
private static ConstructorInfo s_Constructor = GetConstructor();
private static ConstructorInfo GetConstructor() {
return typeof(VirtualPathTemplate).GetConstructor(new[] { typeof(string) });
    }
public InstanceDescriptor Descriptor {
get {
return new InstanceDescriptor(s_Constructor, new[] { _virtualPath });
        }
    }
public VirtualPathInstanceDescriptorProvider(string virtualPath) {            
        _virtualPath = virtualPath;
    }        
}

The code generation engine then generates the resulting code we wanted to specify above using the constructor info and virtual path.

At runtime we use BuildManager.CreateInstanceFromVirtualPath(“~/MyUserControl.ascx”) to create an instance of the user control and add it to the control’s collection and we’re done.

public class VirtualPathTemplate : ITemplate {
private string _virtualPath;
public VirtualPathTemplate(string virtualPath) {
        _virtualPath = virtualPath;
    }
public void InstantiateIn(Control container) {
// Try to create the control from the virtual path
Control control = (Control)BuildManager.CreateInstanceFromVirtualPath(_virtualPath, typeof(Control));
if (control != null) {
// Add it to the controls collection
            container.Controls.Add(control);
        }            
    }
}

How to Enable the ASP.NET Ajax script loader

An important feature of the script loader is the separation of the script meta-data from the script code itself. The meta-data can include the name of the script, its dependencies, instructions on how to figure out if it’s already loaded, its debug and release URL patterns and a declaration of the lazy components and plug-ins it introduces. The script loader can also handle composite scripts but I won’t cover that in this post.

  • The name of the script is what will be used to reference it from other scripts and to generate the URL from a pattern. It shouldn’t include the “.js” extension.
  • The dependencies and executionDependencies are each a simple array of script names that the script depends on. I’ll explain the difference in a minute.
  • The is loaded criterion is a JavaScript expression that returns true if the script is already loaded. This is usually a test on an object that the script file defines. For example, the “templates” script uses !!(Sys.UI && Sys.UI.Templates). It can assume Sys because it’s defined by start.js.
  • Debug and release patterns are expressions that enable the framework to map script names into debug and release URLs. The ASP.NET Library uses “%/MicrosoftAjax{0}.debug.js” and “%/MicrosoftAjax{0}.js” where % gets replaced with the path where the script loader was downloaded from (this can be CDN or local) and {0} gets replaced with the script name. You can create your own pattern or just provide fixed URLs if you have only one script file. The debug pattern is optional.
  • Lazy components and plug-ins are helpers that the script loader can create for you and that enable developers to start using your components before they are even loaded and hide the script loading aspects as much as possible. For example, it’s that feature that enables you to write this while still having only start.js loaded:
    Sys.create.dataView("#myDataView", {
        data: myData
    });

    The code that needed to be written for this helper to be created was this:

    behaviors: ["Sys.UI.DataView"]

    This gets automatically transformed by the script loader into the Sys.create.dataView method, before it even tries to load the actual script that defines Sys.UI.DataView. And if you have jQuery loaded as well, you’ll also get a jQuery plug-in out of it for free, which means that you can do:

    $(".data").dataView({data: myData});

    and instantiate DataView controls over the results of a selector query in one operation. Groovy. Of course, you can do the same with the behaviors and controls that you write in your own scripts, with lots of options to customize names, add parameters, etc.

In the case of the class library code, here’s the meta-data declaration code that I had to write:

Sys.loader.defineScript({
  name: "classBrowserTree",
  releaseUrl: "%/TreejQuery.js",
  executionDependencies:    ["jQuery", "Templates", "ComponentModel"],
  isLoaded: !!(window.jQuery &&    window.jQuery.fn.classBrowserTreeView)
});

This declares that my script, named “classBrowserTree”, can be found at the URL TreejQuery.js relative to the base URL of the script loader, that it depends on jQuery, Templates and ComponentModel (which themselves have their own dependencies) and that the loader can determine whether it’s already loaded by evaluating the classBrowserTreeView jQuery plug-in.

Now, loading that script and all its dependencies is as simple as writing this:

Sys.require(Sys.scripts.classBrowserTree);

Notice that as you’re typing this, you actually get full IntelliSense in Visual Studio on the name of the script, which is great for speed and to avoid typos:ScriptLoaderIntelliSense

One of the things that enable the script loader to do its job is a special way to write your script that makes it possible to separate the loading and parsing of the code from its execution.

Don’t freak out (yet) though as the code you have to introduce is very lightweight and it doesn’t prevent your script from being loaded without the script loader (with a plain old script tag for example).

Reversely, a script that doesn’t have the special script loader code can be handled by the script loader but its dependencies must be declared using “dependencies” instead of “executionDependencies” in the meta-data declaration code, which will in effect disable the more advanced features of the script loader such as parallel loading.

The special code in question is the following:

(function() {
  function execute() {
    // Your code goes here.
  }
  if (window.Sys && Sys.loader) {
    Sys.loader.registerScript(      "classBrowserTree", null, execute);
  }
  else {
    execute();
  }
})();

What you see here is a (function() {…})(); wrapper, which is standard practice to isolate code from the global namespace (essentially, it’s a local scope); we also have another named scope in there that we arbitrarily call “execute” (but the name doesn’t matter). This is where you’ll typically put your actual code. Then we have the bootstrapping code that looks for the script loader. If it isn’t found, the code in the execute function is immediately run. If it is found, the execute function is registered with the script loader but is not immediately executed.

This wrapper code is what enables the script loader to do its magic. Thanks to this little bit of code, it doesn’t care at all in what order the scripts are being loaded, because it can delay the time when any script actually gets executed until all its dependencies have been successfully loaded.

This also allows the script loader to load scripts in parallel, even if one depends on another. Normally a script loader would have to download a dependent script first and wait for it to completely load before loading the next script. This ‘serializes’ the loading process and is not good for performance. Modern browsers can download 6 to 8 scripts simultaneously. Separating the loading of a script from its execution allows the loader to take advantage of that, and in most cases, even complex dependency trees can be downloaded completely in parallel, meaning the total time is not the sum of each script, but only the longest one.