不同浏览器中的LinkBut​​ton PageMethod行为不一致

Lit*_*les -2 javascript c# ajax cross-browser webmethod

我在一个执行回发的页面上有一个LinkBut​​ton,但也有一个onClientClick事件.我们的想法是在后台设置一些会话变量来自客户端数据(不要问).

我在Web方法中设置了一个断点来逐步执行代码,我们遇到的是,根据浏览器的不同,PageMethods可能会返回成功消息,失败消息或根本没有消息.此外,无论PageMethods结果如何,都可以调用或不调用Web方法.

这是一个方便的结果小图表:

Browser          PageMethods    WebMethod
--------------   -------------  --------------------
IE 8, 9, 10      Success        Called successfully
Safari 5.1.7     Failure        *Never called*
Firefox 25.0.1   *Neither*      Called successfully
Chrome v31       Failure        Called successfully
Run Code Online (Sandbox Code Playgroud)

这是四种不同的浏览器,以及四种不同的结果.

我已经尝试在服务器端和客户端代码中生成具有相同效果的链接按钮,甚至没有在WebMethod中设置会话变量,结果相同.

可以使用以下简单代码重现代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script type="text/javascript">

    function doStuff() {
        var a = 'a';
        var b = 'b';

        PageMethods.doStuffWebMethod(a, b, doStuffSuccess, doStuffFail);
    }

    function doStuffSuccess() {
        alert(Success!');
    }
    function doStuffFail() {
        alert(Failure!');
    }

</script>

<html>
    <body style="background-color:#f3f4f6;" >

        <form runat="server" name="mainForm" id="mainForm" action="Test.aspx">

            <asp:ScriptManager ID="ScriptManager1"  EnablePageMethods="true" runat="server"></asp:ScriptManager>

            <asp:LinkButton runat="server" CausesValidation="false" OnClientClick="doStuff();">Do stuff!</asp:LinkButton>

        </form>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

和

protected void Page_Load(object sender, EventArgs e)
{
    LinkButton lbAdd = new LinkButton();
    lbAdd.Text = "Web method test";
    lbAdd.CausesValidation = false;
    lbAdd.OnClientClick = "doStuff();";
    mainForm.Controls.Add(lbAdd);
}

[WebMethod]
public static void doStuffWebMethod(string a, string b)
{
    try
    {
        //System.Web.HttpContext.Current.Session["a"] = a;
        //System.Web.HttpContext.Current.Session["b"] = b;
        string x = a + b;
    }
    catch (Exception ex)
    {
        //
    }
}
Run Code Online (Sandbox Code Playgroud)

问题:

为什么我的Web方法在Safari中失败,并在三个其他浏览器中给我三个不同的返回消息之一?

如何更改此代码以使其在提到的浏览器中工作?

Han*_*ans 5

调用您的Web方法失败的原因是因为您没有取消您的回发LinkButton.您必须从OnClientClick事件返回false才能取消回发.下面的代码应该修复它:

function doStuff() {
  var a = 'a';
  var b = 'b';

  PageMethods.doStuffWebMethod(a, b, doStuffSuccess, doStuffFail);
  return false; // Cancel postback.
}

function doStuffSuccess() {
  alert('Success!');
}

function doStuffFail() {
  alert('Failure!');
}

<asp:LinkButton ID="mybutton"  runat="server" CausesValidation="false" OnClientClick="return doStuff();">Do stuff!</asp:LinkButton>
Run Code Online (Sandbox Code Playgroud)

有关取消浏览器默认行为(回发)的更复杂的解决方案,请查看以下stackoverflow问题和答案.

您为不同的浏览器获得不同结果的原因可能是由于浏览器供应商的不同实现.但我不确定这一点.

您还可以通过创建网络协议跟踪来验证此行为(在Google Chrome浏览器中按F12并切换到网络选项卡).

如果您没有从doStuff()方法返回false,则为协议:

  1. doStuffWebMethod调用页面方法.然后你会得到JavaScript消息框.(HTTP POST)
  2. 您的WebForm.aspx是请求的.(HTTP POST)
  3. 然后请求WebResource.axd和ScriptResource.axd.(HTTP GET)

数字2和3.表示在页面方法请求之后执行回发.

如果你从doStuff()方法返回false,该协议:

  1. 仅doStuffWebMethod调用页面方法.(HTTP POST)

第二条跟踪清楚地表明没有回发执行.

如果您希望LinkBut​​ton发生回发,那么您可以在页面方法返回后使用__doPostBack()方法在JavaScript成功处理程序中手动触发回发:

function doStuffSuccess() {
  alert('Success!');

  __doPostBack('<%= mybutton.UniqueID %>', '');  // trigger the postback.
}
Run Code Online (Sandbox Code Playgroud)