Exploring the depths and potentials of ASP.NET RSS 2.0 or Subscribe to .BenRush by Email
 Sunday, May 21, 2006

A friend of mine and I are buying supplies for brewing beer at his house - if anyone has any experience with this, let me know. Thanks!


kick it on DotNetKicks.com
Sunday, May 21, 2006 11:09:27 AM (Central Standard Time, UTC-06:00)  #    Comments [1] - Trackback
Personal Adventures
 Monday, May 15, 2006

I'm going to continue digging into the UpdatePanel control since the last post I made on this subject, so if you haven't read it, I would recommend doing so first...

The UpdatePanel is a wonderful utility for quickly taking a non-Atlas'ized ASP.Net website and Atlas'izing it, as it empowers you to simply surround traditional controls with <atlas:UpdatePanel> tags to enable them for partial postbacks. However, UpdatePanels can be somewhat misleading too: most people fail to realize (at least I did at first) that the UpdatPanel itself does not post back to the server, instead it is updated on the client using clever DHTML tricks (all controls within an UpdatePanel are surrounded, on the client, by either a span or div tag which is easily identified and whose children are easily over-written and modified). What actually posts back to the server is the PageRequestManager control script which is aided by the dealings of the ScriptManager control on the server. This simple fact - that the UpdatePanel doesn't post back - is important to realize, especially when one begins to think in terms of setting up triggers to update the content of the UpdatePanel. It becomes more of a mindset shift, really...but one that's important to make....let me explain...

Triggers are client-side controls that give developers the ability to say, basically, "I want the content of the UpdatePanel to refresh when such-n-such happens". Out of the box, Atlas comes with two types of triggers: a ControlEventTrigger and a ControlValueTrigger, which "trigger" the update of the UpdatePanel when either a clientside event occurs (button click, etc.) or value changes (text box content) respectively. Asigning triggers to an UpdatePanel is simple and is done like the following:

            <atlas:UpdatePanel runat="server" ID="UpdatePanel3" Mode="Conditional">
                <Triggers>
                    <atlas:ControlEventTrigger ControlID="btnTrigger" EventName="Click" />
                </Triggers>
                <ContentTemplate>
                    <asp:Label runat="server" ID="lblTime2" /><br />
                </ContentTemplate>
            </atlas:UpdatePanel>

...Note the <Triggers></Triggers> tags and the encapsulated instance of the <atlas:ControlEventTrigger>. Again, what this says to the Atlas runtime is that when the control btnTrigger is Click'd that the UpdatePanel ought to have its controls refreshed. Since the <Triggers> control exists "within" the UpdatePanel control (parent/child relationship in the XML), you can see how one would think the UpdatePanel is responsible for doing all clientside postbacks. The result of thinking this way would lead you to think you could simply point to any control you wanted and hook any event you wanted and the UpdatePanel will blindly post back for you, updating the content. The truth is, however, that the UpdatePanel relies on other controls to start the postback sequence in motion; this postback sequence gets "intercepted" by the Atlas clientside framework and re-submitted as a specially formatted postback (for the Atlas serverside framework to deal with). So, let me reiterate this fact: the control that has the trigger attached must initiate the postback!

Why is this important? If the control doesn't start a postback on its own then 1) the browser won't try to postback, 2) the clientside framework won't intercept the postback event, and 3) the framework won't be able to re-submit the post as a partial one and allow the serverside framework to take over, and so forth. As programmatic proof, take a gander at this XML Script statement declaring the PageRequestManager on a page with UpdatePanels and triggers for those panels:

<script type="text/xml-script">
<page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
  <components>
    <pageRequestManager id="_PageRequestManager" updatePanelIDs="Panel1,Panel2,Panel3" asyncPostbackControlIDs="AsyncPostBackButton,Panel3bButton" scriptManagerID="TheScriptManager" form="form1" />
  </components>
</page></script> 

Note the instance of the _PageRequestManager object of type pageRequestManager above between the <components> tags. It has a property, asyncPostbackControlIDs, whose value is a comma-delimited array of control names who, you guessed it, have triggers assigned to them from within UpdatePanels. When an event that triggers a postback is fired on the page, it goes through the follow method at one point in the client code base:

this._doPostBack = function(eventTarget, eventArgument) {
   ...
   _postbackSettings = null;
   var postbackElement = findNearestElement(eventTarget);
   if (postbackElement) {
      _postbackSettings = getPostbackSettings(postbackElement);
   }
   else {
      _postbackSettings = createPostbackSettings(true, _scriptManagerID);
   }
   if (!_postbackSettings.async) {
      _originalDoPostBack(eventTarget, eventArgument);
      return;
   }

   var form = _form;
   form.__EVENTTARGET.value = eventTarget;
   form.__EVENTARGUMENT.value = eventArgument;
   this._onFormSubmit(); 

   if (window.event) {
   window.event.returnValue = false;
   }
}

The _postbackSettings.async property holds a boolean value stating with (True) the control is flagged for partial postbacks or (False) it's not. A status of True is given to any clientside control within an UpdatePanel or pointed to by a trigger from within an UpdatePanel. If this boolean switch is False, then an old-style postback occurs (refreshing the entire page), else the _onFormSubmit method is called which spawns an asynchronous postback to the server, etc.

One final question exists, however - and that's how does the <PageRequestManager> gets its property values? Or, who sets the asyncPostbackControlIDs property on the <PageRequestManager> object for the page? The answer is the ScriptManager control when it renders on the server. After this control's PreRendering phase on the server, it calls the following method which, as you can see at the end, is responsible for setting the property names and values (the values were built using StringBuilder objects):

private void RenderPageRequestManager(ScriptTextWriter writer)
{
   GenericScriptComponent component1 = new GenericScriptComponent(new ScriptTypeDescriptor("pageRequestManager", ScriptNamespace.Default));
   component1.ID = ScriptManager.PageRequestManagerID;
   StringBuilder builder1 = new StringBuilder();
   if (this._allUpdatePanels != null)
   {
      for (int num1 = 0; num1 < this._allUpdatePanels.Count; num1++)
      {
         ...
         builder1.Append(",");
         ...
         builder1.Append(this._allUpdatePanels[num1].UniqueID);
      }
   }
   StringBuilder builder2 = new StringBuilder();
   if (this._asyncPostbackControls != null)
   {
      for (int num2 = 0; num2 < this._asyncPostbackControls.Count; num2++)
      {
         ...
         builder2.Append(",");
         ...
         builder2.Append(this._asyncPostbackControls[num2].ClientID);
      }
   }
   component1.AddValueProperty("updatePanelIDs", builder1.ToString());
   component1.AddValueProperty("asyncPostbackControlIDs", builder2.ToString());
   component1.AddValueProperty("scriptManagerID", this.UniqueID);
   component1.AddValueProperty("form", this._page.Form.ClientID);
   ...
}

Each trigger adds an entry for itself in theScriptManager's _asyncPostBackControls array when the control is being built and each trigger is being initialized on the server by its UpdatePanel.


kick it on DotNetKicks.com
Monday, May 15, 2006 1:14:02 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing
 Thursday, May 11, 2006

....is more than a name.


kick it on DotNetKicks.com
Thursday, May 11, 2006 11:57:57 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Ranting
 Wednesday, May 10, 2006

This is an interesting exception that you might get when dealing with Ajax; more specifically, when trying to assign an EventName to a trigger. The situation might look something like this in your .aspx code:

                                <atlas:UpdatePanel runat="Server" ID="MainBody">
                                    <Triggers>
                                        <atlas:ControlEventTrigger ControlID="LinkButton1" EventName="OnClick" />
                                    </Triggers>
                                    <ContentTemplate>
                                        <%=System.DateTime.Now().ToString()%>
                                    </ContentTemplate>
                                </atlas:UpdatePanel>

What this block of xml script is telling the Atlas server framework to do is find the server control "LinkButton1" in the control tree and handle it's event "OnClick". It does this by telling the <ScriptManager> to first swallow any submit events for this client control (so that the form doesn't do a full postback) and then send back an asynchronous form post instead (basically intercepting the full postback and turning it into a partial postback). The stack trace for the exception is raised from within the Initialize() method of the Microsoft.Web.Atlas.ControlEventTrigger type:

protected internal override void Initialize(Control ownerControl)
{
   ....
   EventInfo info1 = null;
   string text1 = this.EventName;
   if (text1.Length != 0)
   {
      info1 = control1.GetType().GetEvent(text1);
   }
   if (info1 == null)
   {
      throw new InvalidOperationException("The EventName must be set to a valid event name on the associated control.");
   }
   ...
}

Note that it does a control1.GetType().GetEvent() on the data type of the control you're hooking the event on. So...go back and look at your control. As the exception suggests, you're hooking an event on the control that doesn't exist. The confusing part, however, is that you may think that it's hooking CLIENT events, but it's not...the ScriptManager is snagging the client events that cause a postback on this client control, doing a parital postback for it, and then updating the region of the UpdatePanel based on the response from that partial postback. The UpdatePanel, itself, isn't actually doing the postback (in other words, it's the ScriptManager control doing the partial postback, not the UpdatePanel).

....in the case of the XML Script above, to fix it you simply replace "OnClick" (the clientside eventname) with "Click" (the server side eventname).


kick it on DotNetKicks.com
Wednesday, May 10, 2006 2:46:12 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing

....then I'd recommend downloading the Windows Live Messenger (basically, the next generation of MSN messenger) from here. I'm currently in the process of the download right now, so I can't give any critical feedback at the moment.


kick it on DotNetKicks.com
Wednesday, May 10, 2006 1:26:10 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing

....I created this outline of how runtime types are loaded by the CLR. I just re-discovered this outline and thought I would post it for everyone's bedtime reading enjoyment ;)

 


kick it on DotNetKicks.com
Wednesday, May 10, 2006 1:23:42 AM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing

Today I was checking the referrer URLs in my blogs statistics and one of them came out to be this address: http://alternativeviagra.drugsmedic.com/.

After visiting the site, I still am confused as hell as to how THAT referred someone to MY blog.


kick it on DotNetKicks.com
Tuesday, May 09, 2006 11:00:02 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Ranting
 Tuesday, May 09, 2006

....come and get em.


kick it on DotNetKicks.com
Tuesday, May 09, 2006 3:26:52 PM (Central Standard Time, UTC-06:00)  #    Comments [0] - Trackback
Computing

Computers Blogs - Blog Top Sites

Archive
<May 2006>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
Blogroll
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009
Benjamin Rush
Sign In
Statistics
Total Posts: 444
This Year: 0
This Month: 0
This Week: 0
Comments: 128
Themes
Pick a theme:
All Content © 2009, Benjamin Rush
DasBlog theme 'Business' created by Christoph De Baene (delarou)