October 2006 - Posts

Handling errors globally
Tue, Oct 31 2006 4:32

Mike Weerasinghe has made a good question regarding my previous post about error handling. Mike says that he's handling errors by using a module which handles the HttpApplication error event. Unfortunately, this will stop working when you use AJAX extensions because the ScriptManager control will handle the error and automatically return a response to the client stopping the event from being propagated to the HttpApplication object. So, if you're handling the Error event of that class, you won't be notified about the error and your logging will stop working.

The solution to this is to handle the Error of the Page since the methods that handle it will always be called if you get an exception during a partial postback. Since I think nobody will want to add their logging logic to all the pages and will probably want to keep handling the error from a module, then there's a workaround which might just work with you. What you need is to handle the PostMapRequestHandler event, which is fired by the HttpApplication object after mapping the current request to a handler. During that event, you can check for the current handler and see if it's a page. If it is, then you just need to handle the Error event and you should be ready to go. Here's a sample which shows what you need in order for it to work (I'm pasting the code from global.asax, but it should also work from a module though i haven't tested that):

protected void Application_PostMapRequestHandler(object sender, EventArgs e)
{
  Page aux = this.Context.Handler as Page;
  if( aux != null )
  {
        aux.Error += new EventHandler(page_Error);
   }
}

void page_Error(object sender, EventArgs e)
{
   //log error as you want
}

By hooking the error event like this, your method will always be called before the one introduced by ScriptManager and you will have access to the current exception. Just don't clear it because if you do, the ScriptManager's method will not get the info it need to its work.

Hope this helps...

Update: I was so eager to get a general error handling solution that i've just forgot about object lifetime! As my good friend João Paulo said in the comments, my previous solution might be bad if you don't want to leak resources (and yes, I do believe that you don't). As he said,  I should remove my event handler so that I don't keep the page alive. However, there's a problem with the PostRequestHandlerExecute event handling: though I could be mistaken, but I think it won't be called due to the way that ScriptManager handles the Error event generated by the page: it calls Response.End after packaging the response which is being sent back to the client. So, removing the method from the event list during the page_Error method might be the best option to this scenario (specially if you know that the page has a ScriptManager control)

btw, thanks for the correction João...and don't be a stranger! :)

Update2: re-reading my previous update made me think that I didn't explain myself correctly. My previous remarks are only valid for when an exception happens in a page that has a ScriptManager control. If there isn't an exception, you still should hook a post execute handler event in order to unsubscribe the event handling...

Triggers: better control over postback
Mon, Oct 30 2006 16:59

Like the previous CTPs, the current beta version introduces 2 "usable" triggers: AsyncPostBackTrigger and PostBackTrigger. I call them "usable" because they're the leaves of the hierarchical tree defined by the AJAX extensions on the server side. As you can infer by their names, the AsyncPostBackTrigger is responsible for starting an async postback while the PostBackTrigger manages to get a full postback. In current releases, the framework only gave us async postback triggers. So let's see what we can do with the new ones...let's start with the AsyncPostbackTrigger.

You normally use it when you want to configure a control placed inside outside ([Updated: thanks Garbin!]) an UpdatePanel so that a postback started by the control results in partial postback (instead of the usual full postback). Do keep in mind that if you have more than one UpdatePanel on  a page, the number of panels that are refreshed during the partial postback depend on the UpdateMode of each panel (if it's set to always, then it'll be refreshed, even though the trigger may not be associated with that panel). Opposite to one might think, there is at least one scenario where you might want to associate an AsynPostBackTrigger to a control placed inside an UpdatePanel: when you set the UpdatePanel's ChildrenAsTrigger property to false. When this happens, all postbacks started by controls placed inside UpdatePanels do result in full postbacks by default! So, in these situations, you might need to add an AsyncPostBackTrigger to get an async postback when a postback is started by a specific control.

When you use an AsyncPostBackTrigger, you must set two properties: ControlID and EventName. Both these properties work together and influence the behavior of the UpdatePanel during a partial postback (ie, if it is refreshed or not). To understand why, you must know that the PageRequestManager (which is responsible for intercepting postbacks and deciding if you'll get a partial or a full postback) doesn't have the concept of trigger. It only knows if a specific control can (or cannot) start an async postback (it maintains an internal array with the IDs of the controls that can do that. When it intercepts a postback, it checks against that list to see if the responsible for the operation is on it: if it is, you'll get a partial postback - keep in mind that this is just one of several steps envolved in checking if the current postback should be partial or full).

So, when the server side is handling a partial update, ScriptManager ends up calling an auxiliary method (in the PageRequestManager auxiliary class) which is responsible for going through all the UpdatePanels and checking the ones that need to be updated. As you might already have guessed, one of the steps performed during this verification is seeing if any of the associated triggers has been "triggered" (which only happens when the control's event associated to the trigger has been fired). Note that this is only important if the UpdateMode of the UpdatePanel is set to the Conditional (if it's set to Always, the UpdatePanel will always be refreshed).

Declaring an AsyncPostBackTrigger is as simple as writing this:

<asp:UpdatePanel runat="server" ID="painelEsquerdo" UpdateMode="Conditional">
  <ContentTemplate>
       <span>DateTime last partial postback:</span><%= DateTime.Now.ToString() %>
  </ContentTemplate>
   <Triggers>
           <asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click" />
    </Triggers>
</asp:UpdatePanel>
<asp:Button runat="server" ID="myButton" Text="Refrescar painel" OnClick="HandlePartialPosback" />

It's time for the PostBackTriggers. These triggers only have one interesting property: ControlID. As you may now, you can use these triggers to identify a control placed inside an UpdatePanel which is responsible for starting a full postback. This is important when you have <input type="file"> controls on your page since a full postback is the only way you can get that info back on the server (there are some workarounds, which envolve creating iframes, but will leave that for another day). Besides keeping an internal list on which controls can start a partial postback, the PageRequestManager also keeps a list of those controls that can start a full postback. When you use this trigger, you're adding an item to that list. The usage of the trigger is really simple and looks a lot like the previous one (and due to that we won't waste any time by putting it here). and that's it for today...

XBox 360 + Transcode 360 + Media Center = great afternoon!
Sun, Oct 29 2006 16:42

Yep, just had a great time this afternoon watching some videos on my TV by using XBox 360 + Transcode 360 to get the divx streamed to the XBox. really recommend it!

by luisabreu | 1 comment(s)
Filed under:
UpdatePanel: having fun with errors
Sun, Oct 29 2006 15:52

UpdatePanel has always given us some sort of error handling during partial postbacks (or, if you want to use the new official term, async postbacks). In previous CTPs, you could handle a page error event and perform your own error handling (which normally consisted in some form of logging). The problem previous versions had was related with the way that the error message was shown in the client side (by default, it showed an alert message box, though you could define a limited error template). The current release give us a lot more options as I'll show you in this post.

If you don't do anything, when you get an error during partial postback you'll get a simple alert message box showing you the error message associated with the exception you had in the server. As we all agree, this is not the best info to show to our users; it's also not a good idea to show a standard error message. If we don't mind showing an alert message in the client, then we can start by handling the AsyncPostBackError event generated by the ScriptManager control in order to customize the error message returned from the server. Here's a simple page that shows this approach:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void handleClick(object sender, EventArgs e)
{
   int a = 0;
    int res = 10 / a;
}
void HandleError(object sender, AsyncPostBackErrorEventArgs e)
{
    //here we could log the error, and see which exception we're getting in order to set a specific error message
    //in this case, I'm just returning the current date/hour back
    manager.AsyncPostBackErrorMessage = "Ooops...error occurred:  " +
     DateTime.Now.ToString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
   <head runat="server">
     <title>Untitled Page</title>
    </head>
<body>
  <form id="form1" runat="server">
        <asp:ScriptManager runat="server" ID="manager"
               OnAsyncPostBackError="HandleError">
        </asp:ScriptManager>
        <asp:UpdatePanel runat="server" ID="panel">
            <ContentTemplate>
               <asp:Button runat="server" ID="bt" Text="gerar erro no servidor"
                OnClick="handleClick" />
            </ContentTemplate>
         </asp:UpdatePanel>
   </form>
</body>
</html>

As you can see, when the user clicks the button, he'll get a divide by zero exception error on the server side. The previous page shows how you could log the error and return a friendly error message back to the client (the AsyncPostBackErrorMessage was introduced in this version and lets us define the error message which is returned to the client when an exception occurs on the server side). If you run the page, you'll notice that you'll still get the alert message, but this time, it'll show our fridendly error message.

If you want, you can drop the standard alert message and show the error in any way you see fit. To illustrate the steps necessary to perform this operation, I'll start by adding a DIV ccontrol that will be used as a place holder for showing the error returned from the server:

<div id="err"></div>

The next thing we need to do is to handle the endRequest event which is fired by the PageRequestManager object which is present in all the pages that use UpdatePanels:

<script type="text/javascript">
   Sys.WebForms.PageRequestManager.getInstance().add_endRequest( endRequest );
   function endRequest( sender, e ) {
        if( e.get_error() ){
               document.getElementById("err").innerText =  e.get_error().description;
               e.set_errorHandled( true );
        }
   }
</script>

I start by adding a method that will handle the endRequest event by using the add_endRequest method over the Sys.WebForms.PageRequestManager global object. The method starts by checking if there's an error (by using the get_error method) and, when it finds one, it gets its description (through the description field) and sets the errorHandled field of the EventArgs object used to true so that the default alert message isn't shown to the user. Though the previous code is really simple, there's nothing preventing you from using the toolkit behaviors to get similar results to the ones that we had in the previous CTPS (btw, you can also stop processing the server side error event if you don't need logging and do everything in the client side: you're the one that need to decide on what's best here!).

For those that want to show a default error page, then there's still one additional property exposed by ScriptManager which you'll like: AllowCustomerErrors. When you set this property to true, you're saying that ScriptManager should check for a custom error page associated with the current error an show it to the user. To illustrate its usage, lets start by adding the following to the web.config file:

<customErrors mode="On">
     <error statusCode="404" redirect ="error.aspx"/>
</customErrors>

And now lets run the following page:

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void HandleClick(object sender, EventArgs e)
{
     this.Server.Transfer("nopage.aspx"); //don't do this in reall AJAX pages!!!!!
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head runat="server">
      <title>Untitled Page</title>
   </head>
<body>
<form id="form1" runat="server">
   <asp:ScriptManager runat="server" ID="manager"
        AllowCustomErrors="true" />
   <asp:UpdatePanel runat="server" ID="panel">
       <ContentTemplate>
          <asp:Button runat="server" id="bt" Text="postback"
               onclick="HandleClick" />
      </ContentTemplate>
    </asp:UpdatePanel>
</form>
</body>
</html>

First, you should note that you should never use a Server.Transfer instruction on an ajax page. I'm using it since it's simplest way I could think of getting a known 404 error. Now, back to the important things: the AllowCustoErrors property. Since i've set it to true, when ScriptManager handles an exception during an async postback, it'll read the config file and see if there's any error page associated with the current error. If there is, it'll just send an AJAX message to client which instructs the browser to redirect the user to the desired page.

As you have seen, there's now a lot more control over the way exceptions are handled during a partial postback request. You do have to write more code than in the previous versions, but it's also true that the current release is a lot more flexible than the previous one.

by luisabreu | 39 comment(s)
Filed under: ,
Xml-script: how to use your custom classes from it
Thu, Oct 26 2006 6:57

Today I've built a simple custom Action so that I could see what is needed to use a custom element from xml-script. So I started with something like this:

Type.registerNamespace( "LA" );
LA.MyAction = function(){
 //code...doesn't really matter
}
//more prototype code which really doesn't matter :)
LA.MyAction.registerClass( "LA.MyAction", Sys.Preview.Action );

It was time to start writing xml-script...Though I really knew it didn't work, I started by trying something like this:

<script type="text/xml-script">
  <page xmlns:script="http://schemas.microsoft.com/xml-script/2005">
     <components>
          <button id="bt">
               <click>
                    <MyAction> 
                     ...
                  </MyAction>
              </click>
        </button>
     </components>
   </page>
</script>

Yes, it didn't work because the parser was looking for the MyAction class in the default namespaces added by the AJAX client bits. I though that there should be a way to associate a xml namespace with the namespace used in Javascript where my class was defined. After taking a peek at the previewscript.js, I didn't found any method which registered a namespace. So, I decided to look at the _processPrefixMapping method of the Sys.Preview.MarkupParser to see what was going on during xml namepsace resolution. As i've already said, when you use the default namespaces, you automatically get the namespace list defined by the AJAX bits; If you're using a different namespace, then you must make sure that the value you use for the xml namespace is the same you've used for the code namespace (and please pay attention to case-sensitivity because it's important here). So, that means that in order for my code to be correctly interpreted, you need to do this:

<script type="text/xml-script">
  <page xmlns:script="http://schemas.microsoft.com/xml-script/2005" xmlns:test="LA">
     <components>
          <button id="bt">
               <click>
                    <test:MyAction> 
                     ...
                  </test:MyAction>
              </click>
        </button>
     </components>
   </page>
</script>

And now the parser is happy and able to instantiate my custom action. There are some remarks about this strategy:

  • I understand why they do that, though I'd really prefer to be able to associate a specific xml namespace to a code namespace. In other words, I'd prefer to call a register method so that I could say: "map http://mydomain.com" to  namespace X and namespace Y"
  • If you really want to go this way (ie, use the same name for a code namespace and a xml namespace), then one of things must be done: make element names case sensitive too (currently, you only need to write the name of the class, without paying any attention to capital letters) or remove that restriction from domain registration

So, it looks like today xml-script is still sucking a little bit :) And what do you think?

by luisabreu | 4 comment(s)
Filed under: ,
Dino, you're wrong about beta 1!
Wed, Oct 25 2006 16:07

It seems like Dino Esposito isn't happy with the changes made to the AJAX extensions.  I certainly agree with him when he says it's a new product. I also agree that it's relly a PITA to have a book which is being printed and already being somewhat out of date...however, I do think that several of the claims he makes aren't really true. Dino says that "The July CTP was a pretty good one and ready for Beta stage". I completly disagree with this. If you don't believe me, then take a look at the unofficial bug list posted by Garbin on the AJAX foruns. Several of those bugs are really show stoppers and made the previous CTP completly unusable in several real scenarios(for instance, the timeout of the login session cookie which was ignored by the UpdatePanel control). I almost agree with him when he says that "What we have now is a brand new start and is probably less than a stable alpha". As you might guess, I really don't think that the current release is less than a stable alpha...

He also seems confused about seeing 2 download packages. I agree that it would be really cool to get support for all the bits, but it seems like the team can't do that just now and that's why you get 2 packages: one has full support and other is given as value-added to the core bits. I'm not saying that the team shouldn't support everything...I'm just trying to explain why we have two packages (count on me to pressure the team to put more stuff into the supported bits!).

I'm not sure on what Dino is asking here:

"Which version should I study and teach? Both?
Which version should I recommend to clients and which to implement?
What if I have sites using July CTP? I feel comfortable only with Web services and UpdatePanel stuff"

If he's asking between previous CTP and the latest bits, then the answer is really simple: the last bits! Even if the team backs up and brings us some of the previous goodies, like for example, instance page methods (damn! goodies wasn't a well chosen name, specially when we're speaking about instance page methods :) - if you want to know why, then check it here), it's obvious that the latest bits are really better than the previous ones, even though they have less features.

If he's asking if he should look at the core bits or at the value-added bits, i'd really go with both, though only one is officially supported by MS. btw, there aren't really lots of changes between previous CTPS and the current version when you think in terms of web services and UpdatePanels, specially if you don't care about the internals (i admit that script injection from a partial postback is a breaking change, but easilly fixed in pages).

Dino goes on and complains about xml-script. I really think that there are still several things which could be fixed, but what I can say for now is that if xml-script doesn't work, then that's probably because of what i mention in this post. btw, xml-script is on the value-added bits and it has been improved in this last version, though it still suffers from several defects. I really see no ugly JS code on my AJAX pages and i'm really happy that i can easilly create new components with a simple method call ($create method). Yes, there are still some changes that could be made to the control API in order to simplify  control creation (for instance, client validation could really be improved with the addition of a singe method to the InputControl class!). Regarding changes in the near future, I really think that maybe they'll fix one or two bugs and maybe add one or two things that existed previously but were removed from this version. I do really think that these last bits are great and a lot better than previous CPTs. And I hope that Dino isn't upset only because he's book, that is gone to priting, is already somewhat out of date....

by luisabreu | 1 comment(s)
Filed under:
Xml-script is a lot better, but it still sucks a little bit...
Wed, Oct 25 2006 8:40

Today I finally got a chance to play with xml-script. The current implementation is, indeed, better than the previous one. Several things have changed in this version. For starters, the interface which was used in previous versions was dropped and now type descriptor objects (used internally for parsing and instantiating elements) are added directly to a "static" property of the class called descriptor. The anonymous object added to this property lets you define which properties, methods and events can userd from xml-script. In my opinion, this is a better approach than the one used before. Here's a quick example copied from the TextBox class:

Sys.Preview.UI.TextBox.descriptor = {
  properties: [ { name: 'text', type: String } ],
  attributes: [ { name: Sys.Preview.Attributes.ValueProperty, value: 'text' } ]
}

In the current version, you're also free to use  any variation of the name of a class that can be used from xml-script (I'm not sure if this is a good thing since XML is supposed to be case sensitive). In other words, if you want to use a Sys.Preview.UI.TextBox control from xml-script, you no longer have to call it <textBox> as happened in the previous versions. So, if you want it, you can use the word TEXTBOX or TEXTbox and everything should work without any problems. This is possible due to a change made in the internal type system and in the parsing engine. Internally, the parsing engine searches the name of the element in a list of namespaces previously registered (since each namespace maintains a list of classes, it's possible to get the type by using this new approach).

Another good news is that you can now perform the correct mapping between a prefix and a specific namespace too. This means that you can use whatever prefix you want and you aren't tied to the script prefix anymore (which, btw, is still the default prefix associated with AJAX controls).

There are still several things I don't like. First, you can still call your top level element anything you want (I've written about this in the past). Second, the current version still doesn't understand global namespaces and now you can't simply declarate a global namespace like this:

<page xmlns="....">
   ....
</page>

If you do this, the parser will not be able to get an internal list with the current OO namespaces associated with that global XML namespace and it won't create the elements specified inside the <components> element (this happens because currently the parser allways needs a prefix in order to get the correct list of mappings). So, if you really want to use an "AJAX" xml default namespace, you must do this:

<page xmlns:script="....">
   ....
</page>

Again, this is complete nonsense. Note that in xml terms, the second declaration means that script prefix is associated with a specific namespace and that the <page> element is in a global namespace. If you look at the first excerpt, it says the correct thing, ie, that the page element is defined in a global namespace identified by the xmlns attribute...I still haven't tested global custom elements. I think i'll leave that for tomorrow.

by luisabreu | 1 comment(s)
Filed under: ,
Page methods: why I prefer them to be static...
Tue, Oct 24 2006 9:32

In my previous post, I've presented an alternative to using the old page instance methods that existed on previous releases of the CTP. Since I'm always late, i didn't realize that there was already a heated debate on the community and hadn't even noticed that Rick Stralh had a post where he complains about several things in the new release of the AJAX extensions. One of the things he wants back is instance page methods.

Though i really didn't enjoy the old instance page methods, i'll try to perform an honest and independent analysis on instance vs static page methods. If you're reading this, you need to know that i'm not affiliated with Microsoft in any way  nor have been in the past. So, I'm not really defending them, but only giving my opinion on this subject (instance vs static page methods).

Before going on, I should also mention that i didn't really use the old instance page methods and I think I won't be using the new static page methods either (though I really prefer the latter approach). Let's start by the speaking about the strenghts of the old instance page methods. In my opinion, there was one big obvious advantage: you could do all your work from the server side without having to write any Javascript code on the client to get the values you needed. For instance, if you had to get the values of 2 or 3 controls and then perform some calculations on it and return something back to the client, you could simply write your sever method with C# (or other .NET language) and annotate it with the WebMethodAttribute and you were ready to go.

This is a great, specially if you don't want to bother with the details associated with Javascript. Yes, you still need to call the method from the client (by using the global PageMethods object), but you no longer need to get the values of the controls in the client side and pass them as parameters to the server method since you'll be doing that (getting the values of the controls) on the server side, using the traditional server side approach (control.property).

For a long time, I used to think that instance page methods had another advantage: you could update the view state of the page from within an instance page method call. If this was true, it would be its greatest advantage since without it, you couldn't really update the view state without using an UpdatePanel and getting its HTML back (as you must recall, UpdatePanel always returned its HTML in previous releases of the platform, which isn't normally needed when you're using instance page methods).

Unfortunately, I was wrong about this. I've run a simple test with an ancient ATLAS project and I've confirmed that the view state isn't really updated during an instance page method. In other words, you can change the view state of the page on the server side, during an instance page method call, but that info isn't sent back to the client side. Due to that, the hidden view state field isn't updated and when you get the next partial/full postback or perform the next instance page method call, you'll have the same old values that existed before the instance page method call you've just made. As I said, I've just reached this conclusion by running an old ATLAS app and using fiddler to see what the page is getting back from the server (I really can't be sure if this was the behavior present on the previous July CTP, though I think it was).

The biggest disadvantage I see with page methods is that a method call results in sending all the existing form fields back to the server. For instance, let me give an example (which is really an extreme example of how things can be bad). Suppose you have 100 textboxes (sorry Garbin, you've influenced the number of controls:) ) and you need to get the values of 3 of them to perform some calculations on the server side. Using the old instance page method means that the page will be sending the values of the 100 textboxes + the other controls maitained inside the web form (for instance, suppose that you're using viewstate...yes, you'll get that field sent back to the server too). Remember: you just needed the values of 3 textboxes. Unfortunately, that doesn't matter when you use the old page methods since the client really need to send eveything back in order for you to use the controls during the remote instance page method call.

Since you can't really change the view state of the page, the only thing page methods are letting you do is making sure that you don't leave the confort of writing C# code on the server side where things are more coherent than in the client side. Now think about a performace point of view: are really page methods that great? shouldn't you be using Javascript and perform a simple web method call in order to get your result back? think about it...using the instance page method is easier and really confortable...but is it really performant? I'd say no and I'd even go further and say that most things (if not really all the things) that currently are being done with it could be done through web methods calls... that's why I didn't like the old instance page methods: you can build them easilly, but you're paying a huge price when you use them.

Now enter the new static page methods. If you've been using the old instance page methods, you already know that the new static methods are useless for you since you don't get any context associated with the method call (ie, you're no longer able to use the controls on the server side). Reusing the previous 100 TextBoxes example, you will need to get the values of the 3 Textboxes through Javascript in order to perform the remote page method call. I concede to the old instance page method users when they say that having a page method without context is almost useless.

But no totally useless, though, since they solve a problem which existed on the previous releases: how could you write a method on the server side and invoke it from the client without developing a web service? the new static page methods solve this problem and let you perform a remote method call without having to develop web services. The new static page method are also more performant since they don't automatically pack all the form fields when you perform a remote call (which is logical, since the server method is static after all).

So, the new static methods are useful if you're not into writing web services to perform remote server method calls.

Many say that not including the old instance page method calls means that AJAX extensions have less features than in previous releases. Well, that is a fact, but at least you've got one less thing to shoot yourself in the foot. On the other hand, I must say that having the old instance page methods really helped many to write remote method calls without using Javascript code and that there are lots of guys which really don't care about performance and just want to quickly build AJAX pages (not my view of how things should work, but everyone is entitled to think and act as they like).

So, in order to get everyone happy, I'm proposing some fixes for the next release. For starters, we should be able to call static and instance page methods from the client side (you already know that I won't be calling instance methods, but I'm sure that others will). Instance page methods would work as they did in previous releases and static methods would work as they do now. To support this, the team would have to include a new client class (like they did in previous releases) which would help gathering the data during the remote method call.

They'd probably had to add two global variables to the page: one would let you perform the static method calls and the other would let you perform the instance method calls. Nothing too fancy, I think... Allowing both kinds of calls would let everyone happy (including me :)) and i think that it might just be doable!

by luisabreu | 23 comment(s)
Filed under: ,
Page methods are static now
Tue, Oct 24 2006 6:34

And thank god they are! As you surelly know, in previous releases they were instance methods. From a programmer's view, the great advantage that they added was that you could get the values of the controls from within the method as if you were in a "normal" postback. On the other hand, to acieve this, you'd have to send everything back to the server side, ie, you'd have to send all the form's fields back to the server side (including the hidden ones) in order to achieve the functionalities provided by those methods. This last setence should have automatically frightened you: I mean, having to send everything back in order to get a simple value is something which is show stopper for a serious AJAX application.

for a while, i thought that the methods also updated ViewState info and that they were good when you needed to perform some calculations and update the view state but didn't want to return any html to the client (don't ask me why, but i believed that till today :) ). Guess what: i was wrong. If you change the view state during an old page method call, the view state isn't returned back to the client and when you get the next partial/full postback, you'll have the same info which was there from the previous partial or full postback. So, what are the advantages of using instance page methods? I only see one: being able to get the values of the controls on the server side.

To be honest, i don't see that as an advantage since  you're sending a lot of info to the server when you could just send the necessary values, Yes, you'd have to use Javascript and make a simple web service call to perform the necessary calculations, but what's that compared to sending everything back in order to get a value from the server side? It's funny, but there are a lot of guys which still believe that they can build an AJAX page without using Javascript (the last time I looked, the J standed for Javascript...maybe i'm wrong).

So, since page methods are static now, some are wondering how to achieve the same thing they did with the deprecated instance page methods. Well, the answer is simple: use the UpdatePanel control. I'm already seeing a lot of disbeliefe, but they can be used to in some scenarios in order to achieve a similar behavior. The new UpdatePanels are really cool (I never though i'd say this, but it's true: they are!). Using an UpdatePanel has several advantages over using the old page instance methods. The biggest one is that you can rely in having the view state field updated (don't forget that this field is also used for storing control state info!). there's one proble, though: the approach i'm presenting doesn't work when you need to call a client method after you're done with the processing (in those cases, just use a "normal" UpdatePanel)

The next example shows how you can do a remote page method call though an UpdatePanel without getting back the HTML normally generated by the panel. As you can see by running the sample, the panel contents aren't refreshed, but the viewstate info is correctly updated during a partial postback.

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void Handle(object sender, EventArgs e)
{
  ViewState["hits"] = Convert.ToInt32(ViewState["hits"]) + 1;
   //maybe store something in the db here
}
protected override void OnLoad(EventArgs e)
{
  base.OnLoad(e);
  if( !this.IsPostBack )
  {
     ViewState["hits"] = 0;
   }
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
  <form id="form1" runat="server">
      <asp:ScriptManager runat="server" id="manager" />
     <asp:UpdatePanel runat="server" ID="panel" ChildrenAsTriggers="false" UpdateMode="Conditional">
             <ContentTemplate>
                  <asp:Button runat="server" ID="bt" Text="simulate page method" OnClick="Handle" />
                   <span>Last update:</span><%= DateTime.Now.ToString( ) %>
            </ContentTemplate>
     </asp:UpdatePanel>
     <asp:Button runat="server" ID="Button1" Text="full postback" />
     <br />
     <span>hit count during postback:</span><%= ViewState["hits"].ToString( ) %>
</form>
</body>
</html>

The ChildrenAsTrigger property lets you get a partial refresh without forcing the return of the UpdatePanel's HTML back to the client side.

If you don't need to call any method on the client side when the partial postback is done, then this approach does the trick. If you need to call a client method and, say, pass it a value, then you're out of luck because currently you can only insert a javascripy statement during a partial postback by using the new static RegisterXXX methods of the ScriptManager class and those statements must be associated with a control placed inside an UpdatePanel which is being refreshed during that call. This restriction makes using the UpdatePanel  for calling page methods almost impossible and is one of the things i don't like about the new release.

by luisabreu | 1 comment(s)
Filed under: ,
How to add the value-added controls to the toolbox
Mon, Oct 23 2006 12:18

It looks like some guys are getting a hard time adding the value-added controls to the toolbox. The process is simple:

  1. (optional) create a new tab by right clicking on the toolbox and choosing "Add tab". Give it the name you want.
  2. on the tab created on 1 (or on another existing tab), right click it and pick "Choose Items..."
  3. Browse untill you see the value-added bits. they'r normally in Program Files\Microsoft ASP.NET\ASP.NET 2.0 Ajax Extensions\version
  4. Choose the Microsoft.Web.Preview dll and click OK

and that's it.

by luisabreu | with no comments
Filed under:
First impressions on AJAX Extensions
Mon, Oct 23 2006 12:13

It's been a long time since the last time i've posted here...However, i'll try to compensate the days where there hasn't been any posting with several posts about the changes in the AJAX Extensions which have been release to the public a few days ago.

My first impressions are really positive, though i still miss some of the features that have been removed. Bertrand already has several posts on the changes related with the OO extensions introduced by the team. So i think there's no need talking about them again here. btw, i'll just say that i'm glad the team removed abstract and sealed classes and that now an enum can be configured to act as flags just by adding a boolean to the second parameter passed to the registerEnum method.

Another good change is that now you only get page methods for public static methods exposed by your page. Let's face it: page methods as they were (in previous CTPs) were the worst thing that could exist. The only scenario where they had any justification was when you needed to change viewstate and get a single value back on the client side. to be honest, i never needed this and really think that we're all better now.

The UpdatePanel got lots of changes in this release too! The new ChildrenAsTriggers property still hasn't got a lot of attention but it's really cool to let you do something like this. btw, there's also lots of client side events which give you lots of chances of interacting with the page before or after a partial postback (i'll be writting about this in the next days).

You know, there had to be a problem. in this case, the value-added bits are completly broken since someone messed up with the necessary Array extensions. Currently, they're unusable. Lets hope that they solve this quickly. Stay tuned for more info on the AJAX extensions.

by luisabreu | 3 comment(s)
Filed under: ,
Why is xml-script called XML-script?
Wed, Oct 4 2006 17:34

In the last days i've been intrigued by the name the team decided to give to the new declarative style (that is, if I may call it that) used in ATLAS client programming.

well, at first sight, it really resembles XML and it stops working when you try to use invalid XML. On the other hand, there's something that has been bothering me from the start: namespaces. Let me explain with a simple example. Have you noticed how all the samples have a similar declaration to this one:

<script type="text/xml-script">
   <page xmlns:script="http://schemas......">
    ....
   </page>
</script>

The first question is: wtf? why are we using a prefix called script? Since all the elements normally presented inside the page element should be declared on the same namespace, then i really think that the script prefix should be dropped. In fact, it isn't used anywhere, so why not drop it (in fact, dropping it really didn't hurt so I've done that in my pages without even thinking about it :D). In the past, I've asked about this on the ATLAS forum and the best answer i could get was that it looked like the prefix was important for validation. That got me curious, but time went by and I never had the chance to take a look at what's was happening...at least, not until today!

Today I've built a class with my beloved ATLAS OO extensions and decided that it should be usable from xml-script. Well, it seemed so easy: I just had to implement the Sys.ITypeDescriptorProvider interface (the getDescriptor introduced by the interface method is used for defining the properties, methods and events which can be used from xml-script) and add a static parseFromMarkup method to the class. This last method is really important since it's responsible for creating an instance of the element that is being parsed. For instance, Sys._Application implements it so that there's only a Sys.Application object in the page. Sys.Component implements it so that each component that is found inside the components element originates a new Sys.Component object. After performing these steps, i decided to test my code.

The first problem was: where can I put my custom element? You see, most of the time, xml-script is used with controls and components and, to be honest, it's really great in many scenarios. In those cases, you just put everything inside the <components> element and you're ready to go. In my case, this just didn't seem right, so i decided to put an entry as a direct child of the page element. It simply didn't do anything (ie, my parseFromMarkup method simply wasn't called). I know that there are some objects (ex.: Sys.Application) which aren't components and are usable from xml-script...after searching for examples and speaking with Garbin, it was clear that the <application> element (used to represent a Sys.Application object in xml-script) is placed inside the <components> element...another wtf because Sys._Application really doesn't inherit from Sys.Component...hum, so let's try putting my object inside the <components> element...and yes, it worked.

This made me even more curious...if you think about it, there really isn't any logic in having to put my object inside the <components> section because it simply isn't a component! I may be absolutly wrong, but when I see a component section, I expect that everything inside it to be a component (or a component derived object). So i just had to check the code and the processDocumentScripts method (Sys.MarkupParser class) really tells the story. well, what does it do? It's really simple: it gets an array of  xml-script nodes and  sees if the current node is a components element or a references element. If it's none of these, then nothing happens. In other words, it's hard-coded and it only understands those elements. The <references> element uses a script loader object to load all the javascript proxies; the components' child nodes are parsed by using the parseNodes method.

If you put anything outside of those elements, you won't get an error, but it will not work either! hum...it's smeally, right? and note that I've got a cold right now and can't really smeall anything :)

ok, so I decided to peak a little more and guess what? remember the 1st code snipper I've shown? Yes, the one that has the page element as it's top element...now, let's do a simple experiment, shall we? try opening a simple page an replace that element with this one:

<script type="text/xml-script">
   <microsoftThisSucksButItStillWorks xmlns:script="http://schemas......">
    ....
   </microsoftThisSucksButItStillWorks>
</script>

And yes, we've got a touchdown...it works without any complaints whatsoever! And why is that? well, it's because the parser really doesn't interpret the top level element; it simply get's it and discards it without even checking its name. Quick, but also lets you opened to this type of hack :)

So let's recap: we've got a script prefix which really isn't used for anything; elements are only interpreted if they're placed inside the components element or inside the references element; and finally, you're really free to call whatever name you want to your top level element. That's what I call liberal XML :) (unless you also take into account the components/references element thing, where things aren't really so liberal...).

When I thought there were no more revelations, I decided to fire an old project which used an early version of the toolkit controls. the main thing about this project is that I'm just using the client portion of the controls and, therefore, I'm able to write my xml-script. Initially, I had the following:

<script type="text/xml-script">
  <page xmlns:script="http://schemas.microsoft.com/xml-script/2005" xmlns:atlascontroltoolkit="atlascontroltoolkit">
     <components>
          <label id="info">
                <behaviors>
                   <script:opacity value="0.75" />
                   <atlascontroltoolkit:alwaysVisibleControlBehavior
                       HorizontalOffset="10"
                       VerticalOffset="10"
                        HorizontalSide="Left" />
                </behaviors>
         </label>
      </components>
   </page>
</script>

And it worked great (btw, the atlascontroltoolkit value that is used as a namespace uri  was used as the default namespace value of the controls introduced by the tookit (that is, if i'm not mistaken). So, what happens if i change the namespace to test:

xmlns:atlascontroltoolkit="test"

Guess what? it still works. ok, let me say this again: it works! How about changing the prefix name: nop, it doesn't work. You get a validation error! Well, in my opinion, this behavior really sucks: that's not what namespaces are about...I should be able to change the prefix name to whatever I want and it should work assuming that my prefix points to the same uri. Though I'm not really a XML guy, I really think that this is not an acceptable behavior...specially if you think that ms xml parser is able to preform the correct validation. Speaking about validation, it would be nice to have a schema to validate the contents of xml-script.

So, it's true that xml-script must be well formed xml (which is really the only requisite for being xml) for it to get preocessed...but the namespace thing really really really (have i said enough reallys already?) sucks big time (not to speak about having to put an item inside the componets element so that it gets a chance of being correctly parsed). To me, namespaces are probably one of most important things that happened to XML. Why use this ridiculous parsing rule where you perform the validation based on the prefix name instead of using the namespace uri? This kind of behavior really makes me wonder why they have called xml-script XML-script...

by luisabreu | 5 comment(s)
Filed under:
Me...in a caterham
Mon, Oct 2 2006 14:46

Yes, today i got lucky and was able to (finally) sit inside a caterham. wow! that's all i have to say...

Img015

Img016

Img017

Img018

by luisabreu | with no comments
Filed under:
ASP.NET MVP for 2007
Sun, Oct 1 2006 13:18

Well, it looks like MS decided to renew my MVP. Thanks guys!

by luisabreu | 1 comment(s)
Filed under: