I've worked on projects at both extremes, from all functionality piled into one page to all functions having a dedicated usercontrol. At the very least, I recommend doing the following:
- Site-wide design belongs in your masterpages
- Functionality which appears on two or more pages should be encapsulated in a user control. (A login control, for example, might appear in several locations.)
- Other functions is perfectly fine to embed in your aspx page.
The tricky part is getting communication right, which can be difficult when you have deeply nested layers of controls which need to communicate with one another, or when you have a control on a master page which needs to notify controls on a child page (if they exist). If you need communication between two or more levels of controls, use the following model:
ProxyNotifier
/ \
Control1 Control2
In other words, Control1 and Control2 both have access to a ProxyNotifier instance. Control1 signals ProxyNotifer, and ProxyNotifer passes the signal to Control2.
A very simple implementation would look like this: (CAUTION: untested code, not intended for production use):
public static class ProxyNotifer
{
// NOTE: This delegate should NOT be held in a static variable since
// its session specific
private static Action<string> NotifyEvent
{
get
{
if (!Session.ContainsKey["ProxyNotifyEvent"])
{
Session["ProxyNotifyEvent"] = null;
}
return Session["ProxyNotifyEvent"] as Action<string>;
}
}
public static void Subscribe(Action<string> handler)
{
NotifyEvent += handler;
}
public static void Unsubscribe(Action<string> handler)
{
NotifyEvent -= handler;
}
public static void Invoke(string msg)
{
if (NotifyEvent != null) { NotifyEvent(msg); }
}
}
public class Control1 : UserControl
{
void SomethingHappened()
{
ProxyNotifyer.Invoke("Hello world!");
}
}
public class Control2 : UserControl
{
public Control2()
{
ProxyNotifer.Subscribe(Respond);
}
// ALWAYS unregister your event when your control is disposed,
// otherwise weirdness happens
public void Dispose()
{
ProxyNotifier.Unsubscript(Respond);
base.Dispose();
}
public void Respond(string msg)
{
lblMsg.Text = msg;
}
}
Now Control1 and Control2 can communicate no matter where they are on the page.