0

A pretty detailed explanation of how a postback mechanism works can be found here.

In ASP.NET the controls usually have many events. For example the LinkButton class has Click event.

The following code:

<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click" Text="LinkButton" />

is translated to this on client side:

<a id="LinkButton1" href="javascript:__doPostBack('LinkButton1','')">LinkButton</a>

As you can see, the client's code doesn't specify the event to fire or the event handler.

So my question is, how the server knows it should fire the Click event and LinkButton1_Click event handler, if the only thing it receives from the client is the component's ID (the first parameter of __doPostBack method)?

What if I wanted the component to fire a different event than Click?

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158
user107986
  • 1,461
  • 1
  • 17
  • 24
  • What event would you want to fire? Only click makes sense in the described scenario, and that's how the server knows. – Andrew Savinykh Sep 29 '15 at 07:40
  • As @zespri said, there is no other event you can hook it up to. The linkbutton also has a command-event, but both click and command -events are fired at server side when it's clicked. – Esko Sep 29 '15 at 07:43
  • In this case, yes, but if I had a custom control for which more than 1 event would make sense on client side, how would I accomplish this? Should I then pass the info about which event to fire in eventargs when calling doPostBack? – user107986 Sep 29 '15 at 07:43
  • You can use the second parameter, 'event argument' for this. – Andrew Savinykh Sep 29 '15 at 07:48

2 Answers2

1

ASP.NET Web Forms always creates a form which includes all the controls in the page. Whenever the user clicks a control in the page that triggers an event in the server, what is happening behind the scenes is that the form is being posted to the server. Instead of doing a simple POST, the post is done by the client side __doPostback function, which receives two parameters: eventTarget and eventArgument. The first has the ID of the control which triggers the postback, and the the second contains any extra information. The vañlues of these parameters are copied to two hidden fields in the form, which are posted with the rest of the form's controls

Once in the server, the values in this controls can be read to determine which event is being raised. They can be read by accessing Request["__EVENTTARGET"]; and Request["__EVENTARGUMENT"];

You can read this SO Q&A, and the linked pages, to learn more about it: How to use __doPostBack()

The ASP.NET framework simplifies the work by examining these values, and looking for a control whose ID matches the __EVENTTARGET, and implements IPostBackEventHandler. To learn more about this, you should read: Server Event Handling in ASP.NET Web Forms Pagess.

Apart from the postback events, there are also the "change events". This events are raised by comparing the original value of the control, when it was sent to the browser, and the value posted in that control. For example, a TextBox has a TextChanged event. To determine if the event has to trigger, the server extrat the original value of the control from the view state (a hidden field which was sent to the browser, with the state of all the rednered controls, including their values) and compares it with the posted value, triggering the event if necessary. In a similar fashion to IPostBackEventHandler, implementing IPostBackDataHandler will allow the framework to look for controls which need to handle this kind of events.

You should also understand the page lifecycle to know what happens in the server, and in which order: When to wire up event handlers asp.net

Community
  • 1
  • 1
JotaBe
  • 38,030
  • 8
  • 98
  • 117
  • Thanks for a great overview of the whole mechanism! Actually, I was asking what if a single custom control can raise more than 1 event on client side. The client code only sends the identifier of the control that fired an event without specifying what event happened (because for probably all standard controls a client can fire just 1 event in his browser). So for example, the events on a button may be clicking on it, or placing mouse cursor on it. The only way I can think of is to send the info about which event occured in __EVENTARGUMENT. – user107986 Sep 29 '15 at 09:11
  • Yes, zespri's answer explains the standar way to do it. It's related to the `IpostBackEventHandler` implementation: the method `RaisePostBackEvent` is invoked by the framework, because the Event Target matches this control. And the Event Argument `Clack` is passed to this method in the `eventArgument`. There are a lot of server controls that have several different events. The grid, or the controls inside a grid, are good examples of this. I know my answer is too extensive, but if you have the time to read it, you'll have a much more clear view of how ASP.NET Web Forms works. – JotaBe Sep 29 '15 at 09:18
0

The example I'm going to give is useless for any practical purposes, but then, you have not indicated any of your practical purposes, so I think it's a fair game. I hope that it will show the approach to you and then you will be able to modify and extend it you suit your needs.

public class LinkButtonWithClack : LinkButton
{
    private const string ClackMarker = "Clack";
    public bool ClackMode { get; set; }
    protected override PostBackOptions GetPostBackOptions()
    {
        var options = base.GetPostBackOptions();
        if (ClackMode)
        {
            // That's how you specify the event argument for __EVENTARGUMENT
            options.Argument = ClackMarker;
        }
        return options;
    }

    public event EventHandler Clack;

    protected override void RaisePostBackEvent(string eventArgument)
    {
        if (eventArgument == ClackMarker)
        {
            this.OnClack(EventArgs.Empty);
        }
        else
        {
            base.RaisePostBackEvent(eventArgument);
        }          
    }

    protected virtual void OnClack(EventArgs e)
    {
        if (Clack != null)
        {
            Clack(this, e);
        }
    }
}

In this example you are creating a new server control, LinkButtonWithClack. This control inherits from the LinkButton server control and has an additional event, Clack. If you set property ClackMode to true it will start generate Clacks instead of Clicks.

Whether and event a click or clack is communicated by the second argument to doPostBack:

<a id="MainContent_LinkButtonWithClack1" 
href="javascript:__doPostBack(&#39;ctl00$MainContent$LinkButtonWithClack1&#39;,&#39;Clack&#39;)">

Server then examines the contents of it and calls the Clack event if it sees "Clack".

Of course you are unlikely to derive from LinkButton, I'm only using it as an example because you did. You likely will be implementing a server control from scratch. When doing so, please bring all your knowledge on server control creation, or read up if you don't have one - you will need it.

As a side-note, this day it's easier to find help with asp.net mvc than with webforms, since the latter is older and less and less people are using it. If you have any say in technology choice at all I'd choose asp.net mvc over webforms for almost anything.

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158