Custom Controls

ASP.NET makes custom controls extremely easy to write, but if you are not careful, hard to manage.

There are 2 ways to create a custom control

  1. Writing your own HTML code
  2. Using the controls property

Writing your own HTML code

Using your own properties, you can easily write HTML code to generate the
output

e.g consider a simple scenario where you take in a text and color input and
render the control.

You can simply create a class and extend it from the WebControl base class to
have the functions available to your custom control.
Thereafter, just create the properties you require and use them inside the
Render function.
Do note that you can render different output when in design mode and actual
rendering, all you need is to check the DesignMode property.
If however you need input boxes, do take note that you need to handle the
postback event and put the value back into the inputs manually.

public class
SimpleControl :
WebControl

{

public
SimpleControl()

{

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string Text

{

get

{

object obj =
this.ViewState[“Text”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Text”]
=
value; }

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string Color

{

get

{

object obj =
this.ViewState[“Color”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Color”]
=
value; }

}

protected
override
void Render(HtmlTextWriter
writer)

{

writer.Write(“<font color='”
+ Color +
“‘>” +
Text +
“</font>”);

//base.Render(writer);

}

}

Using the controls property

The good thing about using the controls property is that you do not need to
care about ViewState (it is handled by the individual control), Postback
inputs handling (handled again by the individual control).

The bad thing is

  1. Have to write your own custom event handlers
  2. Everything needs to be control based, you cannot emit your own html.

public class
LabelExtendedControl
:
Label

{

public
SimpleControl()

{

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string xText

{

get

{

object obj =
this.ViewState[“Text”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Text”]
=
value; }

}

[BindableAttribute(true),
Category(“UI”),
DefaultValue(“”)]

public
string xColor

{

get

{

object obj =
this.ViewState[“Color”];

if (obj ==
null)
return
“”;

else
return obj.ToString();

}

set {
this.ViewState[“Color”]
=
value; }

}

protected
override
void Render(HtmlTextWriter
writer)

{

this.Text = xText;

this.ForeColor =
System.Drawing.
Color.FromKnownColor(xColor);

base.Render(writer);

}

}

Custom Events

To create your own custom events, you need
to write 3 main items

  1. A readonly object containg the event
  2. A function which will call the Event
  3. The actual event handler itself

private
readonly
object EventCreate =
new
object();

protected
virtual
void OnCreate(EventArgs
e)

{

EventHandler
onCreateHandler = (
EventHandler)Events[EventCreate];

if
(onCreateHandler !=
null)
onCreateHandler(
this,
e);

}

[Category(“Action”),Description(“Raised
when a CommandEvent occurs within an item.”
)]

public
event
EventHandler Create

{

add

{

Events.AddHandler(EventCreate, value);

}

remove

{

Events.RemoveHandler(EventCreate, value);

}

}

Performance Programming with ASP.NET Ajax

At first glance, ajax seems to be a cinch with asp.net 3.5, what with all the updatepanel, timers and such. However behind this ease of development hides a danger which most developers may not notice.

Although updatepanels and timers are easy to use, each update triggers a complete postback and if your viewstate is on the page, its an extremely large form post. On the server side, each event of a normal postback is called, and the whole control tree is generated to handle the ajax form post. This is quite intensive both for the server and for the client.

This can be good or bad depending on how you look at it. Its good because it ensures that the postback is a valid one, and also gives you flexibility on the controls you want to change and to include in any javascript that you need, all these being done on the code behind, without the need to fiddle with all the client side javascript required to perform these actions.

On the flip side, there are also client side apis and scriptmanager service references which gives you complete flexibility to go ahead and program using client side javascript.

Nexus initially went with the first approach (i.e a whole bunch of updatepanels), but the results were less than impressive. Moving onto the second approach required a revamp of the whole source code, but this gave the user a much better experience along with substantially reducing server load.

To reduce the footprint on the server side, i utilized ScriptManager’s ServiceReference parameters

<asp:ScriptManager ID="ScriptManager" runat="server"
      onasyncpostbackerror="ScriptManager_AsyncPostBackError">
<Services>
    <asp:ServiceReference InlineScript="true" Path="JSON.asmx" />
    <asp:ServiceReference InlineScript="true" Path="ProxyAsync.asmx" />
</Services>
</asp:ScriptManager>

ServiceReferences exposes the webservice functions in client side javascript so you can call these webservices without having to write complicated javascript. for example, i have a webservice function called UserFirstLoad(). This function is called the everytime the user logs into Nexus.

[WebMethod]
[ScriptMethod(UseHttpGet = false, XmlSerializeString = true)]
public JSON_Tabs UserFirstLoad()

Instead of writing javascript to interface to this webservice, ScriptManager automatically writes it for you and exposes it nicely as JSON.UserFirstLoad(), a function which i can easily call and have the capability to do error handling if need be.

As i’m not using UpdatePanel, GUI updates are done directly via DOM. Fortunately Ajax ClientScripts provide some global functions which i can use to

  1. Locate the element i want to update ($get)
  2. Add events to the element ($addHandler)

It is also fortunate that Visual Studio 2008 comes with javascript intellisense, which autocompletes your javascript as you type.

As Javascript is OOP, i decided to build my client script scripts around objects and functions. This gives me the flexibility to overwrite functions and have nice clean code which i can then easily debug with VS2008.