2
\$\begingroup\$

Is this useful or is there an obvious other way?

The context is solving the problem of bubbling events in an asp.net site built with user controls and nested user controls. I found myself writing a ton of events.

So instead of events, i'm using a technique to allow any client to watch an arbitrary session value.

A shared context class for Page and UserControl. Updates to session values go through here as well as registrations for session value changes.

public class WebSiteContext
{
    private WebSitePage _webSitePage;

    public WebSiteContext(WebSitePage webSitePage)
    {
        _webSitePage = webSitePage;
    }

    internal void SetSessionValue<T>(string key, T value)
    {
        object current = _webSitePage.Session[key];
        if (current != null && current.Equals(value)) return;
        _webSitePage.Session[key] = value;
        if (_dic.ContainsKey(key)) _dic[key](value);
    }

    internal Dictionary<string, Action<object>> _dic = new Dictionary<string, Action<object>>();

    internal void WhenSessionValueChanges(string key, Action<object> action)
    {
        _dic.Add(key, action);
    }
}

Base page constructor creates context instance.

public class WebSitePage : System.Web.UI.Page
{
    public WebSitePage()
    {
        this.WebSiteContext = new WebSiteContext(this);
    }

    public WebSiteContext WebSiteContext { get; set; }
}

Base user control property to get context from parent page.

public class WebSiteUserControl : System.Web.UI.UserControl
{
    public WebSiteContext WebContext { 
       get { 
          return (this.Page as WebSitePage).WebSiteContext; 
       } 
    }
}

A user control makes a change to a session value.

public partial class AdvertiserSelector : WebSiteUserControl
{
    protected void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
    {
       this.WebContext.SetSessionValue(
          SessionKeys.current_advertiser_id,
          (sender as ComboBox).SelectedValue);
    }
}

Now in my web page code behind, instead of subscribing to an event, an action is registered for a session value change.

namespace WebApplication1.Screens.CampaignSpend
{
    public partial class Default : WebSitePage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            this.WebSiteContext.WhenSessionValueChanges(SessionKeys.current_advertiser_id, c => GridView1.DataBind());
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

What you have implemented is just a change event for the session value, but as you are using a delegate instead of event only one control at a time can register for the event.

Use an event instead of a delegate, and you have a regular change event for session variables.

\$\endgroup\$
  • \$\begingroup\$ i felt like i was missing somehting... would the client then have to both register which session keys it was interested in as well as subscribing to the event? I'm not saying that's bad - i think it was my tendency to want one step that led me down this road \$\endgroup\$ – Aaron Anodide Oct 21 '11 at 17:33
  • 1
    \$\begingroup\$ @Gabriel: You can use most of the code as it looks now, but have a dictionary that contains events instead of delegates. That way you can add multiple event handlers to it. Come to think of it, delegates are multicast too, so you could use the existing dictionary and combine delegates: msdn.microsoft.com/en-us/library/ms173175%28VS.80%29.aspx \$\endgroup\$ – Guffa Oct 21 '11 at 18:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.