No-Compile Web User Controls

 When using no-compile web user controls (where the CompilationMode directive is set to Never), you cannot just add them to your web page declaratively.

There are two ways to do it:

  • Programmatically, by calling Page.LoadControl, casting the returned value to the appropriate class (UserControl-derived or PartialCachingControl, if the web user control has the OutputCache directive) and set its properties manually
  • Use the aspnet_compiler tool to build your site beforehand (another project), add a reference to this project and then register your web user control as a regular server control, with the Assembly and Namespace properties instead of Src

I built a simple control that allows us to declare a no-compile web user control. It allows us to declare its attributes in the markup (through the implementation of the IAttributeAccessor interface), but we also have to specify the location of its .ascx file. I believe this is much better to have a declarative approach, whenever possible, to a programmatic one.

This is how it should be used:

<someprefix:DynamicUserControl runat="server" VirtualPath="~/SomeWebUserControl.ascx SomeProperty="1" SomeOtherProperty="false"/> 

Here is the code:

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.ComponentModel;

namespace Controls

{

[
Themeable(false)]

public class DynamicUserControl: Control, IAttributeAccessor

{

#region Private fields private System.Web.UI.AttributeCollection attributes = null;

private String virtualPath = String.Empty;

#endregion

#region
Public constructorpublic DynamicUserControl()

{

this.attributes = new System.Web.UI.AttributeCollection(this.ViewState);

}

#endregion

#region
Public properties

[Browsable(true)]

[Localizable(false)]

[Description("")]

[DefaultValue("")]

[UrlProperty("*.ascx")]

public String VirtualPath

{

get

{

return (this.virtualPath);

}

 

set

{

this.virtualPath = value ?? String.Empty;

}

}

[
Browsable(false)]public System.Web.UI.AttributeCollection Attributes

{

get

{

return (this.attributes);

}

}

#endregion

#region
Protected override methodsprotected override void OnLoad(EventArgs e)

{

Control ctrl = this.Page.LoadControl(this.VirtualPath);

Control innerCtrl = null;if (ctrl is PartialCachingControl)

{

innerCtrl = (ctrl
as PartialCachingControl).CachedControl;

}

else if (ctrl is UserControl)

{

innerCtrl = ctrl;

}

if (innerCtrl != null)

{

foreach (String key in this.Attributes.Keys)

{

PropertyDescriptor prop = TypeDescriptor.GetProperties(innerCtrl)[key];if (prop != null)

{

TypeConverter converter = prop.Converter;

if (converter != null)

{

prop.SetValue(innerCtrl, converter.ConvertFrom(
this.attributes[key]));

}

else

{

converter =
TypeDescriptor.GetConverter(prop.PropertyType);if (converter != null)

{

prop.SetValue(innerCtrl, converter.ConvertFrom(
this.attributes[key]));

}

else

{

prop.SetValue(innerCtrl,
Convert.ChangeType(this.attributes[key], prop.PropertyType));

}

}

}

}

this.Controls.Add(innerCtrl);

}

base.OnLoad(e);

}

#endregion

#region
IAttributeAccessor Memberspublic String GetAttribute(String key)

{

return (this.Attributes[key]);

}

public void SetAttribute(String key, String value)

{

this.attributes[key] = value;

}

#endregion

}

}

                             

No Comments