从JavaScript调用ASP.NET函数

147
我正在用ASP.NET编写一个网页。我有一些JavaScript代码,并且我有一个带有点击事件的提交按钮。
在JavaScript的点击事件中,是否可以调用我在ASP中创建的方法?

1
你应该使用一些 Ajax 库,比如:Anthem - jdecuyper
20个回答

99

如果您不想使用Ajax或任何其他方式来完成操作,只是希望进行普通的ASP.NET回传,那么以下是如何实现它(不使用任何其他库):

尽管有点棘手... :)

i. 在您的代码文件中(假设您正在使用C#和.NET 2.0或更高版本),请将以下接口添加到您的Page类中,使其看起来像:

public partial class Default : System.Web.UI.Page, IPostBackEventHandler{}

ii. 这应该通过使用 Tab-Tab 将此函数添加到您的代码文件中:

public void RaisePostBackEvent(string eventArgument) { }

iii. 在JavaScript中的onclick事件中编写以下代码:

var pageId = '<%=  Page.ClientID %>';
__doPostBack(pageId, argumentString);

这将使用从JavaScript传递的“argumentString”调用您代码文件中的“RaisePostBackEvent”方法。现在,您可以调用任何其他事件。
附注:这是“下划线-下划线-doPostBack”...而且,在该序列中不应有空格...不知何故,WMD不允许我编写后跟字符的两个下划线!

1
我正在尝试实现这个功能,但它没有正常工作。页面正在进行回发,但我的代码没有被执行。当我调试页面时,RaisePostBackEvent从未被触发。我做的一件不同的事情是,我是在用户控件中而不是在aspx页面中实现的。 - merk
它给我一个错误,说对象预期。我已经以这样的方式调用它:`window.onbeforeunload = confirmExit; //debugger; function confirmExit() { var pageId = '<%= Page.ClientID %>'; var argumentString = 'ReleaseLock'; __doPostBack(pageId, argumentString);}` - Pavitar
由于某些原因,我无法使用 onkeyup 事件使其工作。出现了“JavaScript运行时错误:'__doPostBack'未定义”。我正在使用C#和ASP.NET2.0。 - Andrew T.

62

__doPostBack() 方法运作良好。

另一个解决方案(非常巧妙的)是在您的标记中添加一个不可见的ASP按钮,并用JavaScript方法单击它。

<div style="display: none;">
   <asp:Button runat="server" ... OnClick="ButtonClickHandlerMethod" />
</div>

使用ClientID检索按钮的引用并在JavaScript中调用.click()方法。

var button = document.getElementById(/* button client id */);

button.click();

3
如果我想使用一个参数,我能从客户端获取它并在button.Click()中使用吗? - Kubi
Click方法存在吗? - Saher Ahwal
@saher 是的,但实际上是 .click(小写 c)(http://www.comptechdoc.org/independent/web/cgi/javamanual/javabutton.html) - mbillard
JavaScript 运行时错误:对象不支持属性或方法 'getElementByID',噢,也许使用 Id:D,该死的大小写敏感的垃圾。 - Ms. Nobody
@mbillard 我花了很多时间寻找一种方法来隐藏(视觉上)一个组件,后来我又搜索了如何从JavaScript调用ASP函数。 - Erick Asto Oblitas
显示剩余2条评论

18

Microsoft AJAX库可以实现这一目标。你也可以创建自己的解决方案,使用AJAX调用你自己的aspx文件(基本上)运行.NET函数。

我建议使用Microsoft AJAX库。一旦安装和引用,只需在页面加载或初始化中添加一行:

Ajax.Utility.RegisterTypeForAjax(GetType(YOURPAGECLASSNAME))

然后你可以做这样的事情:

<Ajax.AjaxMethod()> _
Public Function Get5() AS Integer
    Return 5
End Function

然后,在您的页面上可以这样调用:

PageClassName.Get5(javascriptCallbackFunction);

你的函数调用的最后一个参数必须是JavaScript回调函数,当AJAX请求返回时将执行该函数。


11
您可以使用.NET Ajax PageMethods 来异步执行此操作。请参见里 或里。

6
我认为博客文章《如何使用Ajax(jQuery)在ASP.NET页面中获取和显示SQL Server数据库数据》(链接)会对你有所帮助。

JavaScript代码

<script src="http://code.jquery.com/jquery-3.3.1.js" />
<script language="javascript" type="text/javascript">

    function GetCompanies() {
        $("#UpdatePanel").html("<div style='text-align:center; background-color:yellow; border:1px solid red; padding:3px; width:200px'>Please Wait...</div>");
        $.ajax({
            type: "POST",
            url: "Default.aspx/GetCompanies",
            data: "{}",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: OnSuccess,
            error: OnError
        });
    }

    function OnSuccess(data) {
        var TableContent = "<table border='0'>" +
                                "<tr>" +
                                    "<td>Rank</td>" +
                                    "<td>Company Name</td>" +
                                    "<td>Revenue</td>" +
                                    "<td>Industry</td>" +
                                "</tr>";
        for (var i = 0; i < data.d.length; i++) {
            TableContent += "<tr>" +
                                    "<td>"+ data.d[i].Rank +"</td>" +
                                    "<td>"+data.d[i].CompanyName+"</td>" +
                                    "<td>"+data.d[i].Revenue+"</td>" +
                                    "<td>"+data.d[i].Industry+"</td>" +
                                "</tr>";
        }
        TableContent += "</table>";

        $("#UpdatePanel").html(TableContent);
    }

    function OnError(data) {

    }
</script>

ASP.NET 服务器端函数

[WebMethod]
[ScriptMethod(ResponseFormat= ResponseFormat.Json)]
public static List<TopCompany> GetCompanies()
{
    System.Threading.Thread.Sleep(5000);
    List<TopCompany> allCompany = new List<TopCompany>();
    using (MyDatabaseEntities dc = new MyDatabaseEntities())
    {
        allCompany = dc.TopCompanies.ToList();
    }
    return allCompany;
}

4

对我而言,静态、强类型编程一直感觉很自然,因此当我不得不为我的应用程序构建基于Web的前端时,一开始我抗拒学习JavaScript(更不用说HTML和CSS)。我会尽力绕过这个问题,比如重定向到一个页面只是为了在OnLoad事件上执行操作,只要我能编写纯C#代码。

但是你会发现,如果你要处理网站,你必须开放思路,开始更多地考虑Web方向(也就是说,不要试图在服务器端或客户端做与本身职责无关的事情)。我喜欢ASP.NET WebForms并仍在使用它(以及MVC),但我会说,试图简化事物并隐藏客户端和服务器之间的分离可能会使新手困惑,并在某些时候实际上使事情变得更加困难。

我的建议是学习一些基本的JavaScript知识(如如何注册事件、检索DOM对象、操作CSS等),这样你会发现网页编程更加有趣(更不用说更容易了)。很多人提到了不同的Ajax库,但我没有看到任何实际的Ajax示例,所以接下来就是一个示例。如果您不熟悉Ajax,它只是通过异步HTTP请求刷新内容(或在您的场景中执行服务器端操作)而无需重新加载整个页面或进行完整的后台提交。

客户端:

<script type="text/javascript">
var xmlhttp = new XMLHttpRequest(); // Create object that will make the request
xmlhttp.open("GET", "http://example.org/api/service", "true"); // configure object (method, URL, async)
xmlhttp.send(); // Send request

xmlhttp.onstatereadychange = function() { // Register a function to run when the state changes, if the request has finished and the stats code is 200 (OK). Write result to <p>
    if (xmlhttp.readyState == 4 && xmlhttp.statsCode == 200) {
          document.getElementById("resultText").innerHTML = xmlhttp.responseText;
    }
};
</script>

这就是全部内容。虽然名称可能会误导,但结果也可以是纯文本或JSON,您不仅限于XML。jQuery提供了更简单的界面来进行Ajax调用(以及简化其他JavaScript任务)。
请求可以是HTTP-POST或HTTP-GET,并且不必针对网页,而是可以发布到任何监听HTTP请求的服务,例如RESTful API。ASP.NET MVC 4 Web API也可以轻松设置服务器端Web服务以处理请求。但许多人不知道您还可以将API控制器添加到Web表单项目中,并使用它们来处理此类Ajax调用。 服务器端:
public class DataController : ApiController
{
    public HttpResponseMessage<string[]> Get()
    {
        HttpResponseMessage<string[]> response = new HttpResponseMessage<string[]>(
            Repository.Get(true),
            new MediaTypeHeaderValue("application/json")
        );

        return response;
    }
}

Global.asax

然后只需在Global.asax文件中注册HTTP路由,这样ASP.NET就知道如何指导请求了。

void Application_Start(object sender, EventArgs e)
{
    RouteTable.Routes.MapHttpRoute("Service", "api/{controller}/{id}");
}

使用 AJAX 和控制器,您可以随时异步地向服务器发送请求,执行任何服务器端操作。这种组合提供了 JavaScript 的灵活性和 C# / ASP.NET 的强大功能,为访问您网站的用户提供更好的体验。不需要牺牲任何东西,您可以兼得两者的优点。 参考资料

3
微软的AJAX库可以实现这一点。您也可以创建自己的解决方案,涉及使用AJAX调用自己的aspx(基本上)脚本文件来运行.NET函数。
这个叫做AjaxPro的库是由MVP Michael Schwarz编写的。这个库不是由微软编写的。
我广泛使用了AjaxPro,它是一个非常好的库,我推荐在需要与服务器进行简单回调时使用。它与微软版本的Ajax完美配合,没有任何问题。然而,我要注意的是,由于微软使Ajax变得如此简单,只有在真正必要时才会使用它。通过将其放入更新面板中,您可以从微软获取一些非常复杂的功能,而不需要编写大量JavaScript代码。

1
我希望这篇文章能更靠近上面那篇...我浪费了几分钟的时间,试图弄清楚为什么MS文档中没有提到那个方法 :/ - Dave Swersky
1
@Dave 这就是为什么人们应该在答案下评论,而不是将评论添加到其他答案作为独特的答案。 - Charles Boyung

2

如果您想触发服务器端的事件处理程序,例如按钮单击事件,对于同步/异步两种情况都很容易。

触发控件的事件处理程序:

如果您已经在页面上添加了ScriptManager,请跳过步骤1。

  1. Add the following in your page client script section

    //<![CDATA[
    var theForm = document.forms['form1'];
    if (!theForm) {
        theForm = document.form1;
    }
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }
    //]]>
    
    1. Write you server side event handler for your control

      protected void btnSayHello_Click(object sender, EventArgs e) { Label1.Text = "Hello World..."; }

    2. Add a client function to call the server side event handler

      function SayHello() { __doPostBack("btnSayHello", ""); }

将上面代码中的“btnSayHello”替换为您控件的客户端ID。
这样做,如果您的控件位于更新面板内,页面将不会刷新。非常简单。
另外一件事要说的是:要小心客户端ID,因为它取决于您使用ClientIDMode属性定义的ID生成策略。

2
我正在尝试实现这个,但它没有正常工作。页面在提交后返回,但我的代码没有被执行。当我调试页面时,RaisePostBackEvent从未被触发。我所做的一件不同的事情是,我是在一个用户控件中而不是在aspx页面中进行此操作。
如果其他人和Merk一样遇到了问题,请参考以下解决方案:
当您拥有用户控件时,似乎您还必须在父页面中创建PostBackEventHandler。然后,您可以通过直接调用它来调用用户控件的PostBackEventHandler。请参见下面的示例:
public void RaisePostBackEvent(string _arg)
{
    UserControlID.RaisePostBackEvent(_arg);
}

其中 UserControlID 是您在父页面中嵌套标记时为用户控件指定的 ID。

注意:您还可以直接调用属于该用户控件的方法(在这种情况下,您只需要在父页面中使用 RaisePostBackEvent 处理程序):

public void RaisePostBackEvent(string _arg)
{
    UserControlID.method1();
    UserControlID.method2();
}

请开一个新的问题。您正在发布的问题已经超过5年了。 - Nico
抱歉,我会在有机会的时候尽快完成。 - davrob01

2
如果页面上没有生成 __doPostBack 函数,则需要插入一个控件来强制生成,如下所示:

<asp:Button ID="btnJavascript" runat="server" UseSubmitBehavior="false" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接