简体   繁体   English

如何从 ajax、asp.net webforms 调用非静态方法

[英]How to call non static method from ajax, asp.net webforms

in the template I have set and interval every 60 seconds to call backend method to update something in the page在我设置的模板中,每隔 60 秒调用一次后端方法来更新页面中的内容

           setInterval(function () {
                $.ajax({
                    url: 'CameraDashboard.aspx/LoadNotifications',
                    type: 'POST',
                    success: function () {
                        console.log('success')
                    },
                    error: function () {
                        console.log('error')
                    }
                })
            }, 60000);

in the code behind在后面的代码中

    [WebMethod]
    protected void LoadNotifications()
    {
          some code ...
    }

the response is always server error响应始终是服务器错误

I tried to use static method using this method but also get error of instantiating object to use this mtheod我尝试使用此方法使用静态方法,但也得到了实例化对象以使用此 mtheod 的错误

When you do a ajax call, it should work.当您进行 ajax 调用时,它应该可以工作。 So, we have to fix the error first.所以,我们必须先修复错误。

Once that is done, then we have to address the 2nd huge issue:完成后,我们必须解决第二个大问题:

An ajax call or web method on a web page is a "static" member of that class.网页上的 ajax 调用或 Web 方法是该类的“静态”成员。 Since there is no post-back, then ZERO update of the page controls can occur.由于没有回发,因此可能会发生页面控件的零更新。 Since no post-back has occurred, then any and all controls on the web page of course cannot be modified, nor are they available in the code behind for that web method.由于没有发生回发,因此网页上的任何和所有控件当然都不能修改,也不能在该 Web 方法背后的代码中使用。 Keep in mind that ALSO the viewstate is not available at this point in time either (session() is available however).请记住,此时视图状态也不可用(但是 session() 可用)。

So while the ajax call and the web method can be on (and in) the same web page, that web method cannot modify or change controls on the page, since no post-back has occured.因此,虽然 ajax 调用和 web 方法可以在(和)同一个网页上,但该 web 方法不能修改或更改页面上的控件,因为没有发生回发。

Possible solutions:可能的解决方案:

Have the ajax call return the values you want, and then the js code can update and modify and set the controls on the web page.让ajax调用返回你想要的值,然后js代码就可以更新修改和设置网页上的控件了。

Or, you can drop in a asp.net timer, and put the controls (and timer) inside of a update panel.或者,您可以放入一个 asp.net 计时器,并将控件(和计时器)放在更新面板中。 This will result in what we call a partial post-back, and ONLY that part of the web page (inside the update panel) will be set to the server, and thus as a result only updated on the web page.这将导致我们称之为部分回发,并且只有网页的那部分(在更新面板内)将设置为服务器,因此仅在网页上更新。

It is of course significantly less work to use a update panel, since then you don't have to write any client side (js) code, and the whole process is wired up automatic for you.当然,使用更新面板的工作量要少得多,因为那时您不必编写任何客户端 (js) 代码,整个过程都是自动为您连接起来的。

Ok, with the above crystal clear in our minds?好的,上面的内容在我们脑海中一清二楚?

The web method as noted can be placed in the same web page.如上所述的网络方法可以放在同一个网页中。 You do not need say for example to create a seperate web page (ascx), and put your web methods into that seperate page.例如,您不需要说创建一个单独的网页 (ascx),并将您的网络方法放入该单独的页面。 however, the results are quite much the same, since as noted, without a post-back, then no update of controls, or even reading/grabbing/using/seeing controls on the web page can occur in that web method, and the reason as noted is the web page still remains sitting on the users desktop.但是,结果几乎相同,因为如前所述,如果没有回发,则不会更新控件,甚至不会在该 Web 方法中发生在网页上的读取/抓取/使用/查看控件,以及原因如前所述,网页仍然保留在用户桌面上。

If you REALLY need the web method to update some controls on the page, then as noted, have the js client code update such controls, or as noted, dump the ajax call, and introduce a update panel.如果您真的需要 web 方法来更新页面上的某些控件,那么如前所述,让 js 客户端代码更新此类控件,或者如前所述,转储 ajax 调用并引入更新面板。 The results will be quite much the same.结果将几乎相同。 (to be fair, the ajax call is somewhat "lighter" in terms of payload, since the update panel DOES send the viewstate on updates. (公平地说,ajax 调用在负载方面有点“轻量级”,因为更新面板确实会发送更新时的视图状态。

so, lets do this ajax call.所以,让我们做这个 ajax 调用。

So, our markup - first name, last name, and then we call a method to combine the two into a full name (our web method).所以,我们的标记——名字、姓氏,然后我们调用一个方法将两者组合成一个全名(我们的 web 方法)。

So, this markup:所以,这个标记:

        Enter First Name: <asp:TextBox ID="txtFirst" runat="server" ClientIDMode="Static"></asp:TextBox>
        <br />

        Enter First Name: <asp:TextBox ID="txtLast" runat="server" ClientIDMode="Static"></asp:TextBox>

        <br />
        <br />
        <asp:Button ID="Button1" runat="server" Text="combine first and last name"
            OnClientClick="mycombine();return false"
            />
        <br />
        <br />
        Result of ajax call <asp:TextBox ID="txtFullName" runat="server" ClientIDMode="Static"></asp:TextBox>


        <script>

            function mycombine() {

                MyFirstName = $("#txtFirst").val()
                MyLastName = $("#txtLast").val()
                
                $.ajax({
                    type: "POST",
                    url: "AjaxTest2.aspx/CombineName",
                    data: JSON.stringify({ FirstName: MyFirstName, LastName: MyLastName}),
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                        success: function (myresult) {
                        // put result of method call into txtResult
                        // ajax data is ALWAYS ".d" - its a asp.net thing!!!
                        $("#txtFullName").val(myresult.d)
                    },
                    error: function (xhr, status, error) {
                        var errorMessage = xhr.status + ': ' + xhr.statusText
                        alert('Error - ' + errorMessage)
                    }
                });
            }

        </script>

And our code behind:而我们背后的代码:

note: using System.Web.Services;注意:使用 System.Web.Services;

public partial class AjaxTest2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    
    [WebMethod()]
    public static string CombineName(string FirstName, string LastName)
    {
        string MyResult = "";

        MyResult = FirstName + " " + LastName;

        return MyResult;
    }

So, when we run, we get this:所以,当我们运行时,我们会得到:

在此处输入图像描述

So, depending on what you want to update on the page, either the above ajax call, or we can use a update panel.因此,根据您要在页面上更新的内容,可以使用上述 ajax 调用,也可以使用更新面板。

We could do above with a update panel.我们可以在上面使用更新面板。 You also not see and experience a full page post-back, and it is a whole lot less work.您也不会看到和体验一整页的回发,而且工作量要少得多。 It really comes down to what you want to do.这真的取决于你想做什么。

but, do keep in mind in above:但是,请记住上面的内容:

The web method is considered a static member - it really does not have use of any controls on the page - since there is no post-back, and thus you have to mark the web method as "public static". web 方法被认为是静态成员 - 它实际上没有使用页面上的任何控件 - 因为没有回发,因此您必须将 web 方法标记为“公共静态”。 And as such, then it can't see, get, grab, view or use controls on the page, and no use of viewstate is also avaialble.因此,它无法查看、获取、抓取、查看或使用页面上的控件,也无法使用 viewstate。 So, any update of the page will have to be passed back, and done client side.因此,页面的任何更新都必须传回,并在客户端完成。

Of course, the other way is the simple use of a update panel, and we would simple drop all 3 text box, the button inside of the update panel.当然,另一种方式是简单地使用更新面板,我们将所有 3 个文本框,即更新面板内部的按钮简单地放下。 Drop in a script manager, and thus no client side js code would have to be written.放入脚本管理器,因此无需编写客户端 js 代码。

Try both - see which you like.尝试两者 - 看看你喜欢哪个。

so, the lazy bones way?那么,懒骨头的方式?

Lets do this with a update panel.让我们使用更新面板来做到这一点。

So, our markup is now this:所以,我们的标记现在是这样的:

        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
            Enter First Name: <asp:TextBox ID="txtFirst" runat="server" ClientIDMode="Static"></asp:TextBox>
            <br />

            Enter First Name: <asp:TextBox ID="txtLast" runat="server" ClientIDMode="Static"></asp:TextBox>

            <br />
            <br />
            <asp:Button ID="Button1" runat="server" Text="combine first and last name"

                OnClick="Button1_Click"
                />
            <br />
            <br />
            Result of ajax call <asp:TextBox ID="txtFullName" runat="server" ClientIDMode="Static"></asp:TextBox>
            </ContentTemplate>
        </asp:UpdatePanel>

Note the button click - it now a plane jane server side event.请注意按钮单击 - 它现在是平面简服务器端事件。

And our code behind now becomes this:而我们后面的代码现在变成了这样:

public partial class AjaxTest2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    

    protected void Button1_Click(object sender, EventArgs e)
    {
        txtFullName.Text = txtFirst.Text + " " + txtLast.Text;
    }

And the results are the same as the first example.结果与第一个示例相同。

Try both.尝试两者。 If you need a timer, then drop one of those in the update panel.如果您需要计时器,请将其中一个放在更新面板中。

But, to be 100% clear?但是,要 100% 清楚吗? You can't call a non static method, since the page is still sitting on the client side in the browser - there are no non static methods you can run against the web page, since the web page is in fact NOT loaded nor avaialble at that point in time - you ONLY get to call that local routine, and it really does not nor can not know anything about the web page, and especally the "DOM" of that page - it not been posted to the server.您不能调用非静态方法,因为页面仍然位于浏览器的客户端 - 没有可以对网页运行的非静态方法,因为网页实际上没有加载或可用那个时间点——你只能调用那个本地例程,它真的不知道也不能知道关于网页的任何事情,尤其是那个页面的“DOM”——它没有被发布到服务器上。

As noted, you can pass to the web method the values/controls on the page, have the web method do whatever, and then return a value, and then that returned value can update controls (as my first example shows).如前所述,您可以将页面上的值/控件传递给 web 方法,让 web 方法执行任何操作,然后返回一个值,然后该返回的值可以更新控件(如我的第一个示例所示)。

I mean, we could say want to have a text box.我的意思是,我们可以说想要一个文本框。 You enter number of seconds, and then hit a start button.您输入秒数,然后点击开始按钮。 You can do this 100% client side (js) would be fine.你可以做到这一点 100% 客户端 (js) 就可以了。

Or, you could again use the udpate panel.或者,您可以再次使用更新面板。

Say, like this:说,像这样:

        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <h3>Enter seconds into box</h3>
                <asp:TextBox ID="txtSeconds" runat="server" ></asp:TextBox>
            <br />

                <asp:Button ID="cmdStart" runat="server" Text="Start count down" OnClick="cmdStart_Click" />

                <asp:Timer ID="Timer1" runat="server" Interval="1000" Enabled="False" OnTick="Timer1_Tick"></asp:Timer>

            </ContentTemplate>
        </asp:UpdatePanel>

So, you enter a value into the text box, and hit start.因此,您在文本框中输入一个值,然后点击开始。 It will count down seconds from that value you entered.它会从您输入的值开始倒计时。

Code behind will be this:后面的代码是这样的:

    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void cmdStart_Click(object sender, EventArgs e)
    {
        Timer1.Enabled = true;

    }
    protected void Timer1_Tick(object sender, EventArgs e)
    {
        int MySeconds = Convert.ToInt32(txtSeconds.Text);
        MySeconds -= 1;

        txtSeconds.Text = MySeconds.ToString();

        if (MySeconds <= 0)
        {
            Timer1.Enabled = false;
        }
    }
    

but again, if you doing a ajax call, there is NOT any instance of the class in existnce on the server side.但同样,如果您进行 ajax 调用,则服务器端不存在该类的任何实例。 It is out of scope.它超出了范围。 The server does not keep or know or have a instance of the page class in memory.服务器不会在内存中保存或知道或拥有页面类的实例。 After the page has been sent to the browser side, the server does NOT keep that page class in memory - hence there are no methods of the page that you can call that would be of any use - except for static methods.在页面被发送到浏览器端之后,服务器不会将该页面类保存在内存中——因此,除了静态方法之外,没有任何可以调用的页面方法。 This is not any different then have a code module with a class in it, and you want to call + use that class, but a instance of that class is NOT in existence anymore.这与有一个包含类的代码模块没有什么不同,并且您想调用 + 使用该类,但是该类的实例不再存在。 I mean, in your code, you could create a NEW instance of the page class, but it would not have any values nor reflect the web page that is JUST sitting on their users desktop in the browser.我的意思是,在您的代码中,您可以创建页面类的新实例,但它不会有任何值,也不会反映仅位于浏览器用户桌面上的网页。

So, just to be clear?所以,只是为了清楚吗? If you going to call a method of a class - in this case the page class, then an instance of it has to exist.如果你要调用一个类的方法——在这种情况下是页面类,那么它的一个实例必须存在。 Since it does not exist, then you limited to using static methods of that page class, or you live with a post-back which of course then creates a instance of that page class.由于它不存在,因此您仅限于使用该页面类的静态方法,或者您使用回发,这当然会创建该页面类的实例。 this concept of a "round trip", and the page class ALWAYS going out of scope is a basic requirement and knowledge you need when writing asp.net applications.这种“往返”的概念和页面类总是超出范围是编写 asp.net 应用程序时需要的基本要求和知识。

Given your requirement to update controls on the web page, then probably a update panel is your path of least efforts.鉴于您需要更新网页上的控件,那么更新面板可能是您最省力的途径。 The results are "almost" as good as wiring up say ajax calls + web methods, but is a boatload less work.结果“几乎”和连接起来说 ajax 调用 + web 方法一样好,但是工作量更少。

I believe the error is coming from the access modifier.我相信错误来自访问修饰符。

The protected access modifier means that the type or member can be accessed only by code in the same class, or in a class that is derived from that class. protected访问修饰符意味着该类型或成员只能由同一类或从该类派生的类中的代码访问。

Try to write public instead.尝试改为写public

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM