ASP.NET postback with JavaScript

Here is a complete solution

Entire form tag of the asp.net page
<form id="form1" runat="server">
    <asp:LinkButton ID="LinkButton1" runat="server" /> <%-- included to force __doPostBack javascript function to be rendered --%>

    <input type="button" id="Button45" name="Button45" onclick="javascript:__doPostBack('ButtonA','')" value="clicking this will run ButtonA.Click Event Handler" /><br /><br />
    <input type="button" id="Button46" name="Button46" onclick="javascript:__doPostBack('ButtonB','')" value="clicking this will run ButtonB.Click Event Handler" /><br /><br />

    <asp:Button runat="server" ID="ButtonA" ClientIDMode="Static" Text="ButtonA" /><br /><br />
    <asp:Button runat="server" ID="ButtonB" ClientIDMode="Static" Text="ButtonB" />
</form>
Entire Contents of the Page's Code-Behind Class

这里需要注意的是,必须给buttonA和buttonB绑定click事件,这样后面在调用theForm.submit();的时候,才会触发。

 public partial class Main : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ButtonA.Click += ButtonA_Click;
            ButtonB.Click += ButtonB_Click;
        }

        private void ButtonA_Click(object sender, EventArgs e)
        {
            Response.Write("You ran the ButtonA click event");
        }

        private void ButtonB_Click(object sender, EventArgs e)
        {
            Response.Write("You ran the ButtonB click event");
        }
    }

The LinkButton is included to ensure that the __doPostBack javascript function is rendered to the client.

Simply having Button controls will not cause this __doPostBack function to be rendered.

This function will be rendered by virtue of having a variety of controls on most ASP.NET pages, so an empty link button is typically not needed

 

将Page_Load方法改为如下

 protected void Page_Load(object sender, EventArgs e)
        {
            var value = Request.Form["__EVENTTARGET"];
            Console.WriteLine(value);

            Console.WriteLine(IsPostBack);

            ButtonA.Click += ButtonA_Click;
            ButtonB.Click += ButtonB_Click;
        }

在方法中设置断点,会发现总是page_load先触发,然后才触发click事件

 

What's going on?

Two input controls are rendered to the client:

<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
  • __EVENTTARGET receives argument 1 of __doPostBack
  • __EVENTARGUMENT receives argument 2 of __doPostBack

The __doPostBack function is rendered out like this:

第一个参数是控件名字,第二个参数是事件参数

function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}

As you can see, it assigns the values to the hidden inputs.

When the form submits / postback occurs:

  • If you provided the UniqueID of the Server-Control Button whose button-click-handler you want to run (javascript:__doPostBack('ButtonB',''), then the button click handler for that button will be run.

前台JavaScript的theForm.submit();运行后,会触发后台绑定的click事件

 

What if I don't want to run a click handler, but want to do something else instead?

You can pass whatever you want as arguments to __doPostBack

You can then analyze the hidden input values and run specific code accordingly:

通过下面的代码拿到event target,

需要注意的是通过,直接调用javascript:__doPostBack('ButtonA',''),event target才会有数值。

如果是直接点击buttonA的话,虽然也会触发ButtonA_Click,但是获取 Request.Form["__EVENTTARGET"]的时候,是空值

   private void ButtonA_Click(object sender, EventArgs e)
        {
            var value = Request.Form["__EVENTTARGET"];
            Console.WriteLine(value);
            Response.Write("You ran the ButtonA click event");
        }

 

If Request.Form("__EVENTTARGET") = "DoSomethingElse" Then
    Response.Write("Do Something else") 
End If
Other Notes
  • What if I don't know the ID of the control whose click handler I want to run?
    • If it is not acceptable to set ClientIDMode="Static", then you can do something like this: __doPostBack('<%= myclientid.UniqueID %>', '').
    • Or: __doPostBack('<%= MYBUTTON.UniqueID %>','')
    • This will inject the unique id of the control into the javascript, should you wish it

 

 

扩展阅读

Doing or Raising Postback using __doPostBack() function from Javascript in Asp.Net

Understanding the JavaScript __doPostBack Function

 

For this code to work you need to add any web server control on the form except for Button and ImageButton control (I will tell you why later in this article). 

 

__EVENTTARGET is empty on postback of button click

Just add UseSubmitBehavior="False" to your button.

https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.button.usesubmitbehavior?view=netframework-4.8

Gets or sets a value indicating whether the Button control uses the client browser's submit mechanism or the ASP.NET postback mechanism.

如果不设置这个属性,想要拦截对应的js。可以注册一个ClientScriptManager.RegisterOnSubmitStatement

 private void RegisterFormSubmit()
        {
            string script = $@"
    $.each($("".preview""), function (index, file) {{
            console.log($(file).data('data'));
       }});
    return false;
";
            var scriptManager = Page.ClientScript;
            var key = "RegisterFormSubmit";
            var type = GetType();
            if (!scriptManager.IsOnSubmitStatementRegistered(key))
            {
                scriptManager.RegisterOnSubmitStatement(type, key, script);
            }
        }

然后会在前端页面看到

<script type="text/javascript">
//<![CDATA[
function WebForm_OnSubmit() {
if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
    $.each($(".preview"), function (index, file) {
            console.log($(file).data('data'));
       });
    return false;

return true;
}